Subject: Re: netbsd machines get slow and hang, nfs suspected
To: None <mycroft@mit.edu>
From: Gordon W. Ross <gwr@mc.com>
List: current-users
Date: 03/26/1996 11:33:44
> From: mycroft@mit.edu (Charles M. Hannum)
> Date: 26 Mar 1996 10:35:57 -0500

>    Interesting suggestion.  That reminds me:  The SunOS kernel has
> 
> 	   wakeone(int wchan); /* wakeup just one process */
> 
>    for use with things like widely used "mutex" locks, where we
>    don't care who gets to proceed, and we know only one process
>    will actually be allowed to proceed past the mutex.
> 
>    It would be nice to identify the comon places where we are
>    prone to the "thundering herd" problem, and change them to
>    use using wakeone() instead of wakeup().
> 
> There are really a couple of different cases here:
> 
> 1) tsleep() and wakeup() are being used for lock management.  The real
> distinction here is whether the process being woken up needs an
> exclusive or non-exclusive lock.  In this case, it should really be up
> to the tsleep() caller what happens.
> 
> 2) tsleep() and wakeup() are being used to handle resource depletion.
> In this case, it's really the caller of wakeup() that knows how many
> resources just became available.
> 
> It seems to me that a more flexible and less error-prone solution
> would be to write `real' lock and resource management systems.  These
> aren't particularly complicated, and they would also help with
> fine-grain MP locking...

That's true, and it would be nice to have a full muliti-threaded
kernel implementation too, but I'm not holding my breath.

The wakeone() trick is trivial to implement and is easily applied
any place one has code like the following: (lots of places!)

	while (foo->foo_flags & FOO_BUSY) {
		foo->foo_flags |= FOO_WANTED;
		tsleep((caddr_t)foo, PRIFOO, "foo", 0);
	}

	/* play with foo ... */

	if (foo->foo_flags & FOO_WANTED) {
		foo->foo_flags &= ~FOO_WANTED;
		/* no point in waking more than one */
		wakeone((caddr_t)foo);
	}

I hope this example demonstrates how easy it is to take advantage
of the wakeone() trick in cases like this.

Gordon