Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 22 Jun 2012 06:39:29 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r237431 - in head/sys: kern sys
Message-ID:  <201206220639.q5M6dTrD061502@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Fri Jun 22 06:39:28 2012
New Revision: 237431
URL: http://svn.freebsd.org/changeset/base/237431

Log:
  Enchance the shared page chunk allocator.
  
  Do not rely on the busy state of the page from which we allocate the
  chunk, to protect allocator state. Use statically allocated sx lock
  instead.
  
  Provide more flexible KPI. In particular, allow to allocate chunk
  without providing initial data, and allow writes into existing
  allocation. Allow to get an sf buf which temporary maps the chunk, to
  allow sequential updates to shared page content without unmapping in
  between.
  
  Reviewed by:	jhb
  Tested by:	flo
  MFC after:	1 month

Modified:
  head/sys/kern/kern_exec.c
  head/sys/sys/sysent.h

Modified: head/sys/kern/kern_exec.c
==============================================================================
--- head/sys/kern/kern_exec.c	Fri Jun 22 06:38:31 2012	(r237430)
+++ head/sys/kern/kern_exec.c	Fri Jun 22 06:39:28 2012	(r237431)
@@ -1512,33 +1512,81 @@ exec_unregister(execsw_arg)
 	return (0);
 }
 
+static struct sx shared_page_alloc_sx;
 static vm_object_t shared_page_obj;
 static int shared_page_free;
 
-int
-shared_page_fill(int size, int align, const char *data)
+struct sf_buf *
+shared_page_write_start(int base)
 {
 	vm_page_t m;
 	struct sf_buf *s;
+
+	VM_OBJECT_LOCK(shared_page_obj);
+	m = vm_page_grab(shared_page_obj, OFF_TO_IDX(base), VM_ALLOC_RETRY);
+	VM_OBJECT_UNLOCK(shared_page_obj);
+	s = sf_buf_alloc(m, SFB_DEFAULT);
+	return (s);
+}
+
+void
+shared_page_write_end(struct sf_buf *sf)
+{
+	vm_page_t m;
+
+	m = sf_buf_page(sf);
+	sf_buf_free(sf);
+	VM_OBJECT_LOCK(shared_page_obj);
+	vm_page_wakeup(m);
+	VM_OBJECT_UNLOCK(shared_page_obj);
+}
+
+void
+shared_page_write(int base, int size, const void *data)
+{
+	struct sf_buf *sf;
 	vm_offset_t sk;
+
+	sf = shared_page_write_start(base);
+	sk = sf_buf_kva(sf);
+	bcopy(data, (void *)(sk + (base & PAGE_MASK)), size);
+	shared_page_write_end(sf);
+}
+
+static int
+shared_page_alloc_locked(int size, int align)
+{
 	int res;
 
-	VM_OBJECT_LOCK(shared_page_obj);
-	m = vm_page_grab(shared_page_obj, 0, VM_ALLOC_RETRY);
 	res = roundup(shared_page_free, align);
 	if (res + size >= IDX_TO_OFF(shared_page_obj->size))
 		res = -1;
-	else {
-		VM_OBJECT_UNLOCK(shared_page_obj);
-		s = sf_buf_alloc(m, SFB_DEFAULT);
-		sk = sf_buf_kva(s);
-		bcopy(data, (void *)(sk + res), size);
+	else
 		shared_page_free = res + size;
-		sf_buf_free(s);
-		VM_OBJECT_LOCK(shared_page_obj);
-	}
-	vm_page_wakeup(m);
-	VM_OBJECT_UNLOCK(shared_page_obj);
+	return (res);
+}
+
+int
+shared_page_alloc(int size, int align)
+{
+	int res;
+
+	sx_xlock(&shared_page_alloc_sx);
+	res = shared_page_alloc_locked(size, align);
+	sx_xunlock(&shared_page_alloc_sx);
+	return (res);
+}
+
+int
+shared_page_fill(int size, int align, const void *data)
+{
+	int res;
+
+	sx_xlock(&shared_page_alloc_sx);
+	res = shared_page_alloc_locked(size, align);
+	if (res != -1)
+		shared_page_write(res, size, data);
+	sx_xunlock(&shared_page_alloc_sx);
 	return (res);
 }
 
@@ -1547,6 +1595,7 @@ shared_page_init(void *dummy __unused)
 {
 	vm_page_t m;
 
+	sx_init(&shared_page_alloc_sx, "shpsx");
 	shared_page_obj = vm_pager_allocate(OBJT_PHYS, 0, PAGE_SIZE,
 	    VM_PROT_DEFAULT, 0, NULL);
 	VM_OBJECT_LOCK(shared_page_obj);

Modified: head/sys/sys/sysent.h
==============================================================================
--- head/sys/sys/sysent.h	Fri Jun 22 06:38:31 2012	(r237430)
+++ head/sys/sys/sysent.h	Fri Jun 22 06:39:28 2012	(r237431)
@@ -256,8 +256,13 @@ int	lkmressys(struct thread *, struct no
 int	syscall_thread_enter(struct thread *td, struct sysent *se);
 void	syscall_thread_exit(struct thread *td, struct sysent *se);
 
-int shared_page_fill(int size, int align, const char *data);
+struct sf_buf;
+int shared_page_alloc(int size, int align);
+int shared_page_fill(int size, int align, const void *data);
+void shared_page_write(int base, int size, const void *data);
 void exec_sysvec_init(void *param);
+struct sf_buf *shared_page_write_start(int base);
+void shared_page_write_end(struct sf_buf *sf);
 
 #define INIT_SYSENTVEC(name, sv)					\
     SYSINIT(name, SI_SUB_EXEC, SI_ORDER_ANY,				\



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201206220639.q5M6dTrD061502>