summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/kern_exec.c3
-rw-r--r--sys/kern/kern_exit.c3
-rw-r--r--sys/kern/sysv_ipc.c7
-rw-r--r--sys/kern/sysv_shm.c32
-rw-r--r--sys/sys/ipc.h3
-rw-r--r--sys/sys/shm.h3
-rw-r--r--sys/vm/vm_map.c8
7 files changed, 32 insertions, 27 deletions
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 543bd6a..0ee36ba 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -864,8 +864,7 @@ exec_new_vmspace(imgp, sv)
map = &vmspace->vm_map;
if (vmspace->vm_refcnt == 1 && vm_map_min(map) == sv->sv_minuser &&
vm_map_max(map) == sv->sv_maxuser) {
- if (vmspace->vm_shm)
- shmexit(p);
+ shmexit(vmspace);
vm_page_lock_queues();
pmap_remove_pages(vmspace_pmap(vmspace), vm_map_min(map),
vm_map_max(map));
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 8737bed..c34f26f 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -297,8 +297,7 @@ exit1(td, rv)
*/
++vm->vm_exitingcnt;
if (--vm->vm_refcnt == 0) {
- if (vm->vm_shm)
- shmexit(p);
+ shmexit(vm);
vm_page_lock_queues();
pmap_remove_pages(vmspace_pmap(vm), vm_map_min(&vm->vm_map),
vm_map_max(&vm->vm_map));
diff --git a/sys/kern/sysv_ipc.c b/sys/kern/sysv_ipc.c
index fc5fd8f..55d39de 100644
--- a/sys/kern/sysv_ipc.c
+++ b/sys/kern/sysv_ipc.c
@@ -42,7 +42,7 @@
#include <sys/ucred.h>
void (*shmfork_hook)(struct proc *, struct proc *) = NULL;
-void (*shmexit_hook)(struct proc *) = NULL;
+void (*shmexit_hook)(struct vmspace *) = NULL;
/* called from kern_fork.c */
void
@@ -57,12 +57,11 @@ shmfork(p1, p2)
/* called from kern_exit.c */
void
-shmexit(p)
- struct proc *p;
+shmexit(struct vmspace *vm)
{
if (shmexit_hook != NULL)
- shmexit_hook(p);
+ shmexit_hook(vm);
return;
}
diff --git a/sys/kern/sysv_shm.c b/sys/kern/sysv_shm.c
index 6c9d34a..04c9b2a 100644
--- a/sys/kern/sysv_shm.c
+++ b/sys/kern/sysv_shm.c
@@ -97,12 +97,12 @@ static void shm_deallocate_segment(struct shmid_ds *);
static int shm_find_segment_by_key(key_t);
static struct shmid_ds *shm_find_segment_by_shmid(int);
static struct shmid_ds *shm_find_segment_by_shmidx(int);
-static int shm_delete_mapping(struct proc *p, struct shmmap_state *);
+static int shm_delete_mapping(struct vmspace *vm, struct shmmap_state *);
static void shmrealloc(void);
static void shminit(void);
static int sysvshm_modload(struct module *, int, void *);
static int shmunload(void);
-static void shmexit_myhook(struct proc *p);
+static void shmexit_myhook(struct vmspace *vm);
static void shmfork_myhook(struct proc *p1, struct proc *p2);
static int sysctl_shmsegs(SYSCTL_HANDLER_ARGS);
@@ -214,9 +214,7 @@ shm_deallocate_segment(shmseg)
}
static int
-shm_delete_mapping(p, shmmap_s)
- struct proc *p;
- struct shmmap_state *shmmap_s;
+shm_delete_mapping(struct vmspace *vm, struct shmmap_state *shmmap_s)
{
struct shmid_ds *shmseg;
int segnum, result;
@@ -227,8 +225,7 @@ shm_delete_mapping(p, shmmap_s)
segnum = IPCID_TO_IX(shmmap_s->shmid);
shmseg = &shmsegs[segnum];
size = round_page(shmseg->shm_segsz);
- result = vm_map_remove(&p->p_vmspace->vm_map, shmmap_s->va,
- shmmap_s->va + size);
+ result = vm_map_remove(&vm->vm_map, shmmap_s->va, shmmap_s->va + size);
if (result != KERN_SUCCESS)
return (EINVAL);
shmmap_s->shmid = -1;
@@ -278,7 +275,7 @@ shmdt(td, uap)
error = EINVAL;
goto done2;
}
- error = shm_delete_mapping(p, shmmap_s);
+ error = shm_delete_mapping(p->p_vmspace, shmmap_s);
done2:
mtx_unlock(&Giant);
return (error);
@@ -768,20 +765,21 @@ shmfork_myhook(p1, p2)
}
static void
-shmexit_myhook(p)
- struct proc *p;
+shmexit_myhook(struct vmspace *vm)
{
- struct shmmap_state *shmmap_s;
+ struct shmmap_state *base, *shm;
int i;
GIANT_REQUIRED;
- shmmap_s = p->p_vmspace->vm_shm;
- for (i = 0; i < shminfo.shmseg; i++, shmmap_s++)
- if (shmmap_s->shmid != -1)
- shm_delete_mapping(p, shmmap_s);
- free(p->p_vmspace->vm_shm, M_SHM);
- p->p_vmspace->vm_shm = NULL;
+ if ((base = vm->vm_shm) != NULL) {
+ vm->vm_shm = NULL;
+ for (i = 0, shm = base; i < shminfo.shmseg; i++, shm++) {
+ if (shm->shmid != -1)
+ shm_delete_mapping(vm, shm);
+ }
+ free(base, M_SHM);
+ }
}
static void
diff --git a/sys/sys/ipc.h b/sys/sys/ipc.h
index e78082a..c79c857 100644
--- a/sys/sys/ipc.h
+++ b/sys/sys/ipc.h
@@ -115,10 +115,11 @@ struct ipc_perm {
struct thread;
struct proc;
+struct vmspace;
int ipcperm(struct thread *, struct ipc_perm *, int);
extern void (*shmfork_hook)(struct proc *, struct proc *);
-extern void (*shmexit_hook)(struct proc *);
+extern void (*shmexit_hook)(struct vmspace *);
#else /* ! _KERNEL */
diff --git a/sys/sys/shm.h b/sys/sys/shm.h
index b5ce766..6d66384 100644
--- a/sys/sys/shm.h
+++ b/sys/sys/shm.h
@@ -97,8 +97,9 @@ struct shm_info {
struct thread;
struct proc;
+struct vmspace;
-void shmexit(struct proc *);
+void shmexit(struct vmspace *);
void shmfork(struct proc *, struct proc *);
#else /* !_KERNEL */
diff --git a/sys/vm/vm_map.c b/sys/vm/vm_map.c
index 97d7c6d..6c53b7f 100644
--- a/sys/vm/vm_map.c
+++ b/sys/vm/vm_map.c
@@ -80,6 +80,7 @@
#include <sys/resourcevar.h>
#include <sys/sysent.h>
#include <sys/stdint.h>
+#include <sys/shm.h>
#include <vm/vm.h>
#include <vm/vm_param.h>
@@ -284,6 +285,13 @@ static __inline void
vmspace_dofree(struct vmspace *vm)
{
CTR1(KTR_VM, "vmspace_free: %p", vm);
+
+ /*
+ * Make sure any SysV shm is freed, it might not have been in
+ * exit1().
+ */
+ shmexit(vm);
+
/*
* Lock the map, to wait out all other references to it.
* Delete all of the mappings and pages they hold, then call
OpenPOWER on IntegriCloud