Skip to content

Day 88 - Kernel Locking Internals

Date

2026-06-30


Today's Goal

Understand why the Linux kernel requires locking primitives to protect shared data, how race conditions occur, and when to use different synchronization mechanisms such as spinlocks, mutexes, and reader-writer semaphores.

Implement a simplified Linux-style locking framework and integrate it with the existing IRQ subsystem to demonstrate interrupt-safe synchronization using spin_lock_irqsave().


What I Learned

Why Kernel Locking

  • Shared data accessed concurrently can lead to race conditions.
  • A critical section must be protected to guarantee data consistency.
  • Different execution contexts require different locking mechanisms.

Execution Context

  • Process Context may sleep and use blocking synchronization.
  • IRQ Context cannot sleep and must use atomic synchronization.
  • Local IRQs can interrupt Process Context on the same CPU.

Spinlock

  • Implemented a simplified Linux-style spinlock using C11 atomic compare-and-exchange.
  • Learned that spinlocks protect short critical sections through busy waiting.
  • Measured lock contention by counting retry attempts during lock acquisition.
  • Understood why spinlocks must never sleep while holding the lock.

Mutex

  • Implemented a simplified Linux-style mutex wrapper using POSIX pthread mutexes.
  • Compared mutexes with spinlocks.
  • Learned that mutexes suspend waiting threads instead of busy waiting.

spin_lock_irqsave()

  • Simulated local IRQ enable/disable state.
  • Implemented spin_lock_irqsave() and spin_unlock_irqrestore().
  • Demonstrated how disabling local IRQs prevents self-deadlock when an interrupt occurs while holding a spinlock.

Reader-Writer Synchronization

  • Reviewed the purpose of Linux rw_semaphore.
  • Compared rw_semaphore, mutex, and RCU.
  • Understood that reader-writer locks allow multiple concurrent readers while writers remain exclusive.

IRQ Framework Refactoring

  • Refactored the generic IRQ framework into an independent utils/irq subsystem.
  • Separated generic interrupt handling from the GPIO simulation framework.
  • Improved the subsystem organization to better match the Linux kernel architecture.

Labs Completed

Lab 1 - Race Condition

Implemented a shared counter without synchronization and demonstrated race conditions caused by concurrent updates.

Lab 2 - Spinlock

Implemented a simplified Linux-style spinlock.

Verified:

  • Atomic lock acquisition
  • Busy waiting
  • Lock contention
  • Retry count statistics

Lab 3 - Mutex

Implemented a simplified Linux-style mutex.

Compared mutex behavior with spinlocks and verified correct protection of shared data.

Lab 4 - spin_lock_irqsave()

Integrated the locking framework with the IRQ subsystem.

Demonstrated:

  • Process Context holding a spinlock
  • IRQ arriving during the critical section
  • Self-deadlock risk without spin_lock_irqsave()
  • Deferred interrupt handling using spin_lock_irqsave() and spin_unlock_irqrestore()

Key Takeaways

  • Race conditions occur whenever multiple execution contexts modify shared data without synchronization.
  • Spinlocks are suitable for atomic contexts such as IRQ handlers.
  • Mutexes are suitable for sleepable contexts such as Process Context.
  • spin_lock_irqsave() protects against local IRQ re-entry while holding a spinlock.
  • Choosing the correct locking primitive depends on the execution context rather than the data itself.
  • rw_semaphore is appropriate for read-heavy workloads where multiple readers may access shared data concurrently.

Next Step

Day 89 - Linux Kernel Memory Allocation

Topics:

  • Physical vs Virtual Memory
  • Kernel Address Space
  • kmalloc()
  • kzalloc()
  • kcalloc()
  • kfree()
  • GFP Flags
  • vmalloc()
  • Memory Allocation Guidelines