Part 4: Concurrency and Synchronization

The Linux kernel is inherently concurrent - multiple CPUs, interrupts, and preemption mean your code can be interrupted or run simultaneously at any time. Understanding synchronization primitives is essential for writing correct, safe drivers.

Why Concurrency Matters

flowchart TD
    subgraph Sources["Concurrency Sources"]
        direction TB
        SMP["Multiple CPUs"]
        INT["Interrupts"]
        PRE["Preemption"]
        SOFT["Softirqs/Tasklets"]
    end

    subgraph Problem["The Problem"]
        direction TB
        Race["Race Conditions"]
        Corrupt["Data Corruption"]
        Dead["Deadlocks"]
    end

    subgraph Solutions["Solutions"]
        direction TB
        Spin["Spinlocks"]
        Mutex["Mutexes"]
        Atomic["Atomic Operations"]
        RCU["RCU"]
    end

    Sources --> Problem
    Problem --> Solutions

    style Problem fill:#8f6d72,stroke:#c62828
    style Solutions fill:#7a8f73,stroke:#2e7d32

Chapter Contents

Chapter Topic Key Concepts
4.1 Concurrency Concepts Race conditions, critical sections
4.2 Spinlocks spin_lock, spin_lock_irqsave
4.3 Mutexes Sleeping locks, mutex vs spinlock
4.4 Semaphores Counting semaphores
4.5 Atomic Operations atomic_t, bitwise atomics
4.6 RCU Read-Copy-Update
4.7 Completions Signaling between threads
4.8 Work Queues Deferred processing
4.9 Lockdep Deadlock detection
4.10 Kernel Timers timer_list, hrtimer
4.11 Wait Queues wait_event, wake_up
4.12 Kernel Threads kthread_run, kthread_stop

Quick Reference: Choosing a Lock

flowchart TD
    Start["Need to protect data?"]
    Sleep{"Can you sleep?"}
    Duration{"Short critical section?"}
    Read{"Mostly reads?"}
    Counter{"Simple counter?"}

    Start --> Sleep
    Sleep -->|"No (interrupt context)"| Spin["Spinlock"]
    Sleep -->|"Yes (process context)"| Duration
    Duration -->|"Yes"| Spin
    Duration -->|"No"| Mutex["Mutex"]
    Sleep -->|"Yes"| Read
    Read -->|"Yes, rare writes"| RCU["RCU"]
    Sleep -->|"Yes"| Counter
    Counter -->|"Yes"| Atomic["atomic_t"]

    style Spin fill:#8f8a73,stroke:#f9a825
    style Mutex fill:#738f99,stroke:#0277bd
    style RCU fill:#8f7392,stroke:#6a1b9a
    style Atomic fill:#7a8f73,stroke:#2e7d32
Primitive Sleep OK? Interrupt Safe? Best For
Spinlock No With irqsave Short critical sections
Mutex Yes No Longer critical sections
Semaphore Yes No Resource counting
atomic_t N/A Yes Simple counters
RCU Read: Yes Read: Yes Read-heavy data
Completion Yes No Thread synchronization

Examples

This part includes working examples:

  • spinlock-demo: Spinlock usage patterns
  • workqueue-demo: Deferred work processing
  • timer-demo: Kernel timer and hrtimer usage
  • kthread-demo: Background kernel threads

Common Pitfalls

Deadlocks: Taking locks in different orders across code paths

Priority inversion: Low-priority task holds lock needed by high-priority task

Sleeping with spinlock: Calling functions that might sleep while holding a spinlock

Prerequisites

Before starting this part, ensure you understand:

  • Process vs interrupt context (Part 2)
  • Basic module structure (Part 1-2)
  • Character device operations (Part 3)

Further Reading

Next

Start with Concurrency Concepts to understand why synchronization is necessary.


Table of contents


Back to top

Linux Driver Development Guide is a community resource for learning kernel driver development. Not affiliated with the Linux Foundation. Content provided for educational purposes.

This site uses Just the Docs, a documentation theme for Jekyll.