6.3 About Handling Access to Shared Resources

Multiple threads of execution can operate simultaneously on shared kernel data structures. As a result, you must ensure that such access is serialized. You can use spinlocks and mutexes to control access to critical sections, which are areas of code that contain shared resources.

  • A spinlock allows only one thread at a time to access a critical section. Another thread that wants to access the critical section continues to spin until the thread exits that has access. You can use the spin_lock() function to obtain a spinlock if the code does not run in either hardware or software interrupt context.

    #include <linux/spinlock.h>
    spinlock_t spinlock = SPIN_LOCK_UNLOCKED;
        /* Critical section */

    If the code runs in either hardware or software interrupt context, use a spinlock function that disables interrupts, such as spin_lock_irq() or spin_lock_irqsave(). Finally, the spin_lock_bh() function disables software interrupts while leaving hardware interrupts enabled. Each of these functions is paired with a correspondingly named unlock function.

  • A mutex puts a thread to sleep until it can access the critical section.

    #include <linux/mutex.h>
    static DEFINE_MUTEX(mutex);
        /* Critical section */

    This example uses a statically defined mutex. You can use mutex_init() to create a dynamic mutex.

It is better to use mutexes than spinlocks when the wait time is expected to be more than two context switches. However, inside an interrupt handler, you must always use a spinlock because a mutex can put a thread to sleep. Conversely, if the critical section needs to sleep, you must use a mutex as a thread must not be scheduled, preempted, or put to sleep after it has acquired a spinlock.


The mutex interface was introduced as an alternative to the semaphore interface. Semaphores allow simultaneous access by a specified number of threads to a critical section, but this feature is almost never used.

When a thread can only either read from or write to a critical region, there are also the read_lock() and write_lock() functions that you can use to implement reader or writer spin locks. A writer spinlock blocks access to all other writing or reading threads. A reader spinlock blocks access to other writing threads but allows access from other reading threads.

As an alternative to spinlocks and mutexes, you can use the 32 and 64-bit atomic integer types (atomic_t and atomic64_t) and perform operations such as incrementing counters and setting bit masks.

Finally, if a single writer thread maintains a data structure that is always seen consistently by a reader thread, you can use a lock-less circular buffer such as the kfifo structure that is defined in <linux/kfifo.h>. Network drivers typically use such buffers to exchange data with the adapter.