备注
AI Translation Notice
This document was automatically translated by hunyuan-turbos-latest model, for reference only.
Source document: kernel/interrupt/workqueue.md
Translation time: 2026-01-05 16:08:30
Translation model:
hunyuan-turbos-latest
Please report issues via Community Channel
DragonOS Workqueue Mechanism Design Document
1. Overview
The Workqueue is a “bottom half” mechanism in the DragonOS kernel used to defer tasks for execution in the process context. Unlike Softirq and Tasklet, the workqueue handler functions run in kernel threads, thereby allowing the following operations:
Sleeping (blocking while waiting for resources)
Acquiring mutexes or semaphores
Performing I/O operations
Allocating memory (which may block)
The design of this mechanism is based on the Linux kernel’s workqueue implementation, adapted for DragonOS’s Rust architecture.
2. Core Architecture
2.1 Core Components
The Workqueue mechanism primarily consists of the following three components:
Work (Work Item):
Defines the specific task to be executed with a delay.
In the Rust implementation, it is essentially a structure encapsulating a closure or function pointer.
Managed via
Arcfor reference counting, supporting cross-thread sharing.
WorkQueue (Work Queue):
Responsible for managing pending work items.
Maintains one or more associated worker threads.
Internally contains a FIFO queue and a
WaitQueue(for thread synchronization).
Worker Thread (Worker Thread):
A dedicated kernel thread that cyclically retrieves tasks from the WorkQueue and executes them.
When the queue is empty, the thread enters a sleep state (suspended via
WaitQueue).When new tasks are enqueued, the thread is awakened.
2.2 Data Flow Diagram
graph TD
User[调用者 (Driver/Interrupt)] -->|schedule_work()| WQ[WorkQueue]
WQ -->|enqueue| Queue[待处理队列]
WQ -->|wakeup| Worker[Worker Thread]
subgraph Worker Thread Loop
Check{队列为空?} -->|Yes| Sleep[睡眠等待]
Check -->|No| Dequeue[取出 Work]
Dequeue --> Run[执行 Work.func()]
Run --> Check
end
Sleep -.->|被唤醒| Check
3. Detailed Design
3.1 Data Structure Design
Work
The Work structure encapsulates the specific task logic. It uses Box<dyn Fn() + Send + Sync> to store closures, ensuring they can be safely transferred and executed across threads.
pub struct Work {
func: Box<dyn Fn() + Send + Sync>,
}
WorkQueue
The WorkQueue is the core management structure. It includes:
queue: A spinlock-protected deque storingArc<Work>.wait_queue: Used for worker thread synchronization and waiting.worker: A reference pointing to the associated kernel thread’s PCB.
pub struct WorkQueue {
queue: SpinLock<VecDeque<Arc<Work>>>,
wait_queue: Arc<WaitQueue>,
worker: SpinLock<Option<Arc<ProcessControlBlock>>>,
}
3.2 Operational Mechanism
Initialization:
Calling
WorkQueue::new(name)creates a new work queue.This operation automatically starts a kernel thread named
name.
Task Scheduling:
The caller uses
Work::new(closure)to create a work item.wq.enqueue(work)is called to enqueue the task.The
enqueueoperation pushes the task to the end of the queue and callswait_queue.wakeup()to awaken the worker thread.
Task Execution:
The worker thread runs the
worker_loopfunction.It cyclically checks the queue status:
If the queue is not empty: the head task is dequeued, and
work.run()is called to execute it.If the queue is empty: the thread sleeps on
wait_queueby callingwait_event_interruptible, awaiting awakening.
3.3 System Global Queue (SYSTEM_WQ)
To simplify usage in common scenarios, the system provides a global default work queue SYSTEM_WQ.
Most simple background tasks can be directly submitted to this queue without creating a dedicated WorkQueue.
Tasks are scheduled directly via the
schedule_work(work)interface.
4. Interface Description
4.1 Creating Tasks
let work = Work::new(|| {
log::info!("This is running in a workqueue!");
// 可以安全地睡眠或加锁
});
4.2 Scheduling Tasks
// 调度到系统默认队列
schedule_work(work);
// 或者调度到自定义队列
let my_wq = WorkQueue::new("my_driver_wq");
my_wq.enqueue(work);
5. Differences from Linux
Similarities:
Both are delayed execution mechanisms based on kernel threads.
Both support sleeping and blocking operations.
Both provide a system-default global queue.
Differences:
Concurrency Model: The current DragonOS implementation adopts a “single-thread single-queue” model (each WorkQueue corresponds to a kernel thread). Linux employs a complex Worker Pool model, supporting dynamic scaling and concurrency management (CM).
Per-CPU: DragonOS currently does not implement Per-CPU WorkQueues; all tasks are processed in the same thread queue.
API Style: DragonOS leverages Rust’s closure features, making task definitions more flexible and concise. Unlike Linux, it does not require embedding
work_structinto custom structures (though similar patterns are also supported).
6. Future Evolution
Concurrency Management: Introduce a Worker Pool mechanism to allow multiple workers to consume the same queue, improving concurrency.
Per-CPU Queues: Implement Per-CPU WorkQueues to reduce lock contention and enhance cache locality.
Delayed Work (Delayed Work): Integrate timer mechanisms to support
schedule_delayed_work, allowing tasks to execute after a specified delay.