When using the kernel-global workqueue, a simple pattern (workflow) emerges:
- Initialize the work task.
- At the appropriate point in time, schedule it to execute (perhaps with a delay and/or on a particular CPU core).
- Clean up. Typically, in the kernel module (or driver's) cleanup code path, cancel it. (Preferably, do this with synchronization so that any pending work tasks are completed first. Here, we will stick to employing the recommended cancel*work*() routines, avoiding the flush_*() ones).
Let's summarize this using a table:
Using the kernel-global workqueue | Regular work task | Delayed work task | Execute work task on given CPU |
1. Initialization | INIT_WORK() | INIT_DELAYED_WORK() | < either immediate or delayed's fine > |
2. Schedule work task to execute | schedule_work() | schedule_delayed_work() | schedule_delayed_work_on() |
3. Cancel (or flush) it; foo_sync() to ensure it's complete | cancel_work_sync() | cancel_delayed_work_sync... |