Skip to content

Day82 - kthread Internals

Objective

Learn how Linux kernel threads are created, started, stopped, and managed internally.

Implement a userspace simulation of:

  • kthread_create()
  • wake_up_process()
  • kthread_run()
  • kthread_should_stop()
  • kthread_stop()

Extend the framework with:

  • kthread_worker
  • kthread_work

and understand how Linux builds higher-level deferred execution frameworks on top of kernel threads.


Lab Architecture

kthread Framework

task_struct
    ├── thread
    ├── started
    ├── should_stop
    ├── threadfn
    ├── data
    └── name

Execution flow:

kthread_create()
wake_up_process()
kthread_entry()
threadfn()
kthread_stop()
thread exit

TLS Current Task Simulation

Implemented a userspace simulation of Linux current.

static __thread struct task_struct *current_task;

Helper APIs:

tls_set_task()
tls_get_task()

This allows:

kthread_should_stop()

to operate without requiring a task pointer.


kthread_worker Framework

kthread_work
    ├── func
    ├── next
    ├── pending
    └── running


kthread_worker
    ├── task
    ├── head
    ├── tail
    ├── active_works
    ├── running
    ├── lock
    ├── not_empty
    └── work_done

Execution flow:

queue_kthread_work()
worker queue
dedicated kthread
work->func()

Lab1 - kthread_create() and wake_up_process()

Goal

Understand the separation between:

  • Thread creation
  • Thread execution

Implemented APIs

kthread_create()
wake_up_process()

Test Flow

task = kthread_create(...);

wake_up_process(task);

kthread_stop(task);

Expected Output

[TEST] task created but not running yet
[TEST] wake_up_process ret=0
[THREAD] run: hello from kthread
[TEST] kthread_stop ret=0

Key Learning

kthread_create() allocates and initializes a thread but does not start execution.

wake_up_process() starts the thread.


Lab2 - kthread_run()

Goal

Implement a convenience wrapper.

Implemented API

kthread_run()

Implementation concept:

kthread_run()
    =
kthread_create()
    +
wake_up_process()

Test Flow

task = kthread_run(...);

kthread_stop(task);

Expected Output

[TEST] kthread_run returned
[THREAD] run: hello from kthread_run
[TEST] kthread_stop ret=0

Key Learning

Most Linux drivers use:

kthread_run()

instead of manually calling:

kthread_create()
wake_up_process()

Lab3 - Cooperative Thread Stop

Goal

Implement cooperative thread termination.

Implemented APIs

kthread_should_stop()
kthread_stop()

Thread Loop

while (!kthread_should_stop(task)) {
    usleep(100 * 1000);
}

Test Flow

wake_up_process(task);

sleep(1);

kthread_stop(task);

Expected Output

[THREAD] run: demo_kthread
[THREAD] exit (kthread_should_stop()=1)
[TEST] kthread_stop ret=0

Key Learning

Linux does not forcibly terminate a thread.

Threads must periodically check:

kthread_should_stop()

and exit voluntarily.


Lab4 - TLS Current Task Simulation

Goal

Simulate Linux current.

Implementation

static __thread struct task_struct *current_task;

Thread entry:

tls_set_task(task);

threadfn(data);

tls_set_task(NULL);

Updated API:

bool kthread_should_stop(void);

Test Flow

Create two threads:

task1 = kthread_run(...);
task2 = kthread_run(...);

Print TLS task pointer.

Expected Output

[THREAD-1] task=0x11111111
[THREAD-2] task=0x22222222

[THREAD-1] task=0x11111111
[THREAD-2] task=0x22222222

Key Learning

TLS provides independent storage for each thread.

This closely resembles Linux's current task concept.


Lab5 - kthread_worker Fundamentals

Goal

Implement a dedicated worker thread.

Implemented APIs

init_kthread_work()
kthread_worker_init()
queue_kthread_work()

Test Flow

Queue multiple work items:

WORK-1
WORK-2
WORK-3

Expected Output

[WORK-1] execute tid=135119002138304
[WORK-1] done

[WORK-2] execute tid=135119002138304
[WORK-2] done

[WORK-3] execute tid=135119002138304
[WORK-3] done

Key Learning

All work items execute on the same worker thread.

Unlike workqueues:

workqueue
    → worker pool

kthread_worker
    → dedicated worker thread

Lab6 - Worker Synchronization

Goal

Implement synchronization and lifecycle handling.

Implemented APIs

queue_kthread_work()
flush_kthread_worker()
kthread_worker_stop()

Case1 - Duplicate Pending Work

Test

queue work1
queue work1 again

Expected

queue work1 ret=0
queue work1 again ret=-EEXIST

Case2 - Duplicate Running Work

Test

Queue a work item and requeue it while running.

Expected

queue running work ret=-EEXIST

Case3 - flush_kthread_worker()

Test

queue work

flush_kthread_worker()

Expected

flush begin

WORK start
WORK done

flush done

Key Learning

Flush waits for active work completion.


Case4 - Stop Drains Pending Works

Test

Queue:

WORK1
WORK2
WORK3
WORK4
WORK5

Immediately stop worker.

Expected

WORK1 done
WORK2 done
WORK3 done
WORK4 done
WORK5 done

kthread_worker_stop()

Key Learning

Worker stop drains queued work before thread termination.


Summary

kthread APIs

Implemented:

kthread_create()
wake_up_process()
kthread_run()
kthread_should_stop()
kthread_stop()
kthread_destroy()

kthread_worker APIs

Implemented:

init_kthread_work()
kthread_worker_init()
queue_kthread_work()
flush_kthread_worker()
kthread_worker_stop()

Key Concepts

  • Dedicated kernel thread lifecycle
  • Cooperative thread termination
  • TLS-based current task simulation
  • Dedicated worker thread architecture
  • Ordered work execution
  • Flush synchronization
  • Worker lifecycle management

Comparison

Item Workqueue kthread_worker
Worker Threads Worker Pool Dedicated Thread
Execution Order Not Guaranteed Guaranteed
Thread Ownership Kernel Managed Driver Managed
State Machine Usage Limited Common
Long-lived Services Uncommon Common

Next Step

Day83 - Deferred Work Architecture and Selection