From aa5ef359fe07ce4d727334976d2f7b30ce047e10 Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Thu, 7 Jun 2007 23:14:29 +0000 Subject: [PATCH] Entirely remove exec_map from the kernel. Use the new vm_fault_object_page() for the data/bss special case in the elf loader, and use the objcache to cache arguments for exec. This in turn removes nearly all of the SMP page invalidation IPIs that occur during fork/exec/exit/wait sequences by virtue of not needing to map and unmap so much KVM. --- sys/kern/imgact_elf.c | 32 +++++++++++++------------------- sys/kern/kern_exec.c | 26 ++++++++++++++++++++++---- sys/platform/pc32/i386/machdep.c | 4 +--- sys/platform/vkernel/i386/autoconf.c | 4 +--- sys/vm/vm_kern.c | 3 +-- sys/vm/vm_kern.h | 3 +-- 6 files changed, 39 insertions(+), 33 deletions(-) diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index ae219a2999..b70b580f36 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -27,7 +27,7 @@ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD: src/sys/kern/imgact_elf.c,v 1.73.2.13 2002/12/28 19:49:41 dillon Exp $ - * $DragonFly: src/sys/kern/imgact_elf.c,v 1.50 2007/02/25 23:17:12 corecode Exp $ + * $DragonFly: src/sys/kern/imgact_elf.c,v 1.51 2007/06/07 23:14:25 dillon Exp $ */ #include @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -260,7 +261,6 @@ elf_load_section(struct proc *p, struct vmspace *vmspace, struct vnode *vp, size_t copy_len; vm_object_t object; vm_offset_t file_addr; - vm_offset_t data_buf = 0; object = vp->v_object; error = 0; @@ -352,24 +352,18 @@ elf_load_section(struct proc *p, struct vmspace *vmspace, struct vnode *vp, } if (copy_len != 0) { - vm_object_reference(object); - rv = vm_map_find(&exec_map, - object, - trunc_page(offset + filsz), - &data_buf, - PAGE_SIZE, - TRUE, - VM_MAPTYPE_NORMAL, - VM_PROT_READ, VM_PROT_ALL, - MAP_COPY_ON_WRITE | MAP_PREFAULT_PARTIAL); - if (rv != KERN_SUCCESS) { - vm_object_deallocate(object); - return EINVAL; + vm_page_t m; + struct sf_buf *sf; + + m = vm_fault_object_page(object, trunc_page(offset + filsz), + VM_PROT_READ, 0, &error); + if (m) { + sf = sf_buf_alloc(m, SFB_CPUPRIVATE); + error = copyout((caddr_t)sf_buf_kva(sf), + (caddr_t)map_addr, copy_len); + sf_buf_free(sf); + vm_page_unhold(m); } - - /* send the page fragment to user space */ - error = copyout((caddr_t)data_buf, (caddr_t)map_addr, copy_len); - vm_map_remove(&exec_map, data_buf, data_buf + PAGE_SIZE); if (error) { return (error); } diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 31781bc032..b402f8c9d5 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/kern/kern_exec.c,v 1.107.2.15 2002/07/30 15:40:46 nectar Exp $ - * $DragonFly: src/sys/kern/kern_exec.c,v 1.56 2007/04/29 18:25:34 dillon Exp $ + * $DragonFly: src/sys/kern/kern_exec.c,v 1.57 2007/06/07 23:14:25 dillon Exp $ */ #include @@ -72,6 +72,7 @@ #include MALLOC_DEFINE(M_PARGS, "proc-args", "Process arguments"); +MALLOC_DEFINE(M_EXECARGS, "exec-args", "Exec arguments"); static register_t *exec_copyout_strings (struct image_params *); @@ -96,6 +97,23 @@ SYSCTL_INT(_kern, OID_AUTO, debug_execve_args, CTLFLAG_RW, &debug_execve_args, 0, ""); /* + * Exec arguments object cache + */ +static struct objcache *exec_objcache; + +static +void +exec_objcache_init(void *arg __unused) +{ + exec_objcache = objcache_create_mbacked( + M_EXECARGS, PATH_MAX + ARG_MAX, + 16, /* up to this many objects */ + 2, /* minimal magazine capacity */ + NULL, NULL, NULL); +} +SYSINIT(exec_objcache, SI_BOOT2_MACHDEP, SI_ORDER_ANY, exec_objcache_init, 0); + +/* * stackgap_random specifies if the stackgap should have a random size added * to it. It must be a power of 2. If non-zero, the stack gap will be * calculated as: ALIGN(karc4random() & (stackgap_random - 1)). @@ -688,7 +706,8 @@ exec_copyin_args(struct image_args *args, char *fname, size_t length; bzero(args, sizeof(*args)); - args->buf = (char *) kmem_alloc_wait(&exec_map, PATH_MAX + ARG_MAX); + + args->buf = objcache_get(exec_objcache, M_WAITOK); if (args->buf == NULL) return (ENOMEM); args->begin_argv = args->buf; @@ -779,8 +798,7 @@ void exec_free_args(struct image_args *args) { if (args->buf) { - kmem_free_wakeup(&exec_map, - (vm_offset_t)args->buf, PATH_MAX + ARG_MAX); + objcache_put(exec_objcache, args->buf); args->buf = NULL; } } diff --git a/sys/platform/pc32/i386/machdep.c b/sys/platform/pc32/i386/machdep.c index ba2f5c8d63..840fa66de9 100644 --- a/sys/platform/pc32/i386/machdep.c +++ b/sys/platform/pc32/i386/machdep.c @@ -36,7 +36,7 @@ * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 * $FreeBSD: src/sys/i386/i386/machdep.c,v 1.385.2.30 2003/05/31 08:48:05 alc Exp $ - * $DragonFly: src/sys/platform/pc32/i386/machdep.c,v 1.121 2007/05/17 21:08:49 dillon Exp $ + * $DragonFly: src/sys/platform/pc32/i386/machdep.c,v 1.122 2007/06/07 23:14:26 dillon Exp $ */ #include "use_apm.h" @@ -372,8 +372,6 @@ again: kmem_suballoc(&clean_map, &pager_map, &pager_sva, &pager_eva, (nswbuf*MAXPHYS) + pager_map_size); pager_map.system_map = 1; - kmem_suballoc(&kernel_map, &exec_map, &minaddr, &maxaddr, - (16*(ARG_MAX+(PAGE_SIZE*3)))); #if defined(USERCONFIG) userconfig(); diff --git a/sys/platform/vkernel/i386/autoconf.c b/sys/platform/vkernel/i386/autoconf.c index 3cac527b2a..1115c90e3d 100644 --- a/sys/platform/vkernel/i386/autoconf.c +++ b/sys/platform/vkernel/i386/autoconf.c @@ -35,7 +35,7 @@ * * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91 * $FreeBSD: src/sys/i386/i386/autoconf.c,v 1.146.2.2 2001/06/07 06:05:58 dd Exp $ - * $DragonFly: src/sys/platform/vkernel/i386/autoconf.c,v 1.10 2007/05/08 02:31:43 dillon Exp $ + * $DragonFly: src/sys/platform/vkernel/i386/autoconf.c,v 1.11 2007/06/07 23:14:28 dillon Exp $ */ /* @@ -175,8 +175,6 @@ cpu_startup(void *dummy) kmem_suballoc(&clean_map, &pager_map, &pager_sva, &pager_eva, (nswbuf*MAXPHYS) + pager_map_size); pager_map.system_map = 1; - kmem_suballoc(&kernel_map, &exec_map, &minaddr, &maxaddr, - (16*(ARG_MAX+(PAGE_SIZE*3)))); #if defined(USERCONFIG) userconfig(); cninit(); /* the preferred console may have changed */ diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c index d0603cd4bb..a34711dd69 100644 --- a/sys/vm/vm_kern.c +++ b/sys/vm/vm_kern.c @@ -62,7 +62,7 @@ * rights to redistribute these changes. * * $FreeBSD: src/sys/vm/vm_kern.c,v 1.61.2.2 2002/03/12 18:25:26 tegge Exp $ - * $DragonFly: src/sys/vm/vm_kern.c,v 1.28 2007/01/02 05:52:31 dillon Exp $ + * $DragonFly: src/sys/vm/vm_kern.c,v 1.29 2007/06/07 23:14:29 dillon Exp $ */ /* @@ -88,7 +88,6 @@ #include struct vm_map kernel_map; -struct vm_map exec_map; struct vm_map clean_map; struct vm_map buffer_map; diff --git a/sys/vm/vm_kern.h b/sys/vm/vm_kern.h index 0ce9b60096..0baf9375ec 100644 --- a/sys/vm/vm_kern.h +++ b/sys/vm/vm_kern.h @@ -62,7 +62,7 @@ * rights to redistribute these changes. * * $FreeBSD: src/sys/vm/vm_kern.h,v 1.22 2000/02/16 21:11:31 dillon Exp $ - * $DragonFly: src/sys/vm/vm_kern.h,v 1.11 2006/12/28 22:24:02 dillon Exp $ + * $DragonFly: src/sys/vm/vm_kern.h,v 1.12 2007/06/07 23:14:29 dillon Exp $ */ #ifndef _VM_VM_KERN_H_ @@ -85,7 +85,6 @@ extern struct vm_map buffer_map; extern struct vm_map kernel_map; extern struct vm_map clean_map; -extern struct vm_map exec_map; extern u_int vm_kmem_size; extern vm_offset_t kernel_vm_end; -- 2.11.4.GIT