Tasklets:
- are old (around 2.3 I believe)
- have a straightforward, simple API
- are designed for low latency
- cannot sleep (run atomically in soft IRQ context and are guaranteed to never run on more than one CPU of a given processor, for a given tasklet)
Work queues:
- are more recent (introduced in 2.5)
- have a flexible API (more options/flags supported)
- are designed for higher latency
- can sleep
Bottom line is: use tasklets for high priority, low latency atomic tasks that must still execute outside the hard IRQ context.
You can control some level of priority with tasklets using tasklet_hi_enable
/tasklet_hi_schedule
(instead of their respective no-_hi
versions). From this IBM page:
The normal-priority schedule is performed through the TASKLET_SOFTIRQ-level softirq, where high priority is through the HI_SOFTIRQ-level softirq.
...
Tasklets from the high-priority vector are serviced first, followed by those on the normal vector. Note that each CPU maintains its own normal and high-priority softirq vectors.
With work queues, when creating one, you will use alloc_workqueue
(create_workqueue
is deprecated) and can pass a flag to ask for higher priority:
WQ_HIGHPRI:
Work items of a highpri wq are queued to the highpri thread-pool of
the target gcwq. Highpri thread-pools are served by worker threads
with elevated nice level.
Note that normal and highpri thread-pools don't interact with each
other. Each maintain its separate pool of workers and implements
concurrency management among its workers.
I cannot answer all your questions, but I hope this helps anyway.