Index: arch/amd64/include/proc.h =================================================================== RCS file: /cvsroot/src/sys/arch/amd64/include/proc.h,v retrieving revision 1.12 diff -u -p -r1.12 proc.h --- arch/amd64/include/proc.h 14 Mar 2009 14:45:54 -0000 1.12 +++ arch/amd64/include/proc.h 22 Jan 2010 23:35:10 -0000 @@ -66,9 +66,8 @@ struct mdproc { #define MDP_USEDMTRR 0x0008 /* has set volatile MTRRs */ #define MDP_IRET 0x0010 /* return via iret, not sysret */ -#define UAREA_USER_OFFSET (USPACE - ALIGN(sizeof(struct user))) -#define KSTACK_LOWEST_ADDR(l) ((void *)USER_TO_UAREA((l)->l_addr)) -#define KSTACK_SIZE UAREA_USER_OFFSET +#define __HAVE_UAREA_TOP_LAYOUT +#define KSTACK_LOWEST_ADDR(l) (void *)(uvm_lwp_getuarea(l)) #else /* __x86_64__ */ Index: arch/i386/include/proc.h =================================================================== RCS file: /cvsroot/src/sys/arch/i386/include/proc.h,v retrieving revision 1.37 diff -u -p -r1.37 proc.h --- arch/i386/include/proc.h 20 Dec 2008 13:09:44 -0000 1.37 +++ arch/i386/include/proc.h 22 Jan 2010 23:35:51 -0000 @@ -65,8 +65,7 @@ struct mdproc { #define MDP_USEDMTRR 0x0002 /* has set volatile MTRRs */ /* kernel stack params */ -#define UAREA_USER_OFFSET (USPACE - ALIGN(sizeof(struct user))) -#define KSTACK_LOWEST_ADDR(l) ((void *)USER_TO_UAREA((l)->l_addr)) -#define KSTACK_SIZE UAREA_USER_OFFSET +#define __HAVE_UAREA_TOP_LAYOUT +#define KSTACK_LOWEST_ADDR(l) (void *)(uvm_lwp_getuarea(l)) #endif /* _I386_PROC_H_ */ Index: arch/vax/include/proc.h =================================================================== RCS file: /cvsroot/src/sys/arch/vax/include/proc.h,v retrieving revision 1.13 diff -u -p -r1.13 proc.h --- arch/vax/include/proc.h 21 Nov 2009 04:45:39 -0000 1.13 +++ arch/vax/include/proc.h 22 Jan 2010 23:36:09 -0000 @@ -58,7 +58,7 @@ struct mdproc { /* kernel stack params */ #define KSTACK_LOWEST_ADDR(l) \ - ((char *)(l)->l_addr + (REDZONEADDR + VAX_NBPG)) + (void *)(uvm_lwp_getuarea(l) + REDZONEADDR + VAX_NBPG) #define KSTACK_SIZE \ (USPACE - (REDZONEADDR + VAX_NBPG)) Index: compat/mach/mach_thread.c =================================================================== RCS file: /cvsroot/src/sys/compat/mach/mach_thread.c,v retrieving revision 1.49 diff -u -p -r1.49 mach_thread.c --- compat/mach/mach_thread.c 21 Oct 2009 21:12:05 -0000 1.49 +++ compat/mach/mach_thread.c 22 Jan 2010 23:36:09 -0000 @@ -171,7 +171,6 @@ mach_thread_create_running(struct mach_t struct mach_create_thread_child_args mctc; struct mach_right *child_mr; struct mach_lwp_emuldata *mle; - vaddr_t uaddr; int flags; int error; int end_offset; @@ -189,18 +188,11 @@ mach_thread_create_running(struct mach_t mctc.mctc_child_done = 0; mctc.mctc_state = req->req_state; - uaddr = uvm_uarea_alloc(); - if (__predict_false(uaddr == 0)) - return ENOMEM; - flags = 0; - if ((error = lwp_create(l, p, uaddr, flags, NULL, 0, + if ((error = lwp_create(l, p, 0, flags, NULL, 0, mach_create_thread_child, (void *)&mctc, &mctc.mctc_lwp, SCHED_OTHER)) != 0) - { - uvm_uarea_free(uaddr); return mach_msg_error(args, error); - } /* * Make the child runnable. Index: compat/sa/compat_sa.c =================================================================== RCS file: /cvsroot/src/sys/compat/sa/compat_sa.c,v retrieving revision 1.12 diff -u -p -r1.12 compat_sa.c --- compat/sa/compat_sa.c 21 Oct 2009 21:12:05 -0000 1.12 +++ compat/sa/compat_sa.c 22 Jan 2010 23:36:14 -0000 @@ -1815,23 +1815,16 @@ sa_newcachelwp(struct lwp *l, struct sad struct proc *p; struct lwp *l2; struct sadata_vp *vp; - vaddr_t uaddr; int error; p = l->l_proc; if (p->p_sflag & (PS_WCORE | PS_WEXIT)) return (0); - uaddr = uvm_uarea_alloc(); - if (__predict_false(uaddr == 0)) - return ENOMEM; - - error = lwp_create(l, p, uaddr, 0, NULL, 0, + error = lwp_create(l, p, 0, 0, NULL, 0, sa_neverrun, NULL, &l2, l->l_class); - if (error) { - uvm_uarea_free(uaddr); + if (error) return error; - } /* We don't want this LWP on the process's main LWP list, but * newlwp helpfully puts it there. Unclear if newlwp should Index: kern/kern_kthread.c =================================================================== RCS file: /cvsroot/src/sys/kern/kern_kthread.c,v retrieving revision 1.27 diff -u -p -r1.27 kern_kthread.c --- kern/kern_kthread.c 21 Oct 2009 21:12:06 -0000 1.27 +++ kern/kern_kthread.c 22 Jan 2010 23:36:21 -0000 @@ -59,24 +59,17 @@ kthread_create(pri_t pri, int flag, stru lwp_t **lp, const char *fmt, ...) { lwp_t *l; - vaddr_t uaddr; - int error; + int error, lc; va_list ap; - int lc; - uaddr = uvm_uarea_alloc(); - if (uaddr == 0) { - return ENOMEM; - } if ((flag & KTHREAD_TS) != 0) { lc = SCHED_OTHER; } else { lc = SCHED_RR; } - error = lwp_create(&lwp0, &proc0, uaddr, LWP_DETACHED, NULL, + error = lwp_create(&lwp0, &proc0, 0, LWP_DETACHED, NULL, 0, func, arg, &l, lc); if (error) { - uvm_uarea_free(uaddr); return error; } if (fmt != NULL) { Index: kern/kern_lwp.c =================================================================== RCS file: /cvsroot/src/sys/kern/kern_lwp.c,v retrieving revision 1.137 diff -u -p -r1.137 kern_lwp.c --- kern/kern_lwp.c 17 Dec 2009 01:25:10 -0000 1.137 +++ kern/kern_lwp.c 22 Jan 2010 23:36:21 -0000 @@ -243,7 +243,6 @@ struct lwplist alllwp = LIST_HEAD_INITIA struct pool lwp_uc_pool; -static pool_cache_t lwp_cache; static specificdata_domain_t lwp_specificdata_domain; void @@ -255,8 +254,6 @@ lwpinit(void) lwp_specificdata_domain = specificdata_domain_create(); KASSERT(lwp_specificdata_domain != NULL); lwp_sys_init(); - lwp_cache = pool_cache_init(sizeof(lwp_t), MIN_LWP_ALIGNMENT, 0, 0, - "lwppl", NULL, IPL_NONE, NULL, NULL, NULL); } /* @@ -548,32 +545,32 @@ lwp_create(lwp_t *l1, proc_t *p2, vaddr_ void *stack, size_t stacksize, void (*func)(void *), void *arg, lwp_t **rnewlwpp, int sclass) { - struct lwp *l2, *isfree; - turnstile_t *ts; + struct lwp *l2 = NULL; KASSERT(l1 == curlwp || l1->l_proc == &proc0); /* - * First off, reap any detached LWP waiting to be collected. + * At first, reap any detached LWP (with all uarea) waiting to be + * collected, but only if a separate uarea allocation is not passed. * We can re-use its LWP structure and turnstile. */ - isfree = NULL; - if (p2->p_zomblwp != NULL) { + if (uaddr == 0 && p2->p_zomblwp != NULL) { mutex_enter(p2->p_lock); - if ((isfree = p2->p_zomblwp) != NULL) { + if ((l2 = p2->p_zomblwp) != NULL) { p2->p_zomblwp = NULL; - lwp_free(isfree, true, false);/* releases proc mutex */ + lwp_free(l2, true, false); /* Releases proc lock. */ + KASSERT(uvm_lwp_getuarea(l2) != 0); } else mutex_exit(p2->p_lock); } - if (isfree == NULL) { - l2 = pool_cache_get(lwp_cache, PR_WAITOK); + if (l2 == NULL) { + l2 = uvm_lwp_alloc(uaddr); memset(l2, 0, sizeof(*l2)); l2->l_ts = pool_cache_get(turnstile_cache, PR_WAITOK); SLIST_INIT(&l2->l_pi_lenders); } else { - l2 = isfree; - ts = l2->l_ts; + turnstile_t *ts = l2->l_ts; + KASSERT(l2->l_inheritedprio == -1); KASSERT(SLIST_EMPTY(&l2->l_pi_lenders)); memset(l2, 0, sizeof(*l2)); @@ -952,12 +949,14 @@ lwp_free(struct lwp *l, bool recycle, bo kmem_free(l->l_name, MAXCOMLEN); cpu_lwp_free2(l); - uvm_lwp_exit(l); KASSERT(SLIST_EMPTY(&l->l_pi_lenders)); KASSERT(l->l_inheritedprio == -1); - if (!recycle) - pool_cache_put(lwp_cache, l); + + if (!recycle) { + /* Destroy the LWP. */ + uvm_lwp_exit(l); + } } /* Index: kern/sys_aio.c =================================================================== RCS file: /cvsroot/src/sys/kern/sys_aio.c,v retrieving revision 1.30 diff -u -p -r1.30 sys_aio.c --- kern/sys_aio.c 22 Nov 2009 19:09:16 -0000 1.30 +++ kern/sys_aio.c 22 Jan 2010 23:36:21 -0000 @@ -175,7 +175,6 @@ aio_procinit(struct proc *p) struct aioproc *aio; struct lwp *l; int error; - vaddr_t uaddr; /* Allocate and initialize AIO structure */ aio = kmem_zalloc(sizeof(struct aioproc), KM_SLEEP); @@ -192,15 +191,9 @@ aio_procinit(struct proc *p) * Create an AIO worker thread. * XXX: Currently, AIO thread is not protected against user's actions. */ - uaddr = uvm_uarea_alloc(); - if (uaddr == 0) { - aio_exit(p, aio); - return EAGAIN; - } - error = lwp_create(curlwp, p, uaddr, 0, NULL, 0, aio_worker, + error = lwp_create(curlwp, p, 0, 0, NULL, 0, aio_worker, NULL, &l, curlwp->l_class); if (error != 0) { - uvm_uarea_free(uaddr); aio_exit(p, aio); return error; } Index: kern/sys_lwp.c =================================================================== RCS file: /cvsroot/src/sys/kern/sys_lwp.c,v retrieving revision 1.48 diff -u -p -r1.48 sys_lwp.c --- kern/sys_lwp.c 1 Nov 2009 21:46:09 -0000 1.48 +++ kern/sys_lwp.c 22 Jan 2010 23:36:21 -0000 @@ -82,7 +82,6 @@ sys__lwp_create(struct lwp *l, const str } */ struct proc *p = l->l_proc; struct lwp *l2; - vaddr_t uaddr; ucontext_t *newuc; int error, lid; @@ -105,16 +104,9 @@ sys__lwp_create(struct lwp *l, const str /* XXX check against resource limits */ - uaddr = uvm_uarea_alloc(); - if (__predict_false(uaddr == 0)) { - pool_put(&lwp_uc_pool, newuc); - return ENOMEM; - } - - error = lwp_create(l, p, uaddr, SCARG(uap, flags) & LWP_DETACHED, + error = lwp_create(l, p, 0, SCARG(uap, flags) & LWP_DETACHED, NULL, 0, p->p_emul->e_startlwp, newuc, &l2, l->l_class); if (__predict_false(error)) { - uvm_uarea_free(uaddr); pool_put(&lwp_uc_pool, newuc); return error; } Index: sys/lwp.h =================================================================== RCS file: /cvsroot/src/sys/sys/lwp.h,v retrieving revision 1.127 diff -u -p -r1.127 lwp.h --- sys/lwp.h 29 Nov 2009 16:23:49 -0000 1.127 +++ sys/lwp.h 22 Jan 2010 23:36:33 -0000 @@ -181,22 +181,6 @@ struct lwp { uint64_t *l_syscall_counter; /* !: counter for current process */ }; -/* - * USER_TO_UAREA/UAREA_TO_USER: macros to convert between - * the lowest address of the uarea (UAREA) and lwp::l_addr (USER). - * - * the default is just a cast. MD code can modify it by defining - * either these macros or UAREA_USER_OFFSET in . - */ - -#if !defined(USER_TO_UAREA) -#if !defined(UAREA_USER_OFFSET) -#define UAREA_USER_OFFSET 0 -#endif /* !defined(UAREA_USER_OFFSET) */ -#define USER_TO_UAREA(user) ((vaddr_t)(user) - UAREA_USER_OFFSET) -#define UAREA_TO_USER(uarea) ((struct user *)((uarea) + UAREA_USER_OFFSET)) -#endif /* !defined(UAREA_TO_USER) */ - static __inline void * lwp_getpcb(struct lwp *l) { Index: sys/proc.h =================================================================== RCS file: /cvsroot/src/sys/sys/proc.h,v retrieving revision 1.294 diff -u -p -r1.294 proc.h --- sys/proc.h 10 Dec 2009 14:13:54 -0000 1.294 +++ sys/proc.h 22 Jan 2010 23:36:33 -0000 @@ -75,6 +75,7 @@ #endif #include /* Machine-dependent proc substruct */ +#include #include #include #include @@ -550,25 +551,33 @@ void kstack_check_magic(const struct lwp #endif /* - * kernel stack paramaters - * XXX require sizeof(struct user) - */ -/* - * KSTACK_LOWEST_ADDR: return the lowest address of the lwp's kernel stack, - * excluding redzone etc. + * Kernel stack paramaters. XXX: require sizeof(struct pcb) * - * if provides the MD definition, it will be used. - */ -#ifndef KSTACK_LOWEST_ADDR -#define KSTACK_LOWEST_ADDR(l) ((void *)ALIGN((l)->l_addr + 1)) -#endif -/* - * KSTACK_SIZE: the size kernel stack for a lwp, excluding redzone etc. + * KSTACK_LOWEST_ADDR: return the lowest address of the LWP's kernel stack, + * excluding redzone, etc. + * + * KSTACK_SIZE: the size kernel stack for an LWP, excluding redzone, etc. * - * if provides the MD definition, it will be used. + * If provides the MD definition, it will be used. */ -#ifndef KSTACK_SIZE -#define KSTACK_SIZE (USPACE - ALIGN(sizeof(struct user))) + +#define UAREA_LWP_SIZE roundup2(sizeof(struct lwp), \ + MAX(MIN_LWP_ALIGNMENT, coherency_unit)) +#define UAREA_PCB_SIZE roundup2(sizeof(struct pcb), \ + MAX(MIN_LWP_ALIGNMENT, coherency_unit)) + +#ifdef __HAVE_UAREA_TOP_LAYOUT +#define UAREA_LWP_OFFSET (USPACE - (UAREA_LWP_SIZE + UAREA_PCB_SIZE)) +#else +#define UAREA_LWP_OFFSET 0 +#endif + +#ifndef KSTACK_LOWEST_ADDR +#define KSTACK_LOWEST_ADDR(l) \ + (uvm_lwp_getuarea(l) + UAREA_LWP_SIZE + UAREA_PCB_SIZE) +#endif +#ifndef KSTACK_SIZE +#define KSTACK_SIZE (USPACE - (UAREA_LWP_SIZE + UAREA_PCB_SIZE)) #endif extern struct emul emul_netbsd; Index: uvm/uvm_extern.h =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_extern.h,v retrieving revision 1.161 diff -u -p -r1.161 uvm_extern.h --- uvm/uvm_extern.h 21 Nov 2009 17:45:02 -0000 1.161 +++ uvm/uvm_extern.h 22 Jan 2010 23:36:33 -0000 @@ -631,11 +631,11 @@ vaddr_t uvm_uarea_alloc(void); void uvm_uarea_free(vaddr_t); vaddr_t uvm_lwp_getuarea(lwp_t *); void uvm_lwp_setuarea(lwp_t *, vaddr_t); +lwp_t * uvm_lwp_alloc(vaddr_t); int uvm_vslock(struct vmspace *, void *, size_t, vm_prot_t); void uvm_vsunlock(struct vmspace *, void *, size_t); void uvm_cpu_attach(struct cpu_info *); - /* uvm_init.c */ void uvm_init(void); Index: uvm/uvm_glue.c =================================================================== RCS file: /cvsroot/src/sys/uvm/uvm_glue.c,v retrieving revision 1.143 diff -u -p -r1.143 uvm_glue.c --- uvm/uvm_glue.c 17 Dec 2009 01:25:11 -0000 1.143 +++ uvm/uvm_glue.c 22 Jan 2010 23:36:33 -0000 @@ -331,18 +331,44 @@ uvm_uarea_free(vaddr_t uaddr) pool_cache_put(uvm_uarea_cache, (void *)uaddr); } +/* + * uvm_lwp_getuarea/uvm_lwp_setuarea: routines to convert between the lowest + * address of the uarea (UAREA) and lwp::l_addr (PCB). Note that PCB is always + * after/above the LWP structure. + */ + vaddr_t uvm_lwp_getuarea(lwp_t *l) { - return (vaddr_t)l->l_addr - UAREA_USER_OFFSET; + return (vaddr_t)l->l_addr - (UAREA_LWP_OFFSET + UAREA_LWP_SIZE); } void uvm_lwp_setuarea(lwp_t *l, vaddr_t addr) { - l->l_addr = (void *)(addr + UAREA_USER_OFFSET); + KASSERT(trunc_page(addr) == addr); + l->l_addr = (void *)(addr + UAREA_LWP_OFFSET + UAREA_LWP_SIZE); +} + +lwp_t * +uvm_lwp_alloc(vaddr_t uaddr) +{ + + if (uaddr == 0) { + uaddr = uvm_uarea_alloc(); + } + return (lwp_t *)(uaddr + UAREA_LWP_OFFSET); +} + +void +uvm_lwp_exit(struct lwp *l) +{ + vaddr_t va = uvm_lwp_getuarea(l); + + /* Note: LWP is destroyed and 'l' is invalid after this point. */ + uvm_uarea_free(va); } /* @@ -373,17 +399,6 @@ uvm_proc_exit(struct proc *p) uvmspace_free(ovm); } -void -uvm_lwp_exit(struct lwp *l) -{ - vaddr_t va = uvm_lwp_getuarea(l); - - uvm_uarea_free(va); -#ifdef DIAGNOSTIC - uvm_lwp_setuarea(l, (vaddr_t)NULL); -#endif -} - /* * uvm_init_limit: init per-process VM limits *