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