| SPL(9) | Kernel Developer's Manual | SPL(9) | 
spl, spl0,
  splhigh, splvm,
  splbio, splnet,
  spltty, splsched,
  splsoftbio, splsoftclock,
  splsoftnet, splsoftserial,
  splx —
#include <sys/intr.h>
void
  
  spl0(void);
int
  
  splhigh(void);
int
  
  splsched(void);
int
  
  splvm(void);
int
  
  splbio(void);
int
  
  splnet(void);
int
  
  spltty(void);
int
  
  splsoftbio(void);
int
  
  splsoftclock(void);
int
  
  splsoftserial(void);
int
  
  splsoftnet(void);
void
  
  splx(int
    s);
In a multi-CPU system, these functions change the interrupt priority level on the local CPU only. In general, device drivers should not make use of these interfaces. To ensure correct synchronization, device drivers should use the condvar(9), mutex(9), and rwlock(9) interfaces.
Interrupt priorities are arranged in a strict hierarchy, although sometimes levels may be equivalent (overlap). The hierarchy means that raising the IPL to any level will block interrupts at that level, and at all lower levels. The hierarchy is used to minimize data loss due to interrupts not being serviced in a timely fashion.
The levels may be divided into two groups: hard and soft. Hard interrupts are generated by hardware devices. Soft interrupts are a way of deferring hardware interrupts to do more expensive processing at a lower interrupt priority, and are explicitly scheduled by the higher-level interrupt handler. Software interrupts are further described by softint(9).
Note that hard interrupt handlers do not possess process (thread) context and so it is not valid to use kernel facilities that may attempt to sleep from a hardware interrupt. For example, it is not possible to acquire a reader/writer lock from a hardware interrupt. Soft interrupt handlers possess limited process context and so may sleep briefly in order to acquire a reader/writer lock or adaptive mutex, but may not sleep for any other reason.
In order of highest to lowest priority, the priority-raising functions along with their counterpart symbolic tags are:
splhigh(), IPL_HIGHBlocks all hard and soft interrupts, including the highest level I/O interrupts, such as interrupts from serial interfaces and the statistics clock (if any). It is also used for code that cannot tolerate any interrupts.
Code running at this level may not (in general) directly
        access machine independent kernel services. For example, it is illegal
        to call the kernel printf() function or to try
        and allocate memory. The methods of synchronization available are: spin
        mutexes and scheduling a soft interrupt. Generally, all code run at this
        level must schedule additional processing to run in a software
        interrupt.
Code with thread context running at this level must not use a kernel interface that may cause the current LWP to sleep, such as the condvar(9) interfaces.
Interrupt handlers at this level cannot acquire the global kernel_lock and so must be coded to ensure correct synchronization on multiprocessor systems.
splsched(), IPL_SCHEDBlocks all medium priority hardware interrupts, such as interrupts from audio devices, and the clock interrupt.
Interrupt handlers running at this level endure the same restrictions as at IPL_HIGH, but may access scheduler interfaces, and so may awaken LWPs (light weight processes) using the condvar(9) interfaces, and may schedule callouts using the callout(9) interfaces.
Code with thread context running at this level may sleep via the condvar(9) interfaces, and may use other kernel facilities that could cause the current LWP to sleep.
splvm(), IPL_VMBlocks hard interrupts from “low” priority hardware interrupts, such as interrupts from network, block I/O and tty devices.
Code running at this level endures the same restrictions as at IPL_SCHED, but may use the deprecated malloc(9) or endorsed pool_cache(9) interfaces to allocate memory.
The global kernel_lock is
        automatically acquired for interrupts at this level by default, in order
        to support device drivers that do not provide their own multiprocessor
        synchronization. The automatic acquisition of
        kernel_lock can be disabled for individual
        interrupt handlers by device drivers if supported by subsystem, see e.g.
        pci_intr_establish(9).
splbio(),
        splnet(), and spltty()
        are synonyms for splvm(). Their use is
        deprecated; all new code should use splvm().
splsoftserial(), IPL_SOFTSERIALBlocks soft interrupts at the IPL_SOFTSERIAL symbolic level.
This is the first of the software levels. Soft interrupts at this level and lower may acquire reader/writer locks or adaptive mutexes.
splsoftnet(), IPL_SOFTNETBlocks soft interrupts at the IPL_SOFTNET symbolic level.
splsoftbio(), IPL_SOFTBIOBlocks soft interrupts at the IPL_SOFTBIO symbolic level.
splsoftclock(), IPL_SOFTCLOCKBlocks soft interrupts at the IPL_SOFTCLOCK symbolic level.
This is the priority at which callbacks generated by the callout(9) facility runs.
One function lowers the system priority level:
spl0(), IPL_NONEUnblocks all interrupts. This should rarely be used directly;
        splx() should be used instead.
The splx() function restores the system
    priority level to the one encoded in s, which must be
    a value previously returned by one of the other spl
    functions.
splnet() was used to
  block network software interrupts. Most device drivers used
  splimp() to block hardware interrupts. To avoid
  unnecessarily blocking other interrupts, in NetBSD 1.1
  a new function was added that blocks only network hardware interrupts. For
  consistency with other spl functions, the old
  splnet() function was renamed to
  splsoftnet(), and the new function was named
  splnet().
Originally, splsoftclock() lowered the
    system priority level. During the NetBSD 1.5
    development cycle, spllowersoftclock() was
    introduced and the semantics of splsoftclock() were
    changed.
The splimp() call was removed from the
    kernel between NetBSD 1.5 and
    NetBSD 1.6. The function of
    splimp() was replaced by
    splvm() and code which abused the semantics of
    splimp() was changed to not mix interrupt priority
    levels.
Between NetBSD 4.0 and NetBSD 5.0, the hardware levels were reduced in number and a strict hierarchy defined.
| April 7, 2020 | NetBSD 10.0 |