aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/sysv_sem.c
diff options
context:
space:
mode:
authorTim J. Robbins <tjr@FreeBSD.org>2003-11-10 07:22:41 +0000
committerTim J. Robbins <tjr@FreeBSD.org>2003-11-10 07:22:41 +0000
commit541c3b66b54f9a1939768fe89b33b8daa24fc5f5 (patch)
tree4cdf6b9d8d468aa257f8486e7c4620bcc0ea1697 /sys/kern/sysv_sem.c
parent9422d61a1fc0cb13505a2bc3926fae156ab7d6be (diff)
downloadsrc-541c3b66b54f9a1939768fe89b33b8daa24fc5f5.tar.gz
src-541c3b66b54f9a1939768fe89b33b8daa24fc5f5.zip
When there are no free sem_undo structs available in semu_alloc(), only
free one sem_undo with un_cnt == 0 instead of all of them. This is a temporary workaround until the SLIST_FOREACH_PREVPTR loop gets fixed so that it doesn't cause cycles in semu_list when removing multiple adjacent items. It might be easier to just use (doubly-linked) LISTs here instead of complicated SLIST code to achieve O(1) removals. This bug manifested itself as a complete lockup under heavy semaphore use by multiple processes with the SEM_UNDO flag set. PR: 58984
Notes
Notes: svn path=/head/; revision=122390
Diffstat (limited to 'sys/kern/sysv_sem.c')
-rw-r--r--sys/kern/sysv_sem.c7
1 files changed, 4 insertions, 3 deletions
diff --git a/sys/kern/sysv_sem.c b/sys/kern/sysv_sem.c
index 9fbbf8c9c302..0887828462c3 100644
--- a/sys/kern/sysv_sem.c
+++ b/sys/kern/sysv_sem.c
@@ -310,7 +310,7 @@ semu_alloc(td)
SEMUNDO_LOCKASSERT(MA_OWNED);
/*
* Try twice to allocate something.
- * (we'll purge any empty structures after the first pass so
+ * (we'll purge an empty structure after the first pass so
* two passes are always enough)
*/
@@ -332,11 +332,11 @@ semu_alloc(td)
/*
* We didn't find a free one, if this is the first attempt
- * then try to free some structures.
+ * then try to free a structure.
*/
if (attempt == 0) {
- /* All the structures are in use - try to free some */
+ /* All the structures are in use - try to free one */
int did_something = 0;
SLIST_FOREACH_PREVPTR(suptr, supptr, &semu_list,
@@ -345,6 +345,7 @@ semu_alloc(td)
suptr->un_proc = NULL;
did_something = 1;
*supptr = SLIST_NEXT(suptr, un_next);
+ break;
}
}