Skip to content

Day 83 - Deferred Work Architecture and Selection

Today's Goal

Understand how Linux drivers choose among different deferred execution mechanisms.

Topics covered:

  • Execution Context
  • Hard IRQ Context
  • Thread Context
  • Deferred Execution
  • Threaded IRQ
  • Workqueue
  • kthread_worker
  • Dedicated kthread
  • Producer / Queue / Consumer Model
  • Driver Design Patterns
  • Deferred Work Selection Guidelines

Key Concepts

Deferred Execution

The primary purpose of deferred execution is not simply to postpone work.

Instead, deferred execution moves work from a restricted execution context to a more suitable execution context.

Typical example:

IRQ
ISR
Deferred Execution
Thread Context

This allows the driver to perform operations that may sleep, block, or require longer processing time.


Execution Context

Linux driver behavior depends heavily on execution context.

Hard IRQ Context

Characteristics:

  • Cannot sleep
  • Cannot block
  • Cannot wait on mutexes
  • Must return quickly

Typical code:

irqreturn_t my_irq_handler(...)
{
    ...
}

Thread Context

Characteristics:

  • Can sleep
  • Can block
  • Can use mutexes
  • Can wait for events

Examples:

  • Threaded IRQ
  • Workqueue
  • kthread_worker
  • Dedicated kthread

Producer / Queue / Consumer Model

Many Linux driver architectures follow a common pattern:

Producer
 Queue
Consumer

Examples:

Component Example
Producer IRQ, Timer, Hardware Event
Queue FIFO, Ring Buffer, Work List
Consumer Workqueue, kthread_worker, kthread

The deferred execution mechanism is often the consumer side of this architecture.


Deferred Execution Mechanisms

Threaded IRQ

Architecture:

IRQ
Top Half
IRQ_WAKE_THREAD
thread_fn()

Suitable for:

  • IRQ-bound processing
  • Sleepable register access
  • I2C or SPI transactions

Workqueue

Architecture:

IRQ
queue_work()
Worker Pool
work_func()

Suitable for:

  • Short deferred work
  • General background processing
  • Debounce logic

kthread_worker

Architecture:

IRQ
queue_kthread_work()
Dedicated Worker
work_func()

Suitable for:

  • FIFO processing
  • Ordered work execution
  • Driver-specific workers

Dedicated kthread

Architecture:

IRQ
Wake Thread
Driver Loop

Typical structure:

while (!kthread_should_stop()) {
    ...
}

Suitable for:

  • Multiple event sources
  • Background processing
  • State-machine based drivers

Driver Design Patterns

GPIO Button

IRQ
delayed_work
debounce

Recommended mechanism:

Workqueue

I2C Sensor

IRQ
thread_fn()
read register

Recommended mechanism:

Threaded IRQ

Touch Controller

IRQ
kthread_worker
packet processing

Recommended mechanism:

kthread_worker

WiFi Driver

IRQ
Timer
User Request
Event Queue
Dedicated Thread

Recommended mechanism:

Dedicated kthread

Selection Matrix

Requirement Recommended Mechanism
Very short work, no sleep ISR
IRQ-bound sleepable work Threaded IRQ
Simple deferred work Workqueue
FIFO ordering required kthread_worker
Multiple event sources Dedicated kthread
State machine required Dedicated kthread

Labs

Lab1 - Execution Context Comparison

Compared execution contexts of:

  • Top Half
  • Threaded IRQ
  • Workqueue
  • kthread_worker
  • Dedicated kthread

Verified that:

  • Threaded IRQ executes in thread context
  • Workqueue executes in worker threads
  • kthread_worker executes in a dedicated worker thread
  • Dedicated kthread executes in its own thread

Lab2 - Driver Pattern Selection

Implemented four representative driver patterns:

  • Button Driver
  • Sensor Driver
  • Touch Driver
  • WiFi Driver

Mapped each pattern to the most appropriate deferred execution mechanism.


Summary

Deferred execution is fundamentally about selecting the appropriate execution context.

Different mechanisms provide different trade-offs regarding:

  • Sleepability
  • Ordering guarantees
  • Ownership of worker threads
  • State-machine support
  • Multi-event handling

Understanding these trade-offs is essential for Linux driver architecture design.


Next

Day84 - Wait Queue Internals

Topics:

  • wait_queue_head_t
  • wait_queue_entry_t
  • wait_event()
  • wake_up()
  • prepare_to_wait()
  • finish_wait()
  • Task States
  • Blocking Driver Architecture