Provided by: freebsd-manpages_8.2-1_all bug

NAME

     splbio, splclock, splhigh, splimp, splnet, splsoftclock, splsofttty, splstatclock, spltty,
     splvm, spl0, splx — manipulate interrupt priorities

SYNOPSIS

     #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

     assigns interrupt 12 to the “tty” priority group.  The system automatically arranges for
     interrupts in the xxx group to be called at a priority >= splxxx ().

     The function splx() sets the interrupt priority to an absolute value.  The intent is that
     the value returned by the other functions should be saved in a local variable, and later
     passed to splx() in order to restore the previous priority.

     The function spl0() lowers the priority to a value where all interrupt handlers are
     unblocked, but ASTs (asynchronous system traps) remain blocked until the system is about to
     return to user mode.

     The traditional assignment of the various device drivers to the interrupt priority groups
     can be roughly classified as:

     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);
             ...
     }

     Note that the interrupt handler should never reduce the priority level.  It is automatically
     called as it had raised the interrupt priority to its own level, i.e., further interrupts of
     the same group are being blocked.

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.