Skip to content

Day67 - Workqueue Fundamentals

Goal

Understand how Linux Workqueues provide deferred execution by moving work from interrupt context into process context.

This lab focuses on Workqueue architecture, lifecycle management, cleanup behavior, and driver design patterns.


Deferred Execution

Problem

Hard IRQ handlers must execute quickly and cannot perform operations that may sleep.

Examples of prohibited operations inside Hard IRQ Context:

msleep(100);

mutex_lock(&lock);

wait_event(...);

To perform these operations safely, work must be deferred into a sleepable context.


Workqueue Solution

IRQ
schedule_work()
Workqueue
kworker thread
Work Handler

The work handler executes in process context.

Allowed operations:

  • mutex_lock()
  • msleep()
  • schedule()
  • i2c_transfer()
  • spi_sync()

Workqueue Lifecycle

Global Workqueue

Linux provides a default global workqueue:

schedule_work(&work);

Equivalent:

queue_work(system_wq, &work);

Private Workqueue

Drivers may create dedicated workqueues:

struct workqueue_struct *wq;

wq = alloc_workqueue(
        "my_driver_wq",
        WQ_UNBOUND,
        0);

Submit work:

queue_work(wq, &work);

Advantages:

  • Workload isolation
  • Dedicated lifecycle
  • Independent worker pool

Delayed Work

Delayed Work combines:

Timer
+
Workqueue

Initialization:

INIT_DELAYED_WORK(&retry_work,
                  retry_handler);

Schedule:

schedule_delayed_work(
        &retry_work,
        msecs_to_jiffies(100));

Reschedule:

mod_delayed_work(
        wq,
        &retry_work,
        msecs_to_jiffies(100));

Common Driver Patterns

Retry Mechanism

IRQ
Device Busy
Delayed Work
Retry Later

Typical examples:

  • Firmware update
  • Device recovery
  • Hardware reset sequence

Debounce

GPIO IRQ
mod_delayed_work()
20 ms delay
Read stable state

Monitoring

Delayed Work
Read Device Status
Reschedule

Examples:

  • Battery monitor
  • Thermal monitor
  • Link status monitor

Workqueue Cleanup

Work Cancellation

cancel_work_sync(&work);

Behavior:

  • Remove pending work
  • Wait for running handler completion

Delayed Work Cancellation

cancel_delayed_work_sync(&retry_work);

Behavior:

  • Cancel timer if pending
  • Wait for running handler completion

Workqueue Flush

flush_workqueue(wq);

Behavior:

Wait until all queued work completes.

The workqueue remains usable.


Workqueue Destroy

destroy_workqueue(wq);

Behavior:

Flush all work
Destroy worker pool
Release workqueue

Driver Remove Sequence

Recommended shutdown sequence:

disable_irq()
cancel_work_sync()
cancel_delayed_work_sync()
destroy_workqueue()
free_irq()
release resources

Reason:

Prevent pending work from accessing
already-freed driver resources.

Workqueue vs Threaded IRQ

Threaded IRQ

IRQ
IRQ Thread
Immediate Handling
Return

Suitable for:

  • Interrupt-driven processing
  • I2C/SPI transactions
  • Event reporting

Workqueue

Event
Background Job
Completion

Suitable for:

  • Retry mechanisms
  • Recovery operations
  • Deferred processing
  • Delayed execution

Workqueue vs Kernel Thread

Workqueue

Job-Oriented

Characteristics:

  • Event-driven
  • Finite execution
  • Managed by kernel worker pools

Kernel Thread

Service-Oriented

Characteristics:

  • Long-lived execution
  • State machine processing
  • Monitoring and background services

Summary

Key concepts learned:

  • Deferred execution moves work into sleepable context.
  • Workqueue handlers run in process context.
  • Delayed Work combines timers and workqueues.
  • Private workqueues isolate driver workloads.
  • Workqueue cleanup is essential during driver removal.
  • Workqueue is designed for jobs, not permanent services.
  • Kernel Threads are better suited for long-lived state machines.