Skip to content

Day81 - Workqueue Internals

Goal

Understand how Linux Workqueue manages worker threads, work lifecycle, synchronization, and concurrency internally.


Lab1 - System Workqueue

Objective

Implement a global system workqueue and support:

  • workqueue_system_init()
  • workqueue_system_exit()
  • schedule_work()

Implementation

Implemented a global workqueue instance:

static struct workqueue *system_wq;

Added the following APIs:

workqueue_system_init()
workqueue_system_exit()
schedule_work()

Implemented the relationship:

schedule_work()
queue_work(system_wq, work)
worker thread
work function

Test Result

[TEST] schedule_work work1 ret=0
[TEST] schedule_work work2 ret=0
[WORK] run on system_wq
[WORK] run on system_wq

Key Observation

Linux drivers commonly use:

schedule_work(&work);

instead of creating dedicated workqueues.

The global system workqueue is shared among many drivers.


Lab2 - Worker Pool

Objective

Convert the workqueue from a single-worker model to a worker-pool model.

Implementation

Added worker pool support:

#define WORKER_COUNT 4

Added worker object:

struct worker {
    pthread_t tid;
    int id;
    struct workqueue *wq;
};

Updated workqueue:

struct workqueue {
    ...
    struct worker workers[WORKER_COUNT];
};

Each worker waits on the same queue and dequeues work items concurrently.

Test Result

[INFO] [WORKER-1] start
[INFO] [WORKER-2] start
[INFO] [WORKER-3] start
[INFO] [WORKER-4] start

[WORK-1] start
[WORK-2] start
[WORK-3] start
[WORK-4] start

[WORK-1] done
[WORK-2] done
[WORK-3] done
[WORK-4] done

Key Observation

The framework evolved from:

Single Worker

to:

Worker Pool
    ├─ Worker-1
    ├─ Worker-2
    ├─ Worker-3
    └─ Worker-4

Multiple work items can execute concurrently.


Lab3 - Work Lifecycle

Objective

Track work states and prevent duplicate scheduling.

Implementation

Added state tracking:

struct work_struct {
    ...
    bool pending;
    bool running;
};

Updated scheduling logic:

if (work->pending || work->running)
    return -EEXIST;

State Machine

IDLE
PENDING
RUNNING
IDLE

Test Result

[TEST] #1 schedule_work, ret=0
[TEST] #2 schedule_work, ret=-17

[WORK] done

[TEST] #3 schedule_work, ret=0

Key Observation

The framework no longer checks whether a work item exists in the queue.

Instead, scheduling decisions are based on the lifecycle state of the work item itself.


Lab4 - Work Synchronization APIs

Objective

Implement synchronization APIs for work completion and cancellation.

Implementation

Added work completion synchronization:

pthread_cond_t work_done;

Added active work accounting:

int active_works;

Implemented:

flush_work()
flush_workqueue()
cancel_work_sync()

flush_work()

Wait until a specific work item becomes idle.

flush_work(&work);

flush_workqueue()

Wait until all pending and running work items complete.

flush_workqueue(wq);

Implemented using:

while (wq->active_works > 0)

cancel_work_sync()

Behavior:

Work State Result
PENDING Remove from queue
RUNNING Wait for completion
IDLE Return immediately

Test Result

Running work:

[WORK-2] start

cancel_work_sync(work2)

[WORK-2] done

cancelled=0

Pending work:

schedule work1
schedule work2
schedule work3
schedule work4
schedule work5

cancel_work_sync(work5)

cancelled=1

Verified:

[WORK-5] start

never appeared.

Key Observation

flush_work() waits for a specific work item.

flush_workqueue() waits for the entire workqueue to become idle.

cancel_work_sync() combines cancellation and synchronization semantics.


Summary

Implemented:

  • System Workqueue
  • Worker Pool
  • Work Lifecycle Management
  • flush_work()
  • flush_workqueue()
  • cancel_work_sync()

Added:

  • pending
  • running
  • active_works
  • work_done

Verified:

  • Shared system workqueue
  • Concurrent worker execution
  • Work lifecycle tracking
  • Duplicate scheduling prevention
  • Work completion synchronization
  • Pending work cancellation

Next Step

Day82 - kthread Internals

Topics:

  • Kernel Thread Architecture
  • kthread_create()
  • kthread_run()
  • kthread_stop()
  • kthread_should_stop()
  • kthread Worker Pattern
  • kthread_work
  • Workqueue vs kthread Internals
  • Driver Usage Patterns