Subject: Re: use of wakeup_one by kern_lock.c vs. mixed shared/exclusive locks..
To: None <sommerfeld@netbsd.org>
From: Darren Reed <darrenr@reed.wattle.id.au>
List: tech-kern
Date: 09/30/2001 16:08:26
In some email I received from Bill Sommerfeld, sie wrote:
> 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.

Is there something we can do to code this rule into place ?

For example, make wakeup_one() panic when it sees this condition, or
automatically call wakeup() instead, maybe ?

Darren