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