diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2002-12-30 18:41:28 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2002-12-30 18:41:28 +0000 |
commit | 5efde0d4c7dbdd7f581189e4ab5e80e5eb02f32e (patch) | |
tree | 97a1333e0ec8f20d11891fa9a9cf96835de17979 /sys/kern/sysv_sem.c | |
parent | 5437fbf5f093482f01b82b7a8df54f74374b90e3 (diff) |
If we can't allocate a struct sem_undo w/o sleeping, use PR_WAITOK
but then check to see that one with our struct proc was not allocated
in the meantime.
Diffstat (limited to 'sys/kern/sysv_sem.c')
-rw-r--r-- | sys/kern/sysv_sem.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c index 2183f7cc8be..9d97ff7fde2 100644 --- a/sys/kern/sysv_sem.c +++ b/sys/kern/sysv_sem.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sysv_sem.c,v 1.13 2002/12/29 21:58:15 millert Exp $ */ +/* $OpenBSD: sysv_sem.c,v 1.14 2002/12/30 18:41:27 millert Exp $ */ /* $NetBSD: sysv_sem.c,v 1.26 1996/02/09 19:00:25 christos Exp $ */ /* @@ -94,13 +94,28 @@ seminit(void) struct sem_undo * semu_alloc(struct proc *p) { - struct sem_undo *suptr; + struct sem_undo *suptr, *tmp; - if (semutot == seminfo.semmnu || - (suptr = pool_get(&semu_pool, 0)) == NULL) + if (semutot == seminfo.semmnu) return (NULL); /* no space */ + /* + * Allocate a semu w/o waiting if possible. + * If we do have to wait, we must check to verify that a semu + * with un_proc == p has not been allocated in the meantime. + */ semutot++; + if ((suptr = pool_get(&semu_pool, 0)) == NULL) { + tmp = pool_get(&semu_pool, PR_WAITOK); + for (suptr = semu_list; suptr != NULL; suptr = suptr->un_next) { + if (suptr->un_proc == p) { + pool_put(&semu_pool, tmp); + semutot--; + return (suptr); + } + } + suptr = tmp; + } suptr->un_cnt = 0; suptr->un_proc = p; suptr->un_next = semu_list; |