Subject: Re: spl models and smp (was Re: Some interesting papers on BSD ...)
To: None <michaelh@cet.co.jp>
From: Gordon W. Ross <gwr@mc.com>
List: tech-kern
Date: 09/19/1996 09:26:42
> Date: Thu, 19 Sep 1996 10:59:37 +0900 (JST)
> From: Michael Hancock <michaelh@cet.co.jp>

> [Just going through some old mail]
> 
> I was reviewing some spl and locking models for SMP.  SVR4/MP combines
> locking primitives with spl and Solaris is completely redesigned to the
> implementation to use kernel threads instead for interrupts so it can use
> the same locking model as the rest of the code. 

Actually, I'm pretty sure that's not quite true.  Here is how it works.
The relevant parts of the interface are:

  /* This is a mutex lock.  It MIGHT lock out interrupts. */
  kmutex_t driver_mutex;

  /* Somewhere, during initialization (attach) you do this: */
  mutex_init(&driver_mutex, "mcos", MUTEX_DRIVER, (void*)&driver_ibcookie);

  /* Then, a section that needs atomic actions is wrapped with: */
  mutex_enter(&driver_mutex);
  /* now have exclusive access to the object locked with this mutex. */
  mutex_exit(&driver_mutex);
  /* now others may take the mutex lock. */

The way these block interrupts is: if the driver_ibcookie (which
was returned to you when you attached your interrupt handler) is
passed to mutex_init, rather than a null pointer, then anyone who
does a mutex_enter() on that mutex will raise their spl as needed
to block that interrupt, and then spin-wait.  The spin-wait will
never have to actually spin unless there is another CPU that holds
the mutex.  When we take the mutex from non-interrupt level, the
mutex_enter() will have raised the spl() such that we don't have
to worry about deadlocking against our own interrupt handler.

Also note that Solaris no longer supports sleep/wakeup in MP drivers.
Instead, you use these new functions:

  /* Here is the equivalent to the old sleep() call: */
  status = cv_timedwait_sig(&sp->condvar, &driver_mutex, abst);

  /* Here is the equivalent to the old wakeup() call: */
  cv_signal(&sp->condvar);

Note that you MUST hold a mutex lock on some object that has both
the mutex and a condition variable, adn the cv_timedwait_sig()
does an atomic "block and release the mutex" while making you
non-runnable, and later does an atomic "resume and take mutex."
Interesting scheme, eh?

Gordon