From 924be1137c5a246ba6fdb1d17417b0ce1a94c872 Mon Sep 17 00:00:00 2001 From: guenther Date: Thu, 15 May 2014 03:52:25 +0000 Subject: [PATCH] Move from struct proc to process the reference-count-holding pointers to the process's vmspace and filedescs. struct proc continues to keep copies of the pointers, copying them on fork, clearing them on exit, and (for vmspace) refreshing on exec. Also, make uvm_swapout_threads() thread aware, eliminating p_swtime in kernel. particular testing by ajacoutot@ and sebastia@ --- sys/arch/vax/vax/pmap.c | 86 ++++++++++++---------------- sys/kern/init_main.c | 6 +- sys/kern/kern_descrip.c | 23 +++----- sys/kern/kern_exec.c | 19 +++--- sys/kern/kern_exit.c | 18 +++--- sys/kern/kern_fork.c | 37 ++++++------ sys/kern/kern_proc.c | 7 +-- sys/kern/sched_bsd.c | 3 +- sys/sys/filedesc.h | 8 +-- sys/sys/proc.h | 11 ++-- sys/sys/sysctl.h | 11 ++-- sys/uvm/uvm_extern.h | 11 ++-- sys/uvm/uvm_glue.c | 124 +++++++++++++++++----------------------- sys/uvm/uvm_map.c | 34 ++++++----- 14 files changed, 184 insertions(+), 214 deletions(-) diff --git a/sys/arch/vax/vax/pmap.c b/sys/arch/vax/vax/pmap.c index c97421f99ec..2ce070f512e 100644 --- a/sys/arch/vax/vax/pmap.c +++ b/sys/arch/vax/vax/pmap.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pmap.c,v 1.64 2014/05/08 19:06:07 miod Exp $ */ +/* $OpenBSD: pmap.c,v 1.65 2014/05/15 03:52:25 guenther Exp $ */ /* $NetBSD: pmap.c,v 1.74 1999/11/13 21:32:25 matt Exp $ */ /* * Copyright (c) 1994, 1998, 1999, 2003 Ludd, University of Lule}, Sweden. @@ -605,71 +605,61 @@ rmspace(struct pmap *pm) * Avoid to remove ourselves. Logic is designed after uvm_swapout_threads(). */ -static inline boolean_t -pmap_vax_swappable(struct proc *p, struct pmap *pm) -{ - if (p->p_flag & (P_SYSTEM | P_WEXIT)) /* !swappable(p) */ - return FALSE; - if (p->p_vmspace->vm_map.pmap == pm) - return FALSE; - switch (p->p_stat) { - case SRUN: - case SSLEEP: - case SSTOP: - return TRUE; - default: - return FALSE; - } -} - int pmap_rmproc(struct pmap *pm) { + struct process *pr, *outpr; struct pmap *ppm; - struct proc *p; - struct proc *outp, *outp2; - int outpri, outpri2; + struct proc *p, *slpp; + int outpri; int didswap = 0; extern int maxslp; - outp = outp2 = NULL; - outpri = outpri2 = 0; - LIST_FOREACH(p, &allproc, p_list) { - if (!pmap_vax_swappable(p, pm)) + outpr = NULL; + outpri = 0; + LIST_FOREACH(pr, &allprocess, ps_list) { + if (pr->ps_flags & (PS_SYSTEM | PS_EXITING)) continue; ppm = p->p_vmspace->vm_map.pmap; + if (ppm == pm) /* Don't swap ourself */ + continue; if (ppm->pm_p0lr == 0 && ppm->pm_p1lr == NPTEPERREG) - continue; /* Already swapped */ - switch (p->p_stat) { - case SRUN: -#if 0 /* won't pass pmap_vax_swappable() */ - case SONPROC: -#endif - if (p->p_swtime > outpri2) { - outp2 = p; - outpri2 = p->p_swtime; + continue; /* Already swapped */ + + /* + * slpp: the sleeping or stopped thread in pr with + * the smallest p_slptime + */ + slpp = NULL; + TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) { + switch (p->p_stat) { + case SRUN: + case SONPROC: + goto next_process; + + case SSLEEP: + case SSTOP: + if (slpp == NULL || + slpp->p_slptime < p->p_slptime) + slpp = p; + continue; } - continue; - case SSLEEP: - case SSTOP: - if (p->p_slptime >= maxslp) { + } + if (slpp != NULL) { + if (slpp->p_slptime >= maxslp) { rmspace(ppm); didswap++; - } else if (p->p_slptime > outpri) { - outp = p; + } else if (slpp->p_slptime > outpri) { + outpr = pr; outpri = p->p_slptime; } - continue; } +next_process: ; } - if (didswap == 0) { - if ((p = outp) == NULL) - p = outp2; - if (p) { - rmspace(p->p_vmspace->vm_map.pmap); - didswap++; - } + if (didswap == 0 && outpr != NULL) { + rmspace(outpr->ps_vmspace->vm_map.pmap); + didswap++; } return didswap; } diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c index 92481c3308f..fba69020a84 100644 --- a/sys/kern/init_main.c +++ b/sys/kern/init_main.c @@ -1,4 +1,4 @@ -/* $OpenBSD: init_main.c,v 1.212 2014/05/04 05:03:26 guenther Exp $ */ +/* $OpenBSD: init_main.c,v 1.213 2014/05/15 03:52:25 guenther Exp $ */ /* $NetBSD: init_main.c,v 1.84.4.1 1996/06/02 09:08:06 mrg Exp $ */ /* @@ -305,7 +305,7 @@ main(void *framep) siginit(pr); /* Create the file descriptor table. */ - p->p_fd = fdinit(NULL); + p->p_fd = pr->ps_fd = fdinit(); /* Create the limits structures. */ pr->ps_limit = &limit0; @@ -325,7 +325,7 @@ main(void *framep) /* Allocate a prototype map so we have something to fork. */ uvmspace_init(&vmspace0, pmap_kernel(), round_page(VM_MIN_ADDRESS), trunc_page(VM_MAX_ADDRESS), TRUE, TRUE); - p->p_vmspace = &vmspace0; + p->p_vmspace = pr->ps_vmspace = &vmspace0; p->p_addr = proc0paddr; /* XXX */ diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index ab36785730d..484d3c76691 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_descrip.c,v 1.107 2014/04/12 14:18:11 espie Exp $ */ +/* $OpenBSD: kern_descrip.c,v 1.108 2014/05/15 03:52:25 guenther Exp $ */ /* $NetBSD: kern_descrip.c,v 1.42 1996/03/30 22:24:38 christos Exp $ */ /* @@ -867,21 +867,12 @@ restart: * Build a new filedesc structure. */ struct filedesc * -fdinit(struct proc *p) +fdinit(void) { struct filedesc0 *newfdp; extern int cmask; newfdp = pool_get(&fdesc_pool, PR_WAITOK|PR_ZERO); - if (p != NULL) { - struct filedesc *fdp = p->p_fd; - - newfdp->fd_fd.fd_cdir = fdp->fd_cdir; - vref(newfdp->fd_fd.fd_cdir); - newfdp->fd_fd.fd_rdir = fdp->fd_rdir; - if (newfdp->fd_fd.fd_rdir) - vref(newfdp->fd_fd.fd_rdir); - } rw_init(&newfdp->fd_fd.fd_lock, "fdlock"); /* Create the file descriptor table. */ @@ -904,19 +895,19 @@ fdinit(struct proc *p) * Share a filedesc structure. */ struct filedesc * -fdshare(struct proc *p) +fdshare(struct process *pr) { - p->p_fd->fd_refcnt++; - return (p->p_fd); + pr->ps_fd->fd_refcnt++; + return (pr->ps_fd); } /* * Copy a filedesc structure. */ struct filedesc * -fdcopy(struct proc *p) +fdcopy(struct process *pr) { - struct filedesc *newfdp, *fdp = p->p_fd; + struct filedesc *newfdp, *fdp = pr->ps_fd; struct file **fpp; int i; diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 969ac154091..91bbc2e05b4 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_exec.c,v 1.141 2014/04/18 11:51:17 guenther Exp $ */ +/* $OpenBSD: kern_exec.c,v 1.142 2014/05/15 03:52:25 guenther Exp $ */ /* $NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $ */ /*- @@ -78,7 +78,7 @@ /* * Map the shared signal code. */ -int exec_sigcode_map(struct proc *, struct emul *); +int exec_sigcode_map(struct process *, struct emul *); /* * If non-zero, stackgap_random specifies the upper limit of the random gap size @@ -256,7 +256,7 @@ sys_execve(struct proc *p, void *v, register_t *retval) #endif char *stack; struct ps_strings arginfo; - struct vmspace *vm = p->p_vmspace; + struct vmspace *vm = pr->ps_vmspace; char **tmpfap; extern struct emul emul_native; #if NSYSTRACE > 0 @@ -415,17 +415,16 @@ sys_execve(struct proc *p, void *v, register_t *retval) /* * we're committed: any further errors will kill the process, so * kill the other threads now. - * XXX wait until threads are reaped to make uvmspace_exec() cheaper? */ single_thread_set(p, SINGLE_EXIT, 0); /* * Prepare vmspace for remapping. Note that uvmspace_exec can replace - * p_vmspace! + * pr_vmspace! */ uvmspace_exec(p, VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS); - vm = p->p_vmspace; + vm = pr->ps_vmspace; /* Now map address space */ vm->vm_taddr = (char *)pack.ep_taddr; vm->vm_tsize = atop(round_page(pack.ep_tsize)); @@ -653,7 +652,7 @@ sys_execve(struct proc *p, void *v, register_t *retval) #endif /* map the process's signal trampoline code */ - if (exec_sigcode_map(p, pack.ep_emul)) + if (exec_sigcode_map(pr, pack.ep_emul)) goto free_pack_abort; #ifdef __HAVE_EXEC_MD_MAP @@ -817,7 +816,7 @@ copyargs(struct exec_package *pack, struct ps_strings *arginfo, void *stack, } int -exec_sigcode_map(struct proc *p, struct emul *e) +exec_sigcode_map(struct process *pr, struct emul *e) { vsize_t sz; @@ -851,9 +850,9 @@ exec_sigcode_map(struct proc *p, struct emul *e) uvm_unmap(kernel_map, va, va + round_page(sz)); } - p->p_p->ps_sigcode = 0; /* no hint */ + pr->ps_sigcode = 0; /* no hint */ uao_reference(e->e_sigobject); - if (uvm_map(&p->p_vmspace->vm_map, &p->p_p->ps_sigcode, round_page(sz), + if (uvm_map(&pr->ps_vmspace->vm_map, &pr->ps_sigcode, round_page(sz), e->e_sigobject, 0, 0, UVM_MAPFLAG(UVM_PROT_RX, UVM_PROT_RX, UVM_INH_SHARE, UVM_ADV_RANDOM, 0))) { uao_detach(e->e_sigobject); diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 37e7c39fbd7..1fbaa8649ff 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_exit.c,v 1.140 2014/04/18 11:51:17 guenther Exp $ */ +/* $OpenBSD: kern_exit.c,v 1.141 2014/05/15 03:52:25 guenther Exp $ */ /* $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $ */ /* @@ -176,12 +176,10 @@ exit1(struct proc *p, int rv, int flags) } p->p_siglist = 0; - /* - * Close open files and release open-file table. - */ - fdfree(p); - if ((p->p_flag & P_THREAD) == 0) { + /* close open files and release open-file table */ + fdfree(p); + timeout_del(&pr->ps_realit_to); #ifdef SYSVSEM semexit(pr); @@ -242,6 +240,8 @@ exit1(struct proc *p, int rv, int flags) atomic_setbits_int(&pr->ps_flags, PS_NOZOMBIE); } + p->p_fd = NULL; /* zap the thread's copy */ + #if NSYSTRACE > 0 if (ISSET(p->p_flag, P_SYSTRACE)) systrace_exit(p); @@ -446,7 +446,8 @@ reaper(void) * We must do this from a valid thread because doing * so may block. */ - uvm_exit(p); + uvm_uarea_free(p); + p->p_vmspace = NULL; /* zap the thread's copy */ if (p->p_flag & P_THREAD) { /* Just a thread */ @@ -454,6 +455,9 @@ reaper(void) } else { struct process *pr = p->p_p; + /* Release the rest of the process's vmspace */ + uvm_exit(pr); + if ((pr->ps_flags & PS_NOZOMBIE) == 0) { /* Process is now a true zombie. */ p->p_stat = SZOMB; diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index adbabb331d9..30e29bc0993 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_fork.c,v 1.166 2014/05/06 11:50:14 mpi Exp $ */ +/* $OpenBSD: kern_fork.c,v 1.167 2014/05/15 03:52:25 guenther Exp $ */ /* $NetBSD: kern_fork.c,v 1.29 1996/02/09 18:59:34 christos Exp $ */ /* @@ -196,12 +196,21 @@ process_new(struct proc *p, struct process *parent, int flags) p->p_p = pr; /* - * Create signal actions for the child process. + * Duplicate sub-structures as needed. + * Increase reference counts on shared objects. */ + if (flags & FORK_SHAREFILES) + pr->ps_fd = fdshare(parent); + else + pr->ps_fd = fdcopy(parent); if (flags & FORK_SIGHAND) pr->ps_sigacts = sigactsshare(parent); else pr->ps_sigacts = sigactsinit(parent); + if (flags & FORK_SHAREVM) + pr->ps_vmspace = uvmspace_share(parent); + else + pr->ps_vmspace = uvmspace_fork(parent); if (parent->ps_flags & PS_PROFIL) startprofclock(pr); @@ -334,18 +343,11 @@ fork1(struct proc *curp, int flags, void *stack, pid_t *tidptr, process_new(p, curpr, flags); pr = p->p_p; } + p->p_fd = pr->ps_fd; + p->p_vmspace = pr->ps_vmspace; if (pr->ps_flags & PS_SYSTEM) atomic_setbits_int(&p->p_flag, P_SYSTEM); - /* - * Duplicate sub-structures as needed. - * Increase reference counts on shared objects. - */ - if (flags & FORK_SHAREFILES) - p->p_fd = fdshare(curp); - else - p->p_fd = fdcopy(curp); - if (flags & FORK_PPWAIT) { atomic_setbits_int(&pr->ps_flags, PS_PPWAIT); atomic_setbits_int(&curpr->ps_flags, PS_ISPWAIT); @@ -380,13 +382,16 @@ fork1(struct proc *curp, int flags, void *stack, pid_t *tidptr, p->p_addr = (struct user *)uaddr; /* - * Finish creating the child process. It will return through a - * different path later. + * Finish creating the child thread. cpu_fork() will copy + * and update the pcb and make the child ready to run. If + * this is a normal user fork, the child will exit directly + * to user mode via child_return() on its first time slice + * and will not return here. If this is a kernel thread, + * the specified entry point will be executed. */ - uvm_fork(curp, p, ((flags & FORK_SHAREVM) ? TRUE : FALSE), stack, - 0, func ? func : child_return, arg ? arg : p); + cpu_fork(curp, p, stack, 0, func ? func : child_return, arg ? arg : p); - vm = p->p_vmspace; + vm = pr->ps_vmspace; if (flags & FORK_FORK) { forkstat.cntfork++; diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index c749d5352ae..757878a1b4e 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_proc.c,v 1.57 2014/03/30 21:54:48 guenther Exp $ */ +/* $OpenBSD: kern_proc.c,v 1.58 2014/05/15 03:52:25 guenther Exp $ */ /* $NetBSD: kern_proc.c,v 1.14 1996/02/09 18:59:41 christos Exp $ */ /* @@ -403,9 +403,8 @@ proc_printit(struct proc *p, const char *modif, TAILQ_NEXT(p, p_runq), p->p_list.le_next, p->p_list.le_prev); (*pr)(" process=%p user=%p, vmspace=%p\n", p->p_p, p->p_addr, p->p_vmspace); - (*pr)(" estcpu=%u, cpticks=%d, pctcpu=%u.%u, swtime=%u\n", - p->p_estcpu, p->p_cpticks, p->p_pctcpu / 100, p->p_pctcpu % 100, - p->p_swtime); + (*pr)(" estcpu=%u, cpticks=%d, pctcpu=%u.%u\n", + p->p_estcpu, p->p_cpticks, p->p_pctcpu / 100, p->p_pctcpu % 100); (*pr)(" user=%u, sys=%u, intr=%u\n", p->p_uticks, p->p_sticks, p->p_iticks); } diff --git a/sys/kern/sched_bsd.c b/sys/kern/sched_bsd.c index ed512c2af29..1a73afc54d3 100644 --- a/sys/kern/sched_bsd.c +++ b/sys/kern/sched_bsd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sched_bsd.c,v 1.33 2013/06/03 16:55:22 guenther Exp $ */ +/* $OpenBSD: sched_bsd.c,v 1.34 2014/05/15 03:52:25 guenther Exp $ */ /* $NetBSD: kern_synch.c,v 1.37 1996/04/22 01:38:37 christos Exp $ */ /*- @@ -222,7 +222,6 @@ schedcpu(void *arg) * (if sleeping). We ignore overflow; with 16-bit int's * (remember them?) overflow takes 45 days. */ - p->p_swtime++; if (p->p_stat == SSLEEP || p->p_stat == SSTOP) p->p_slptime++; p->p_pctcpu = (p->p_pctcpu * ccpu) >> FSHIFT; diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h index 452c7a41c0d..b383a38351e 100644 --- a/sys/sys/filedesc.h +++ b/sys/sys/filedesc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: filedesc.h,v 1.27 2014/04/12 14:18:11 espie Exp $ */ +/* $OpenBSD: filedesc.h,v 1.28 2014/05/15 03:52:25 guenther Exp $ */ /* $NetBSD: filedesc.h,v 1.14 1996/04/09 20:55:28 cgd Exp $ */ /* @@ -125,9 +125,9 @@ int dupfdopen(struct filedesc *, int, int, int); int fdalloc(struct proc *p, int want, int *result); void fdexpand(struct proc *); int falloc(struct proc *p, struct file **resultfp, int *resultfd); -struct filedesc *fdinit(struct proc *p); -struct filedesc *fdshare(struct proc *p); -struct filedesc *fdcopy(struct proc *p); +struct filedesc *fdinit(void); +struct filedesc *fdshare(struct process *); +struct filedesc *fdcopy(struct process *); void fdfree(struct proc *p); int fdrelease(struct proc *p, int); void fdremove(struct filedesc *, int); diff --git a/sys/sys/proc.h b/sys/sys/proc.h index cf4170ad2a8..dffe7120c11 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -1,4 +1,4 @@ -/* $OpenBSD: proc.h,v 1.185 2014/05/04 05:03:26 guenther Exp $ */ +/* $OpenBSD: proc.h,v 1.186 2014/05/15 03:52:25 guenther Exp $ */ /* $NetBSD: proc.h,v 1.44 1996/04/22 01:23:21 christos Exp $ */ /*- @@ -166,6 +166,8 @@ struct process { struct sigacts *ps_sigacts; /* Signal actions, state */ struct vnode *ps_textvp; /* Vnode of executable. */ + struct filedesc *ps_fd; /* Ptr to open files structure */ + struct vmspace *ps_vmspace; /* Address space */ /* The following fields are all zeroed upon creation in process_new. */ #define ps_startzero ps_klist @@ -259,8 +261,8 @@ struct proc { TAILQ_ENTRY(proc) p_thr_link;/* Threads in a process linkage. */ /* substructures: */ - struct filedesc *p_fd; /* Ptr to open files structure. */ - struct vmspace *p_vmspace; /* Address space. */ + struct filedesc *p_fd; /* copy of p_p->ps_fd */ + struct vmspace *p_vmspace; /* copy of p_p->ps_vmspace */ #define p_rlimit p_p->ps_limit->pl_rlimit int p_flag; /* P_* flags. */ @@ -285,8 +287,7 @@ struct proc { const volatile void *p_wchan;/* Sleep address. */ struct timeout p_sleep_to;/* timeout for tsleep() */ const char *p_wmesg; /* Reason for sleep. */ - fixpt_t p_pctcpu; /* %cpu for this thread during p_swtime */ - u_int p_swtime; /* Time swapped in or out. */ + fixpt_t p_pctcpu; /* %cpu for this thread */ u_int p_slptime; /* Time since last blocked. */ u_int p_uticks; /* Statclock hits in user mode. */ u_int p_sticks; /* Statclock hits in system mode. */ diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h index 2e43d2e10be..97d355ea034 100644 --- a/sys/sys/sysctl.h +++ b/sys/sys/sysctl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sysctl.h,v 1.144 2014/03/30 21:54:48 guenther Exp $ */ +/* $OpenBSD: sysctl.h,v 1.145 2014/05/15 03:52:25 guenther Exp $ */ /* $NetBSD: sysctl.h,v 1.16 1996/04/09 20:55:36 cgd Exp $ */ /* @@ -357,8 +357,8 @@ struct kinfo_proc { u_int32_t p_rtime_sec; /* STRUCT TIMEVAL: Real time. */ u_int32_t p_rtime_usec; /* STRUCT TIMEVAL: Real time. */ int32_t p_cpticks; /* INT: Ticks of cpu time. */ - u_int32_t p_pctcpu; /* FIXPT_T: %cpu for this process during p_swtime */ - u_int32_t p_swtime; /* U_INT: Time swapped in or out. */ + u_int32_t p_pctcpu; /* FIXPT_T: %cpu for this process */ + u_int32_t p_swtime; /* unused, always zero */ u_int32_t p_slptime; /* U_INT: Time since last blocked. */ int32_t p_schedflags; /* INT: PSCHED_* flags */ @@ -469,9 +469,9 @@ do { \ \ if (show_addresses) { \ (kp)->p_paddr = PTRTOINT64(paddr); \ - (kp)->p_fd = PTRTOINT64((p)->p_fd); \ + (kp)->p_fd = PTRTOINT64((pr)->ps_fd); \ (kp)->p_limit = PTRTOINT64((pr)->ps_limit); \ - (kp)->p_vmspace = PTRTOINT64((p)->p_vmspace); \ + (kp)->p_vmspace = PTRTOINT64((pr)->ps_vmspace); \ (kp)->p_sigacts = PTRTOINT64((pr)->ps_sigacts); \ (kp)->p_sess = PTRTOINT64((pg)->pg_session); \ (kp)->p_ru = PTRTOINT64((pr)->ps_ru); \ @@ -551,7 +551,6 @@ do { \ } \ (kp)->p_addr = PTRTOINT64((p)->p_addr); \ (kp)->p_stat = (p)->p_stat; \ - (kp)->p_swtime = (p)->p_swtime; \ (kp)->p_slptime = (p)->p_slptime; \ (kp)->p_holdcnt = 1; \ (kp)->p_priority = (p)->p_priority; \ diff --git a/sys/uvm/uvm_extern.h b/sys/uvm/uvm_extern.h index 4dd4ee8bb54..76b5946352f 100644 --- a/sys/uvm/uvm_extern.h +++ b/sys/uvm/uvm_extern.h @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_extern.h,v 1.114 2014/05/06 11:50:14 mpi Exp $ */ +/* $OpenBSD: uvm_extern.h,v 1.115 2014/05/15 03:52:25 guenther Exp $ */ /* $NetBSD: uvm_extern.h,v 1.57 2001/03/09 01:02:12 chs Exp $ */ /* @@ -513,9 +513,8 @@ int uvm_fault(vm_map_t, vaddr_t, void uvm_chgkprot(caddr_t, size_t, int); #endif vaddr_t uvm_uarea_alloc(void); -void uvm_fork(struct proc *, struct proc *, boolean_t, - void *, size_t, void (*)(void *), void *); -void uvm_exit(struct proc *); +void uvm_uarea_free(struct proc *); +void uvm_exit(struct process *); void uvm_init_limits(struct proc *); boolean_t uvm_kernacc(caddr_t, size_t, int); @@ -668,9 +667,9 @@ struct vmspace *uvmspace_alloc(vaddr_t, vaddr_t, void uvmspace_init(struct vmspace *, struct pmap *, vaddr_t, vaddr_t, boolean_t, boolean_t); void uvmspace_exec(struct proc *, vaddr_t, vaddr_t); -struct vmspace *uvmspace_fork(struct vmspace *); +struct vmspace *uvmspace_fork(struct process *); void uvmspace_free(struct vmspace *); -void uvmspace_share(struct proc *, struct proc *); +struct vmspace *uvmspace_share(struct process *); /* uvm_meter.c */ diff --git a/sys/uvm/uvm_glue.c b/sys/uvm/uvm_glue.c index 5865c46fa35..88eb3c3a873 100644 --- a/sys/uvm/uvm_glue.c +++ b/sys/uvm/uvm_glue.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_glue.c,v 1.64 2014/05/03 22:49:43 guenther Exp $ */ +/* $OpenBSD: uvm_glue.c,v 1.65 2014/05/15 03:52:25 guenther Exp $ */ /* $NetBSD: uvm_glue.c,v 1.44 2001/02/06 19:54:44 eeh Exp $ */ /* @@ -316,53 +316,26 @@ uvm_uarea_alloc(void) } /* - * uvm_fork: fork a virtual address space + * uvm_uarea_free: free a dead thread's stack * - * - the address space is copied as per parent map's inherit values - * - if specified, the child gets a new user stack described by - * stack and stacksize - * - NOTE: the kernel stack may be at a different location in the child - * process, and thus addresses of automatic variables may be invalid - * after cpu_fork returns in the child process. We do nothing here - * after cpu_fork returns. - * - XXXCDC: we need a way for this to return a failure value rather - * than just hang + * - the thread passed to us is a dead thread; we + * are running on a different context now (the reaper). */ void -uvm_fork(struct proc *p1, struct proc *p2, boolean_t shared, void *stack, - size_t stacksize, void (*func)(void *), void * arg) +uvm_uarea_free(struct proc *p) { - if (shared == TRUE) { - p2->p_vmspace = NULL; - uvmspace_share(p1, p2); /* share vmspace */ - } else - p2->p_vmspace = uvmspace_fork(p1->p_vmspace); /* fork vmspace */ - - /* - * cpu_fork() copy and update the pcb, and make the child ready - * to run. If this is a normal user fork, the child will exit - * directly to user mode via child_return() on its first time - * slice and will not return here. If this is a kernel thread, - * the specified entry point will be executed. - */ - cpu_fork(p1, p2, stack, stacksize, func, arg); + uvm_km_free(kernel_map, (vaddr_t)p->p_addr, USPACE); + p->p_addr = NULL; } /* * uvm_exit: exit a virtual address space - * - * - the process passed to us is a dead (pre-zombie) process; we - * are running on a different context now (the reaper). - * - we must run in a separate thread because freeing the vmspace - * of the dead process may block. */ void -uvm_exit(struct proc *p) +uvm_exit(struct process *pr) { - uvmspace_free(p->p_vmspace); - p->p_vmspace = NULL; - uvm_km_free(kernel_map, (vaddr_t)p->p_addr, USPACE); - p->p_addr = NULL; + uvmspace_free(pr->ps_vmspace); + pr->ps_vmspace = NULL; } /* @@ -395,11 +368,6 @@ int swapdebug = 0; #define SDB_SWAPOUT 4 #endif -/* - * swappable: is process "p" swappable? - */ - -#define swappable(p) (((p)->p_flag & (P_SYSTEM | P_WEXIT)) == 0) /* * swapout_threads: find threads that can be swapped @@ -413,9 +381,10 @@ int swapdebug = 0; void uvm_swapout_threads(void) { - struct proc *p; - struct proc *outp, *outp2; - int outpri, outpri2; + struct process *pr; + struct proc *p, *slpp; + struct process *outpr; + int outpri; int didswap = 0; extern int maxslp; /* XXXCDC: should move off to uvmexp. or uvm., also in uvm_meter */ @@ -426,33 +395,45 @@ uvm_swapout_threads(void) #endif /* - * outp/outpri : stop/sleep process with largest sleeptime < maxslp - * outp2/outpri2: the longest resident process (its swap time) + * outpr/outpri : stop/sleep process whose most active thread has + * the largest sleeptime < maxslp */ - outp = outp2 = NULL; - outpri = outpri2 = 0; - LIST_FOREACH(p, &allproc, p_list) { - if (!swappable(p)) + outpr = NULL; + outpri = 0; + LIST_FOREACH(pr, &allprocess, ps_list) { + if (pr->ps_flags & (PS_SYSTEM | PS_EXITING)) continue; - switch (p->p_stat) { - case SRUN: - if (p->p_swtime > outpri2) { - outp2 = p; - outpri2 = p->p_swtime; + + /* + * slpp: the sleeping or stopped thread in pr with + * the smallest p_slptime + */ + slpp = NULL; + TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) { + switch (p->p_stat) { + case SRUN: + case SONPROC: + goto next_process; + + case SSLEEP: + case SSTOP: + if (slpp == NULL || + slpp->p_slptime < p->p_slptime) + slpp = p; + continue; } - continue; - - case SSLEEP: - case SSTOP: - if (p->p_slptime >= maxslp) { - pmap_collect(p->p_vmspace->vm_map.pmap); + } + + if (slpp != NULL) { + if (slpp->p_slptime >= maxslp) { + pmap_collect(pr->ps_vmspace->vm_map.pmap); didswap++; - } else if (p->p_slptime > outpri) { - outp = p; - outpri = p->p_slptime; + } else if (slpp->p_slptime > outpri) { + outpr = pr; + outpri = slpp->p_slptime; } - continue; } +next_process: ; } /* @@ -461,15 +442,14 @@ uvm_swapout_threads(void) * if we are real low on memory since we don't gain much by doing * it. */ - if (didswap == 0 && uvmexp.free <= atop(round_page(USPACE))) { - if ((p = outp) == NULL) - p = outp2; + if (didswap == 0 && uvmexp.free <= atop(round_page(USPACE)) && + outpr != NULL) { #ifdef DEBUG if (swapdebug & SDB_SWAPOUT) - printf("swapout_threads: no duds, try procp %p\n", p); + printf("swapout_threads: no duds, try procpr %p\n", + outpr); #endif - if (p) - pmap_collect(p->p_vmspace->vm_map.pmap); + pmap_collect(outpr->ps_vmspace->vm_map.pmap); } } diff --git a/sys/uvm/uvm_map.c b/sys/uvm/uvm_map.c index 5d668e16c4e..1648d40ec53 100644 --- a/sys/uvm/uvm_map.c +++ b/sys/uvm/uvm_map.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uvm_map.c,v 1.167 2014/04/13 23:14:15 tedu Exp $ */ +/* $OpenBSD: uvm_map.c,v 1.168 2014/05/15 03:52:25 guenther Exp $ */ /* $NetBSD: uvm_map.c,v 1.86 2000/11/27 08:40:03 chs Exp $ */ /* @@ -3015,15 +3015,16 @@ uvmspace_init(struct vmspace *vm, struct pmap *pmap, vaddr_t min, vaddr_t max, * uvmspace_share: share a vmspace between two processes * * - XXX: no locking on vmspace - * - used for vfork and threads + * - used for vfork */ -void -uvmspace_share(p1, p2) - struct proc *p1, *p2; +struct vmspace * +uvmspace_share(struct process *pr) { - p2->p_vmspace = p1->p_vmspace; - p1->p_vmspace->vm_refcnt++; + struct vmspace *vm = pr->ps_vmspace; + + vm->vm_refcnt++; + return vm; } /* @@ -3035,7 +3036,8 @@ uvmspace_share(p1, p2) void uvmspace_exec(struct proc *p, vaddr_t start, vaddr_t end) { - struct vmspace *nvm, *ovm = p->p_vmspace; + struct process *pr = p->p_p; + struct vmspace *nvm, *ovm = pr->ps_vmspace; struct vm_map *map = &ovm->vm_map; struct uvm_map_deadq dead_entries; @@ -3049,8 +3051,9 @@ uvmspace_exec(struct proc *p, vaddr_t start, vaddr_t end) /* see if more than one process is using this vmspace... */ if (ovm->vm_refcnt == 1) { /* - * if p is the only process using its vmspace then we can safely - * recycle that vmspace for the program that is being exec'd. + * If pr is the only process using its vmspace then + * we can safely recycle that vmspace for the program + * that is being exec'd. */ #ifdef SYSVSHM @@ -3104,16 +3107,16 @@ uvmspace_exec(struct proc *p, vaddr_t start, vaddr_t end) pmap_remove_holes(map); } else { /* - * p's vmspace is being shared, so we can't reuse it for p since - * it is still being used for others. allocate a new vmspace - * for p + * pr's vmspace is being shared, so we can't reuse + * it for pr since it is still being used for others. + * allocate a new vmspace for pr */ nvm = uvmspace_alloc(start, end, (map->flags & VM_MAP_PAGEABLE) ? TRUE : FALSE, TRUE); /* install new vmspace and drop our ref to the old one. */ pmap_deactivate(p); - p->p_vmspace = nvm; + p->p_vmspace = pr->ps_vmspace = nvm; pmap_activate(p); uvmspace_free(ovm); @@ -3409,8 +3412,9 @@ uvm_mapent_forkcopy(struct vmspace *new_vm, struct vm_map *new_map, * => parent's map must not be locked. */ struct vmspace * -uvmspace_fork(struct vmspace *vm1) +uvmspace_fork(struct process *pr) { + struct vmspace *vm1 = pr->ps_vmspace; struct vmspace *vm2; struct vm_map *old_map = &vm1->vm_map; struct vm_map *new_map; -- 2.20.1