Skip to content

Day80 - IRQ Bottom Half and Deferred Work

Overview

This lab explores common Linux Bottom Half mechanisms used to defer interrupt processing from IRQ context to process context.

Implemented mechanisms:

  • Workqueue
  • Delayed Work
  • Threaded IRQ

Simulation framework:

utils/gpio-sim/
├── irq.c
├── irq.h
├── workqueue.c
├── workqueue.h
├── delayed_work.c
├── delayed_work.h
└── kernel_macro.h

Lab1 - Workqueue Bottom Half

Objective

Implement a basic Workqueue framework and verify deferred execution through a worker thread.


Workqueue Architecture

queue_work()
+----------------+
|  workqueue     |
|  FIFO Queue    |
+----------------+
+----------------+
| worker thread  |
+----------------+
work->func()

APIs

void init_work(struct work_struct *work,
               work_func_t func);

struct workqueue *workqueue_create(void);

void workqueue_destroy(struct workqueue *wq);

int queue_work(struct workqueue *wq,
               struct work_struct *work);

Verification

[MAIN] queue work: 1
[MAIN] queue_work ret=0
[MAIN] queue work: 2
[MAIN] queue_work ret=0
[MAIN] queue work: 3
[MAIN] queue_work ret=0

[WORK-1] running
[WORK-2] running
[WORK-3] running

Verified:

  • FIFO ordering
  • Worker thread execution
  • Deferred processing

Lab2 - Delayed Work

Objective

Implement delayed execution using a timer mechanism and Workqueue.


Delayed Work Architecture

schedule_delayed_work()
      Timer Delay
       queue_work()
       Worker Thread

APIs

void init_delayed_work(struct delayed_work *dwork,
                       work_func_t func);

int schedule_delayed_work(struct workqueue *wq,
                          struct delayed_work *dwork,
                          unsigned int delay_ms);

int cancel_delayed_work(struct delayed_work *dwork);

int mod_delayed_work(struct workqueue *wq,
                     struct delayed_work *dwork,
                     unsigned int delay_ms);

Delayed Work Verification

[MAIN] schedule delayed work 1000ms
[MAIN] schedule_delayed_work ret=0

[WORK] delayed work count=1

[MAIN] schedule delayed work 500ms
[MAIN] schedule_delayed_work ret=0

[WORK] delayed work count=2

Verified:

  • Delayed execution
  • Pending protection
  • Workqueue integration

Cancel Delayed Work

[MAIN] schedule delayed work 3000ms
[MAIN] schedule_delayed_work ret=0

[MAIN] cancel delayed work
[MAIN] cancel_delayed_work ret=0

[MAIN] no delayed work executed

Verified:

  • Delayed work cancellation
  • Timer termination path

IRQ Debounce Pattern

Using:

mod_delayed_work(dev->wq,
                 &dev->dwork,
                 500);

Verification:

IRQ #1
IRQ #2
IRQ #3


WORK only once

Output:

[ISR] delayed_work ret=0
[ISR] delayed_work ret=0
[ISR] delayed_work ret=0

[WORK] delayed work count=1

Verified:

  • Debounce pattern
  • Timer restart behavior
  • Single Bottom Half execution

Lab3 - Threaded IRQ

Objective

Implement Threaded IRQ handling using a dedicated IRQ thread.


Threaded IRQ Architecture

IRQ
Top Half
IRQ_WAKE_THREAD
IRQ Thread
thread_fn()

APIs

int request_threaded_irq(
        int irq,
        enum irq_trigger_type trigger,
        irq_handler_t handler,
        irq_handler_t thread_fn,
        const char *name,
        void *dev_id);

Verification

[TRIGGER] irq=100
[DISPATCH] irq=100 (button threaded irq)

[TOP] irq=100 return IRQ_WAKE_THREAD

[IRQ] wake thread

[THREAD] irq=100 count=1

Additional verification:

[THREAD] irq=100 count=2
[THREAD] irq=100 count=3

[MAIN] free_irq ret=0
[MAIN] irq_trigger after free ret=-2

Verified:

  • IRQ_WAKE_THREAD
  • Dedicated IRQ thread
  • thread_fn execution
  • IRQ lifecycle

Comparison

Workqueue

IRQ
ISR
queue_work()
Worker Thread

Characteristics:

  • Shared worker thread
  • Deferred processing
  • General-purpose Bottom Half

Threaded IRQ

IRQ
Top Half
IRQ_WAKE_THREAD
IRQ Thread

Characteristics:

  • Dedicated IRQ thread
  • Interrupt-specific processing
  • Lower scheduling latency

Conclusion

This lab implemented three common Linux Bottom Half mechanisms:

  • Workqueue
  • Delayed Work
  • Threaded IRQ

The simulation demonstrates how Linux moves work from IRQ context into process context while keeping interrupt latency low.