LOCKING(9)             NetBSD Kernel Developer's Manual             LOCKING(9)

NAME
     locking -- introduction to kernel synchronization and interrupt control

DESCRIPTION
     The NetBSD kernel provides several synchronization and interrupt control
     primitives.  This man page aims to give an overview of these interfaces
     and their proper application.  Also included are basic kernel thread con-
     trol primitives and a rough overview of the NetBSD kernel design.

KERNEL OVERVIEW
     The aim of synchronization, threads and interrupt control in the kernel
     is:

              To control concurrent access to shared resources (critical sec-
               tions).

              Spawn tasks from an interrupt in the thread context.

              Mask interrupts from threads.

              Scale on multiple CPU system.

     There are three types of contexts in the NetBSD kernel:

              Thread context - running processes (represented by struct proc)
               and light-weight processes (represented by struct lwp, also
               known as kernel threads).  Code in this context can sleep,
               block resources and own address-space.

              Software interrupt context - limited by thread context.  Code
               in this context must be processed shortly.  These interrupts
               don't own any address space context.  Software interrupts are a
               way of deferring hardware interrupts to do more expensive pro-
               cessing at a lower interrupt priority.

              Hard interrupt context - Code in this context must be processed
               as quickly as possible.  It is forbidden for a piece of code to
               sleep or access long-awaited resources here.

     The main differences between processes and kernel threads are:

              A single process can own multiple kernel threads (LWPs).

              A process owns address space context to map userland address
               space.

              Processes are designed for userland executables and kernel
               threads for in-kernel tasks.  The only process running in the
               kernel-space is proc0 (called swapper).

INTERFACES
   Atomic memory operations
     The atomic_ops family of functions provide atomic memory operations.
     There are 7 classes of atomic memory operations available: addition, log-
     ical ``and'', compare-and-swap, decrement, increment, logical ``or'',
     swap.

     See atomic_ops(3).

   Condition variables
     Condition variables (CVs) are used in the kernel to synchronize access to
     resources that are limited (for example, memory) and to wait for pending
     I/O operations to complete.

     See condvar(9).

   Memory access barrier operations
     The membar_ops family of functions provide memory access barrier opera-
     tions necessary for synchronization in multiprocessor execution environ-
     ments that have relaxed load and store order.

     See membar_ops(3).

   Memory barriers
     The memory barriers can be used to control the order in which memory
     accesses occur, and thus the order in which those accesses become visible
     to other processors.  They can be used to implement ``lockless'' access
     to data structures where the necessary barrier conditions are well under-
     stood.

   Mutual exclusion primitives
     Thread-base adaptive mutexes.  These are lightweight, exclusive locks
     that use threads as the focus of synchronization activity.  Adaptive
     mutexes typically behave like spinlocks, but under specific conditions an
     attempt to acquire an already held adaptive mutex may cause the acquiring
     thread to sleep.  Sleep activity occurs rarely.  Busy-waiting is typi-
     cally more efficient because mutex hold times are most often short.  In
     contrast to pure spinlocks, a thread holding an adaptive mutex may be
     pre-empted in the kernel, which can allow for reduced latency where soft
     real-time application are in use on the system.

     See mutex(9).

   Restartable atomic sequences
     Restartable atomic sequences are user code only sequences which are guar-
     anteed to execute without preemption.  This property is assured by check-
     ing the set of restartable atomic sequences registered for a process dur-
     ing cpu_switchto(9).  If a process is found to have been preempted during
     a restartable sequence, then its execution is rolled-back to the start of
     the sequence by resetting its program counter which is saved in its
     process control block (PCB).

     See ras(9).

   Reader / writer lock primitives
     Reader / writer locks (RW locks) are used in the kernel to synchronize
     access to an object among LWPs (lightweight processes) and soft interrupt
     handlers.  In addition to the capabilities provided by mutexes, RW locks
     distinguish between read (shared) and write (exclusive) access.

     See rwlock(9).

   Functions to modify system interrupt priority level
     These functions raise and lower the interrupt priority level.  They are
     used by kernel code to block interrupts in critical sections, in order to
     protect data structures.

     See spl(9).

   Machine-independent software interrupt framework
     The software interrupt framework is designed to provide a generic soft-
     ware interrupt mechanism which can be used any time a low-priority call-
     back is required.  It allows dynamic registration of software interrupts
     for loadable drivers, protocol stacks, software interrupt prioritization,
     software interrupt fair queuing and allows machine-dependent optimiza-
     tions to reduce cost.

     See softint(9).

   Functions to raise the system priority level
     The splraiseipl function raises the system priority level to the level
     specified by icookie, which should be a value returned by
     makeiplcookie(9).  In general, device drivers should not make use of this
     interface.  To ensure correct synchronization, device drivers should use
     the condvar(9), mutex(9), and rwlock(9) interfaces.

     See splraiseipl(9).

   Passive serialization mechanism
     Passive serialization is a reader / writer synchronization mechanism
     designed for lock-less read operations.  The read operations may happen
     from software interrupt at IPL_SOFTCLOCK.

     See pserialize(9).

   Passive reference mechanism
     Passive references allow CPUs to cheaply acquire and release passive ref-
     erences to a resource, which guarantee the resource will not be destroyed
     until the reference is released.  Acquiring and releasing passive refer-
     ences requires no interprocessor synchronization, except when the
     resource is pending destruction.

     See psref(9).

   Localcount mechanism
     Localcounts are used in the kernel to implement a medium-weight reference
     counting mechanism.  During normal operations, localcounts do not need
     the interprocessor synchronization associated with atomic_ops(3) atomic
     memory operations, and (unlike psref(9)) localcount references can be
     held across sleeps and can migrate between CPUs.  Draining a localcount
     requires more expensive interprocessor synchronization than atomic_ops(3)
     (similar to psref(9)).  And localcount references require eight bytes of
     memory per object per-CPU, significantly more than atomic_ops(3) and
     almost always more than psref(9).

     See localcount(9).

   Simple do-it-in-thread-context framework
     The workqueue utility routines are provided to defer work which is needed
     to be processed in a thread context.

     See workqueue(9).

USAGE
     The following table describes in which contexts the use of the NetBSD
     kernel interfaces are valid.  Synchronization primitives which are avail-
     able in more than one context can be used to protect shared resources
     between the contexts they overlap.

           interface        thread      softirq     hardirq
           atomic_ops(3)    yes         yes         yes
           condvar(9)       yes         partly      no
           membar_ops(3)    yes         yes         yes
           mutex(9)         yes         depends     depends
           rwlock(9)        yes         yes         no
           softint(9)       yes         yes         yes
           spl(9)           yes         no          no
           splraiseipl(9)   yes         no          no
           pserialize(9)    yes         yes         no
           psref(9)         yes         yes         no
           localcount(9)    yes         yes         no
           workqueue(9)     yes         yes         yes

SEE ALSO
     atomic_ops(3), membar_ops(3), condvar(9), mutex(9), ras(9), rwlock(9),
     softint(9), spl(9), splraiseipl(9), workqueue(9)

HISTORY
     Initial SMP support was introduced in NetBSD 2.0 and was designed with a
     giant kernel lock.  Through NetBSD 4.0, the kernel used spinlocks and a
     per-CPU interrupt priority level (the spl(9) system).  These mechanisms
     did not lend themselves well to a multiprocessor environment supporting
     kernel preemption.  The use of thread based (lock) synchronization was
     limited and the available synchronization primitive (lockmgr) was ineffi-
     cient and slow to execute.  NetBSD 5.0 introduced massive performance
     improvements on multicore hardware by Andrew Doran.  This work was spon-
     sored by The NetBSD Foundation.

     A locking manual first appeared in NetBSD 8.0 and was inspired by the
     corresponding locking manuals in FreeBSD and DragonFly.

AUTHORS
     Kamil Rytarowski <kamil@NetBSD.org>.

NetBSD 8.0                      August 23, 2017                     NetBSD 8.0

You can also request any man page by name and (optionally) by section:

Command: 
Section: 
Architecture: 
Collection: 
 

Use the DEFAULT collection to view manual pages for third-party software.


©1994 Man-cgi 1.15, Panagiotis Christias
©1996-2018 Modified for NetBSD by Kimmo Suominen