table of contents
SPL(9) | Kernel Developer's Manual | SPL(9) |
NAME¶
splbio, splclock, splhigh, splimp, splnet, splsoftclock, splsofttty, splstatclock, spltty, splvm, spl0, splx — manipulate interrupt prioritiesSYNOPSIS¶
#include <sys/types.h>#include <sys/systm.h> intrmask_t
splbio(void); intrmask_t
splclock(void); intrmask_t
splhigh(void); intrmask_t
splimp(void); intrmask_t
splnet(void); intrmask_t
splsoftclock(void); intrmask_t
splsofttty(void); intrmask_t
splstatclock(void); intrmask_t
spltty(void); void
spl0(void); void
splx(intrmask_t ipl);
DESCRIPTION¶
This API is
deprecated. Use mutexes to protect data structures instead. See
mutex(9) for more information. The API is now a complete
NOP. This man page documents historical behavior so you can understand the
code locking that the spl did when converting code from versions of the kernel
prior to FreeBSD 5.0. The examples in this man page
are also obsolete and should not be viewed as documenting
FreeBSD 5.0 and newer.
The spl() function family sets the interrupt priority
“level” of the CPU. This prevents interrupt handlers of the
blocked priority level from being run. This is used in the
“synchronous” part of a driver (the part that runs on behalf of
the user process) to examine or modify data areas that might be examined or
modified by interrupt handlers.
Each driver that uses interrupts is normally assigned to an interrupt priority
group by a keyword in its config line. For example:
device foo0 at isa? port 0x0815 irq 12 tty
- splnet()
- Software part of the network interface drivers.
- splimp()
- All network interface drivers.
- splbio()
- All buffered IO (i.e., disk and the like) drivers.
- spltty()
- Basically, all non-network communications devices, but effectively used for all drivers that are neither network nor disks.
RETURN VALUES¶
All functions except splx() and spl0() return the previous priority value.EXAMPLES¶
This is a typical example demonstrating the usage:struct foo_softc { ... int flags; #define FOO_ASLEEP 1 #define FOO_READY 2 } foo_softc[NFOO]; int foowrite(...) { struct foo_softc *sc; int s, error; ... s = spltty(); if (!(sc->flags & FOO_READY)) { /* Not ready, must sleep on resource. */ sc->flags |= FOO_ASLEEP; error = tsleep(sc, PZERO, "foordy", 0); sc->flags &= ~FOO_ASLEEP; } sc->flags &= ~FOO_READY; splx(s); ... } void foointr(...) { struct foo_softc *sc; ... sc->flags |= FOO_READY; if (sc->flags & FOO_ASLEEP) /* Somebody was waiting for us, awake him. */ wakeup(sc); ... }
HISTORY¶
The interrupt priority levels appeared in a very early version of UNIX. They have been traditionally known by number instead of by names, and were inclusive up to higher priority levels (i.e., priority 5 has been blocking everything up to level 5). This is no longer the case in FreeBSD. The traditional name ‘level
’ for them is still reflected in the
letter ‘l
’ of the respective functions and
variables, although they are not really levels anymore, but rather different
(partially inclusive) sets of functions to be blocked during some periods of
the life of the system. The historical number scheme can be considered as a
simple linearly ordered set of interrupt priority groups.
FreeBSD 5.0 eliminated spl entirely in favor of locking
primitives which scale to more than one processor.
AUTHORS¶
This manual page was written by Jörg Wunsch.July 21, 1996 | Debian |