diff options
author | Tim J. Robbins <tjr@FreeBSD.org> | 2003-11-10 07:22:41 +0000 |
---|---|---|
committer | Tim J. Robbins <tjr@FreeBSD.org> | 2003-11-10 07:22:41 +0000 |
commit | 541c3b66b54f9a1939768fe89b33b8daa24fc5f5 (patch) | |
tree | 4cdf6b9d8d468aa257f8486e7c4620bcc0ea1697 /sys/kern/sysv_sem.c | |
parent | 9422d61a1fc0cb13505a2bc3926fae156ab7d6be (diff) | |
download | src-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.c | 7 |
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; } } |