Subject: use of wakeup_one by kern_lock.c vs. mixed shared/exclusive locks..
To: None <tech-kern@netbsd.org>
From: Bill Sommerfeld <sommerfeld@netbsd.org>
List: tech-kern
Date: 09/27/2001 16:08:02
It appears that the following wedge is possible:

Initial state:
	lock is held exclusive by A, with two waiters:
		- B wants exclusive access
		- C wants shared access

A: lockmgr(&lock, LK_RELEASE, ...);
this does a wakeup_one(&lock);

The scheduler picks "C".

C wakes up, sees that WANT_EXCL is set in the lock, so it goes back to
sleep because writers have priority over readers.

B is never woken up, and we wedge with an unlock lock with only
LK_WANT_EXCL set.

We might get unwedged if another process could come along and try to
take an exclusive lock, but in the case I observed, this is not
possible; the locks were vnode locks, and the parent directory lock
was held exclusively by either B or C, so nobody else of interest
could get the vnode in question.

Fix:

Use wakeup() instead of wakeup_one().

Now, either the ACQUIRE macro could (a) do a wakeup_one to "pass the
ball" in this case, but it is likely to be difficult to get this
right....

Moreover, doing a wakeup_one() when there are multiple *readers*
waiting doesn't make any sense; it would seem that the only time
wakeup_one() would be safe is if a lock is *only* used exclusively.

						- Bill