diff options
author | alc <alc@FreeBSD.org> | 2004-07-27 03:53:41 +0000 |
---|---|---|
committer | alc <alc@FreeBSD.org> | 2004-07-27 03:53:41 +0000 |
commit | 8a38bc6b2ce7980dbddef0dc33bfba51ec5d3824 (patch) | |
tree | 6d7127f6cedfdcd82a7c1768b6c913502023d8cf /sys/vm/vm_map.c | |
parent | a745685147cf8bdd139918b29529822fc40acdf6 (diff) | |
download | FreeBSD-src-8a38bc6b2ce7980dbddef0dc33bfba51ec5d3824.zip FreeBSD-src-8a38bc6b2ce7980dbddef0dc33bfba51ec5d3824.tar.gz |
- 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.
Diffstat (limited to 'sys/vm/vm_map.c')
-rw-r--r-- | sys/vm/vm_map.c | 17 |
1 files changed, 11 insertions, 6 deletions
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); } |