Skip to content

Deferred Work Selection

Deferred execution is a fundamental design technique in Linux drivers.

The primary goal is not simply to delay work, but to move processing from a restricted execution context to a more appropriate execution context.

Typical example:

IRQ
ISR
Deferred Execution
Thread Context

This allows drivers to perform operations that may sleep, block, or require significant processing time.


Why Deferred Execution Exists

Interrupt handlers execute in hard IRQ context.

Hard IRQ context has strict limitations:

  • Cannot sleep
  • Cannot block
  • Cannot wait for events
  • Should execute as quickly as possible

For example, the following operations are typically not allowed inside an ISR:

I2C transfer
SPI transfer
mutex_lock()
wait_event()
msleep()

Therefore, Linux drivers commonly move work into a thread context.


Execution Context

Hard IRQ Context

Examples:

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

Characteristics:

  • Cannot sleep
  • Cannot block
  • Must return quickly

Typical responsibilities:

  • Acknowledge interrupt
  • Capture minimal state
  • Schedule deferred work

Thread Context

Examples:

  • Threaded IRQ
  • Workqueue worker
  • kthread_worker
  • Dedicated kthread

Characteristics:

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

Typical responsibilities:

  • Register access
  • Data processing
  • State-machine execution
  • Background work

Deferred Execution Mechanisms

Linux provides multiple mechanisms for deferred execution.


Threaded IRQ

Architecture:

IRQ
Top Half
IRQ_WAKE_THREAD
thread_fn()

Characteristics:

  • Dedicated IRQ thread
  • Closely tied to a specific interrupt source
  • Supports sleeping operations

Typical use cases:

  • I2C sensors
  • SPI sensors
  • GPIO expanders

Example:

IRQ
Read Sensor Register
Update Driver State

Workqueue

Architecture:

IRQ
queue_work()
Worker Pool
work_func()

Characteristics:

  • Shared worker threads
  • Low management overhead
  • General-purpose deferred execution

Typical use cases:

  • Debounce logic
  • Background cleanup
  • Short deferred work

Example:

IRQ
schedule_delayed_work()
GPIO Debounce

kthread_worker

Architecture:

IRQ
queue_kthread_work()
Dedicated Worker
work_func()

Characteristics:

  • Dedicated worker thread
  • FIFO ordering
  • Driver-specific execution context

Typical use cases:

  • Touch controllers
  • Packet processing
  • Ordered event handling

Example:

IRQ
Read Packet
Parse Packet
Report Event

Dedicated kthread

Architecture:

IRQ
Timer
User Request
Event Queue
Dedicated Thread

Typical implementation:

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

Characteristics:

  • Full control over execution flow
  • Supports state machines
  • Supports multiple event sources

Typical use cases:

  • WiFi drivers
  • Bluetooth drivers
  • Modem drivers
  • Complex protocol stacks

Producer / Queue / Consumer Model

Many Linux drivers follow a common architecture:

Producer
 Queue
Consumer

Examples:

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

The deferred execution mechanism often acts as the consumer.


Important Observation

A work item is not necessarily an event.

Example:

IRQ
Hardware FIFO
Worker

Multiple interrupts may occur while a worker is already running.

This is often acceptable because:

Event
    Stored in FIFO

Worker
    Consumes FIFO

The worker processes all pending data before exiting.

This prevents event loss even when duplicate work scheduling is suppressed.


Driver Design Patterns

GPIO Button

Architecture:

IRQ
delayed_work
debounce

Recommended mechanism:

Workqueue

Reason:

  • Simple processing
  • No state machine
  • No dedicated thread required

I2C Sensor

Architecture:

IRQ
thread_fn()
read register

Recommended mechanism:

Threaded IRQ

Reason:

  • IRQ-bound processing
  • Sleepable register access
  • Simple execution flow

Touch Controller

Architecture:

IRQ
kthread_worker
read packet
parse packet

Recommended mechanism:

kthread_worker

Reason:

  • Ordered packet processing
  • FIFO execution
  • Dedicated worker

WiFi Driver

Architecture:

IRQ
Timer
User Request
Event Queue
Dedicated Thread

Recommended mechanism:

Dedicated kthread

Reason:

  • Multiple event sources
  • Long-running background processing
  • State-machine based design

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

Selection Flow

Need sleep?
    ├─ No
    │    ↓
    │   ISR
    └─ Yes
         ├─ Need FSM?
         │     ↓
         │  Dedicated kthread
         ├─ Need multiple event sources?
         │     ↓
         │  Dedicated kthread
         ├─ Need FIFO ordering?
         │     ↓
         │  kthread_worker
         ├─ IRQ-bound processing?
         │     ↓
         │  Threaded IRQ
         └─ Workqueue

Related Topics

  • IRQ Bottom Half and Deferred Work
  • Workqueue Internals
  • Kthread
  • Wait Queue Internals

Related Labs