summaryrefslogtreecommitdiff
path: root/sys/kern/sysv_sem.c
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>2002-12-30 18:41:28 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>2002-12-30 18:41:28 +0000
commit5efde0d4c7dbdd7f581189e4ab5e80e5eb02f32e (patch)
tree97a1333e0ec8f20d11891fa9a9cf96835de17979 /sys/kern/sysv_sem.c
parent5437fbf5f093482f01b82b7a8df54f74374b90e3 (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.c23
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;