From 8a38bc6b2ce7980dbddef0dc33bfba51ec5d3824 Mon Sep 17 00:00:00 2001 From: alc Date: Tue, 27 Jul 2004 03:53:41 +0000 Subject: - Use atomic ops for updating the vmspace's refcnt and exitingcnt. - Push down Giant into shmexit(). (Giant is acquired only if the vmspace contains shm segments.) - Eliminate the acquisition of Giant from proc_rwmem(). - Reduce the scope of Giant in exit1(), uncovering the destruction of the address space. --- sys/kern/kern_exit.c | 10 +++++++--- sys/kern/sys_process.c | 18 +++++++----------- sys/kern/sysv_shm.c | 4 ++-- sys/kern/vfs_aio.c | 2 +- sys/vm/vm_glue.c | 4 ++-- sys/vm/vm_map.c | 17 +++++++++++------ 6 files changed, 30 insertions(+), 25 deletions(-) (limited to 'sys') diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index a268771..78f3feb 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -114,6 +114,7 @@ exit1(struct thread *td, int rv) struct ucred *tracecred; #endif struct plimit *plim; + int refcnt; /* * Drop Giant if caller has it. Eventually we should warn about @@ -254,7 +255,6 @@ retry: } mtx_unlock(&ppeers_lock); - mtx_lock(&Giant); /* The next two chunks should probably be moved to vmspace_exit. */ vm = p->p_vmspace; /* @@ -272,8 +272,11 @@ retry: * by vmspace_exit() (which decrements exitingcnt) cleans up the * remainder. */ - ++vm->vm_exitingcnt; - if (--vm->vm_refcnt == 0) { + atomic_add_int(&vm->vm_exitingcnt, 1); + do + refcnt = vm->vm_refcnt; + while (!atomic_cmpset_int(&vm->vm_refcnt, refcnt, refcnt - 1)); + if (refcnt == 1) { shmexit(vm); pmap_remove_pages(vmspace_pmap(vm), vm_map_min(&vm->vm_map), vm_map_max(&vm->vm_map)); @@ -281,6 +284,7 @@ retry: vm_map_max(&vm->vm_map)); } + mtx_lock(&Giant); sx_xlock(&proctree_lock); if (SESS_LEADER(p)) { struct session *sp; diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c index 11bbe3e..9dad83a 100644 --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -153,24 +153,21 @@ proc_rwmem(struct proc *p, struct uio *uio) vm_object_t backing_object, object = NULL; vm_offset_t pageno = 0; /* page number */ vm_prot_t reqprot; - int error, writing; + int error, refcnt, writing; - mtx_lock(&Giant); /* * if the vmspace is in the midst of being deallocated or the * process is exiting, don't try to grab anything. The page table * usage in that process can be messed up. */ vm = p->p_vmspace; - if ((p->p_flag & P_WEXIT)) { - mtx_unlock(&Giant); + if ((p->p_flag & P_WEXIT)) return (EFAULT); - } - if (vm->vm_refcnt < 1) { - mtx_unlock(&Giant); - return (EFAULT); - } - ++vm->vm_refcnt; + do { + if ((refcnt = vm->vm_refcnt) < 1) + return (EFAULT); + } while (!atomic_cmpset_int(&vm->vm_refcnt, refcnt, refcnt + 1)); + /* * The map we want... */ @@ -278,7 +275,6 @@ proc_rwmem(struct proc *p, struct uio *uio) } while (error == 0 && uio->uio_resid > 0); vmspace_free(vm); - mtx_unlock(&Giant); return (error); } diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c index 1430942..0b016f1 100644 --- a/sys/kern/sysv_shm.c +++ b/sys/kern/sysv_shm.c @@ -822,14 +822,14 @@ shmexit_myhook(struct vmspace *vm) struct shmmap_state *base, *shm; int i; - GIANT_REQUIRED; - if ((base = vm->vm_shm) != NULL) { vm->vm_shm = NULL; + mtx_lock(&Giant); for (i = 0, shm = base; i < shminfo.shmseg; i++, shm++) { if (shm->shmid != -1) shm_delete_mapping(vm, shm); } + mtx_unlock(&Giant); free(base, M_SHM); } } diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c index a56a54f..6d47c78 100644 --- a/sys/kern/vfs_aio.c +++ b/sys/kern/vfs_aio.c @@ -868,7 +868,7 @@ aio_daemon(void *uproc) * refer to it. */ mycp->p_vmspace = userp->p_vmspace; - mycp->p_vmspace->vm_refcnt++; + atomic_add_int(&mycp->p_vmspace->vm_refcnt, 1); /* Activate the new mapping. */ pmap_activate(FIRST_THREAD_IN_PROC(mycp)); diff --git a/sys/vm/vm_glue.c b/sys/vm/vm_glue.c index dd85fa9..4e083b8 100644 --- a/sys/vm/vm_glue.c +++ b/sys/vm/vm_glue.c @@ -638,7 +638,7 @@ vm_forkproc(td, p2, td2, flags) if (flags & RFMEM) { p2->p_vmspace = p1->p_vmspace; - p1->p_vmspace->vm_refcnt++; + atomic_add_int(&p1->p_vmspace->vm_refcnt, 1); } while (vm_page_count_severe()) { @@ -952,7 +952,7 @@ retry: vm = p->p_vmspace; KASSERT(vm != NULL, ("swapout_procs: a process has no address space")); - ++vm->vm_refcnt; + atomic_add_int(&vm->vm_refcnt, 1); PROC_UNLOCK(p); if (!vm_map_trylock(&vm->vm_map)) goto nextproc1; diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c index 3585b8a..cbeb906 100644 --- a/sys/vm/vm_map.c +++ b/sys/vm/vm_map.c @@ -311,13 +311,15 @@ vmspace_dofree(struct vmspace *vm) void vmspace_free(struct vmspace *vm) { - GIANT_REQUIRED; + int refcnt; if (vm->vm_refcnt == 0) panic("vmspace_free: attempt to free already freed vmspace"); - --vm->vm_refcnt; - if (vm->vm_refcnt == 0 && vm->vm_exitingcnt == 0) + do + refcnt = vm->vm_refcnt; + while (!atomic_cmpset_int(&vm->vm_refcnt, refcnt, refcnt - 1)); + if (refcnt == 1 && vm->vm_exitingcnt == 0) vmspace_dofree(vm); } @@ -325,8 +327,8 @@ void vmspace_exitfree(struct proc *p) { struct vmspace *vm; + int exitingcnt; - GIANT_REQUIRED; vm = p->p_vmspace; p->p_vmspace = NULL; @@ -341,8 +343,11 @@ vmspace_exitfree(struct proc *p) * The last wait on the exiting child's vmspace will clean up * the remainder of the vmspace. */ - --vm->vm_exitingcnt; - if (vm->vm_refcnt == 0 && vm->vm_exitingcnt == 0) + do + exitingcnt = vm->vm_exitingcnt; + while (!atomic_cmpset_int(&vm->vm_exitingcnt, exitingcnt, + exitingcnt - 1)); + if (vm->vm_refcnt == 0 && exitingcnt == 1) vmspace_dofree(vm); } -- cgit v1.1