diff options
author | dd <dd@FreeBSD.org> | 2001-05-22 03:56:26 +0000 |
---|---|---|
committer | dd <dd@FreeBSD.org> | 2001-05-22 03:56:26 +0000 |
commit | 0ec004ce3fd5ebf40f7bfeb80da9d56daab1ab6e (patch) | |
tree | 8568d14af5de296c5cacb122785ad0afa21f1d4c /sys/kern/sysv_shm.c | |
parent | 5402ddb39e19e6bb7507aa58a3d4a95a247f2ba5 (diff) | |
download | FreeBSD-src-0ec004ce3fd5ebf40f7bfeb80da9d56daab1ab6e.zip FreeBSD-src-0ec004ce3fd5ebf40f7bfeb80da9d56daab1ab6e.tar.gz |
Correct the vm_mtx handling; specifically, don't acquire it in
shm_deallocate_segment because shmexit_myhook calls it, and the latter
should always be called with it already held.
Submitted by: dwmalone, dd
Approved by: alfred
Diffstat (limited to 'sys/kern/sysv_shm.c')
-rw-r--r-- | sys/kern/sysv_shm.c | 18 |
1 files changed, 13 insertions, 5 deletions
diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c index 5e8a638..7408e45 100644 --- a/sys/kern/sysv_shm.c +++ b/sys/kern/sysv_shm.c @@ -181,10 +181,10 @@ shm_deallocate_segment(shmseg) struct shm_handle *shm_handle; size_t size; + /* for vm_object_deallocate */ + mtx_assert(&vm_mtx, MA_OWNED); shm_handle = shmseg->shm_internal; - mtx_lock(&vm_mtx); vm_object_deallocate(shm_handle->shm_object); - mtx_unlock(&vm_mtx); free((caddr_t)shm_handle, M_SHM); shmseg->shm_internal = NULL; size = round_page(shmseg->shm_segsz); @@ -202,12 +202,12 @@ shm_delete_mapping(p, shmmap_s) int segnum, result; size_t size; + /* for vm_map_remove and shm_deallocate_segment */ + mtx_assert(&vm_mtx, MA_OWNED); segnum = IPCID_TO_IX(shmmap_s->shmid); shmseg = &shmsegs[segnum]; size = round_page(shmseg->shm_segsz); - mtx_lock(&vm_mtx); result = vm_map_remove(&p->p_vmspace->vm_map, shmmap_s->va, shmmap_s->va + size); - mtx_unlock(&vm_mtx); if (result != KERN_SUCCESS) return EINVAL; shmmap_s->shmid = -1; @@ -233,6 +233,7 @@ shmdt(p, uap) { struct shmmap_state *shmmap_s; int i; + int error; if (!jail_sysvipc_allowed && jailed(p->p_ucred)) return (ENOSYS); @@ -246,7 +247,10 @@ shmdt(p, uap) break; if (i == shminfo.shmseg) return EINVAL; - return shm_delete_mapping(p, shmmap_s); + mtx_lock(&vm_mtx); + error = shm_delete_mapping(p, shmmap_s); + mtx_unlock(&vm_mtx); + return error; } #ifndef _SYS_SYSPROTO_H_ @@ -455,7 +459,9 @@ shmctl(p, uap) shmseg->shm_perm.key = IPC_PRIVATE; shmseg->shm_perm.mode |= SHMSEG_REMOVED; if (shmseg->shm_nattch <= 0) { + mtx_lock(&vm_mtx); shm_deallocate_segment(shmseg); + mtx_unlock(&vm_mtx); shm_last_free = IPCID_TO_IX(uap->shmid); } break; @@ -663,6 +669,8 @@ shmexit_myhook(p) struct shmmap_state *shmmap_s; int i; + /* shm_delete_mapping requires this */ + mtx_assert(&vm_mtx, MA_OWNED); shmmap_s = (struct shmmap_state *)p->p_vmspace->vm_shm; for (i = 0; i < shminfo.shmseg; i++, shmmap_s++) if (shmmap_s->shmid != -1) |