Thursday, October 30, 2025

Using Spinlocks in the Linux Kernel - Basics

 

Updated for Linux Kernel Version 6.x

1. Kernel Contexts and Sleep Capability


Different kernel contexts have different capabilities and constraints regarding sleeping and locking mechanisms:

- Interrupt context: Cannot sleep. Use spinlocks with irqsave.
- Softirq/Tasklet context: Cannot sleep. Use spin_lock_bh.
- Workqueue context: Can sleep. Use spinlocks carefully or mutexes.
- Kernel threads: Can sleep. Use mutexes or sleeping locks.

2. Locking Primitives Overview

Primitive

Sleep Allowed?

Use Case

Notes

spin_lock()

No

Short non-blocking critical section

Does not disable interrupts

spin_lock_irqsave()

No

Shared with IRQ handler

Disables local interrupts

spin_lock_bh()

No

Shared with bottom halves

Disables bottom halves

mutex_lock()

Yes

Process context critical section

Safe to sleep

atomic_t

N/A

Simple counters/flags

No blocking

RCU

Readers no lock

Read-dominant data

Use for many readers



3. Using Spinlocks in Workqueues—When & How


Spinlocks can be used in work queues when the critical section is short and non-sleeping.

Example:

static spinlock_t lock;
static int shared;

irqreturn_t irq_handler(int irq, void *dev)
{
    unsigned long flags;
    spin_lock_irqsave(&lock, flags);
    shared++;
    spin_unlock_irqrestore(&lock, flags);
    schedule_work(&my_work);
    return IRQ_HANDLED;
}

static void my_work_fn(struct work_struct *w)
{
    unsigned long flags;
    spin_lock_irqsave(&lock, flags);
    int local = shared;
    shared = 0;
    spin_unlock_irqrestore(&lock, flags);

    /* heavy processing outside lock */
}

4. Decision Tree: Choosing the Right Lock


1. Are all contexts process-context (can sleep)? → Use mutex/rwlock.
2. Is one side interrupt or softirq (cannot sleep)? → Use spinlock variant.
3. Is the critical section very short? → Spinlock OK.
4. Is data read-mostly? → RCU.
5. Heavy contention? → Per-CPU data or atomics.

5. Diagrams

Context and Locking Flow Diagram:


IRQ (non-sleep) ─┬─> shared data ─┬─> workqueue (process context)
                 │                 │
                 └─ spin_lock_irqsave()/unlock_irqrestore()

6. Summary


- You can use spinlocks in workqueues only if the code under the lock does not sleep.
- Use the appropriate spinlock variant if shared with IRQ or softirq.
- Prefer mutexes for long or blocking sections.
- Use single-thread work queues for serialized access instead of complex locks.

No comments:

Post a Comment