Simple Locks
Simple locks are exclusive-write, non-recursive locks that protect thread-thread or thread-interrupt critical sections. Simple locks are preemptable, meaning that a kernel thread can be preempted by another, higher priority kernel thread while it holds a simple lock.
The simple lock kernel services are:
Item | Description |
---|---|
simple_lock_init | Initializes a simple lock. |
simple_lock, simple_lock_try | Locks a simple lock. |
simple_unlock | Unlocks a simple lock. |
On a multiprocessor system, simple locks that protect thread-interrupt critical sections must be used in conjunction with interrupt control in order to serialize execution both within the executing processor and between different processors. On a uniprocessor system interrupt control is sufficient; there is no need to use locks. The following kernel services provide appropriate locking calls for the system on which they are executed:
Item | Description |
---|---|
disable_lock | Raises the interrupt priority, and locks a simple lock if necessary. |
unlock_enable | Unlocks a simple lock if necessary, and restores the interrupt priority. |
Using the disable_lock and unlock_enable kernel services to protect thread-interrupt critical sections (instead of calling the underlying interrupt control and locking kernel services directly) ensures that multiprocessor-safe code does not make unnecessary locking calls on uniprocessor systems.
Simple locks are spin locks; a kernel thread that attempts to acquire a simple lock may spin (busy-wait: repeatedly execute instructions which do nothing) if the lock is not free. The table shows the behavior of kernel threads and interrupt handlers that attempt to acquire a busy simple lock.
Caller | Owner is Running | Owner is Sleeping |
---|---|---|
Thread (with interrupts enabled) | Caller spins initially; it sleeps if the maximum spin threshold is crossed. | Caller sleeps immediately. |
Interrupt handler or thread (with interrupts disabled) | Caller spins until lock is acquired. | Caller spins until lock is freed (must not happen). |
A simple lock that protects a thread-interrupt critical section must never be held across a sleep, otherwise the interrupt could spin for the duration of the sleep, as shown in the table. This means that such a routine must not call any external services that might result in a sleep. In general, using any kernel service which is callable from process level may result in a sleep, as can accessing unpinned data. These restrictions do not apply to simple locks that protect thread-thread critical sections.
The lock word of a simple lock must be located in pinned memory if simple locking services are called with interrupts disabled.