SPL(K) UNIX System V SPL(K)
Name
spl: spl0, spl1, spl2, spl3, spl4, spl5, spl6, spl7, splbuf,
splcli, splhi, splni, splpp, spltty, splx - block/permit
interrupts
Syntax
int int int int
spl0() spl4() splbuf() splpp()
int int int int
spl1() spl5() splcli() spltty()
int int int
spl2() spl6() splhi()
int int int
spl3() spl7() splni()
int
splx(oldspl)
int oldspl;
Description
In many drivers, a need exists to protect sections of code
from an interrupt occuring and causing a context switch.
Protecting code sections ensures the integrity of the kernel
and its data structures. The spl1, spl2, spl3, spl4, spl5,
spl6, spl7, splbuf, splcli, splni, splpp and spltty routines
prevent specific levels of interrupts from occuring. The
following table describes each of the spl routines:
_________________________________________________________________________
| Routine| IPL| Description |
|________|_____|_________________________________________________________|
| spl0 | 0 | Permit all interrupts to occur |
|________|_____|_________________________________________________________|
| spl1 | 1 | Prevent interrupts from context and process switches |
|________|_____|_________________________________________________________|
| spl2 | 2 | Prevent priority level 2 interrupts |
|________|_____|_________________________________________________________|
| spl3 | 3 | Prevent priority level 3 interrupts |
|________|_____|_________________________________________________________|
| spl4 | 4 | Prevent character device interrupts |
|________|_____|_________________________________________________________|
| spl5 | 5 | Prevent interrupts from character devices, |
| splcli | | from a ports card, and from tty devices. |
| splpp | | |
|________|_____|_________________________________________________________|
| spl6 | 6 | Prevent interrupts from block devices, network devices,|
| splbuf | | and the clock. |
| splni | | |
|________|_____|_________________________________________________________|
| spltty | 7 | Prevent tty interrupts (and the clock) |
|________|_____|_________________________________________________________|
| spl7 | 8 | Prevent all interrupts |
| splhi | | |
|________|_____|_________________________________________________________|
| splx | - | Restore interrupt level to a former level |
|________|_____|_________________________________________________________|
IPL stands for interrupt priority level. The IPL value for
a device is set on its card.
spl0 permits all interrupts to occur. splx restores the
interrupt level to that specified by its argument oldspl.
Use of spl0 is not encouraged because by restoring all
interrupts, you may undo a previously set level by a kernel
process or routine calling your driver. Use splx whenever
possible to restore a previously set level. When coding an
interrupt routine, only use splx.
The spl5 and splcli routines prevent interrupts associated
with tty devices and those that use character lists (clists)
to buffer data. spl5 is provided for backward compatibility
only. If you are writing a serial device driver, use splcli
whenever possible. splcli should be used to protect
critical sections of code which manipulate clist structures
or pointers. It is possible that a device driver's xxpoll
routine will preempt another driver while it is manipulating
clists. If your xxpoll routine manipulates clist
structures, you should exercise care to make sure that your
routine was not entered at an spl level higher than 5.
Otherwise you may corrupt the kernel cfreelist. Do not
manipulate clists in an interrupt routine. It is not
necessary to use splcli before calling any of the cblock or
clist routines (the routines on the getc(K) and putc(K)
manual pages) because these routines raise the system
priority level before entering their critical sections and
then restore it to its previous value before they return.
It is only necessary for you to use splcli if you are
directly manipulating fields in a clist structure or the
freelist. You should only do this if you have extensive
experience with character device drivers.
The spl6, splni, and splbuf routines mask all interrupts
except for those from the serial device. These routines
prevents block device interrupts from occuring. These
routines block the system clock and should be used sparingly
because if the code it is protecting takes longer than two
clock ticks to execute, the system clock is degraded.
The spltty routine blocks interrupts from a serial device.
The spl7 and splhi routines disable all interrupts. Use
this routine only for extremely short periods when updating
critical data structures that could be accessed by a high
priority device. These routines also block the system clock
and should not be allowed to execute longer than a single
clock tick.
The splx routine restores a previously set interrupt
priority level.
Parameters
The integer oldspl specifies a previous spl level, it should
only be set by the return value of a previous spl routine.
Warnings
The interrupt priority level in an interrupt routine must
not be dropped below the level at which the interrupt
occurred or the stack may become corrupted causing a system
panic or loss of data. Use of spl0 is not recommended as it
can lower previously set priority levels used by other
kernel processes. Always store the previous priority level
returned by the spl call and use splx to restore the
previous level at the end of your critical code section.
The spl7 and splhi routines block all interrupts. While
these routines are in effect, the following happens:
+ Clock interrupts do not occur.
+ Characters are not echoed back to the console.
+ The capslock, numlock, and scrolllock indicators do not
work.
+ Multi-screens cannot be switched.
+ If your driver hangs during this interval, the machine
must be power-cycled to regain control.
Return Value
The previous spl value is returned. It should be saved and
used to restore the spl level by a subsequent call to splx.
Notes
Use of spl6, spl7, and splhi can cause the software clock to
lose time and prevents other device drivers' xxpoll routines
from being called. This may have an unpredictable effect on
the behavior of other device drivers that require periodic
execution of their xxpoll routines.
Example
The following code fragments show how to check an spl level
in an xxpoll routine and demonstrate the use of splcli in a
task time routine.
/*
* This macro tells us if the previous spl level was "lev"
* or higher. PS_PRIMASK is defined in sys/param.h.
*/
#define ATSPL(lev,ps) ((ps) >= lev)
xxpoll(ps)
{
/*
* If we were at spl5 or higher before the clock tick, leave!
*/
if (ATSPL(5,ps)) {
return;
}
/*
** end xxpoll fragment.
*/
/*
* xxread(), xxwrite(), xxopen(), xxclose, and
* xxioctl() are all examples of task time routines
*/
xxread(dev)
int dev;
{
int oldspl;
/* set new spl and save old level in oldspl */
oldspl = splcli();
.
. /* perform clist operations */
.
/* restore saved spl */
splx(oldspl);
.
.
.
/*
** end task time fragment.
*/
}
(printed 7/7/89)