Eliminating tasklets
[Posted June 24, 2007 by corbet]
Tasklets are a deferred-execution method used within the kernel; they were
added in the 2.3 development series as a way for interrupt handlers to
schedule work to be done in the very near future. Essentially, a tasklet
is a function to be called (with a data pointer) in a software interrupt as
soon as the kernel is able to do so.
In practice, a tasklet which is scheduled will (probably) be executed when
the kernel either (1) finishes running an interrupt handler, or
(2) returns to user space. Since tasklets run in software interrupt
mode, they must be atomic - no sleeping, references to user space, etc. So
the work that can be done in tasklets is limited, but they are still
heavily used within the kernel.
There is another problem with tasklets: since they run as software
interrupts, they have a higher priority than any process on the system.
Tasklets can, thus, create unbounded latencies - something which the
low-latency developers have been long working to eliminate. Some efforts
have been made to mitigate this problem; if the kernel has a hard time
keeping up with software interrupts it will eventually dump them into the
ksoftirqd process and let them fight it out in the scheduler.
Specific tasklets which have been shown to create latency problems - the
RCU callback handler, for example - have been made to behave better. And
the realtime tree pushes all software interrupt handling into separate
processes which can be scheduled (and preempted) like anything else.
Recently, Steven Rostedt came up with a different approach: why not
just get rid of tasklets altogether? Since the development of tasklets,
the kernel has acquired other, more flexible ways of deferring work; in
particular, workqueues function much like tasklets, but without many of the
disadvantages of tasklets. Since workqueues use dedicated worker
processes, they can be preempted and do not present the same latency
problems as tasklets; as a
bonus, they provide a process context which allows work functions to sleep
if need be. Workqueues, argues Steven, are sufficiently capable that there
is no need for tasklets anymore.
So Steven's patch cleans up the interface in a few ways, and turns the RCU
tasklet into a separate software interrupt outside of the tasklet
mechanism. Then the tasklet code is torn out and replaced with a wrapper
interface which conceals a workqueue underneath. The end result is a
tasklet-free kernel without the need to rewrite all of the code which uses
tasklets.
There is little opposition to the idea of eliminating tasklets, though it
is clear that quite a bit of performance testing will be required before
such a change could go into the mainline kernel. But almost nobody likes
the wrapper interface; it is just the sort of compatibility glue that the
"no stable internal API" policy tries to avoid. So there is a lot of
pressure to dump the wrapper and simply convert all tasklet users directly
to workqueues. Needless to say, this is a rather larger job; it's not
surprising that somebody might be tempted to try to avoid it. In any case,
the current patch is good for testing; if the replacement of tasklets will
cause trouble, this patch should turn it up before anybody has gone to the
trouble of converting all the tasklet users.
Another question needs to be answered here, though: does the conversion of
tasklets to workqueues lead to a better interrupt handling path, or should
wider changes be considered? Rather than doing a context switch into a
workqueue process, the system might get better performance by simply
running the interrupt handler as a thread as well. As it happens, the
realtime tree has long done exactly that: all (OK, almost all) interrupt
handlers run in their own threads. The realtime developers have plans to
merge this work within the next few kernel cycles.
Under the current plans, threaded interrupt handlers would probably be a
configuration-time option. But if developers knew that interrupt
handlers would run in process context, they could simply do the necessary
processing in the handler and do away with deferred work mechanisms
altogether. This approach might not work in every driver - for some
devices, it might risk adding unacceptable interrupt response latency -
but, in many cases, it has the potential to simplify and streamline the
situation considerably. The code would not just be simpler - it might just
perform better as well.
Either way, the removal of tasklets would appear to be in the works. As a
step in that direction, Ingo Molnar is looking
for potential performance problems:
So how about the following, different approach: anyone who has a
tasklet in any performance-sensitive codepath, please yell
now. We'll also do a proactive search for such places. We can
convert those places to softirqs, or move them back into hardirq
context. Once this is done - and i doubt it will go beyond 1-2
places - we can just mass-convert the other 110 places to the lame
but compatible solution of doing them in a global thread context.
This is a fairly clear call to action for anybody who is concerned about
the possible performance impact of this change on any particular part of
the kernel. If you think some code needs faster deferred work response
than a workqueue-based mechanism can provide, now is not the time to defer
the work of responding to this request.
(
Log in to post comments)