In linux Kernel implementation for ARM platform, deferred work in tasklet is added to percpu vec|vec_hi list.
how? can someone help me with this... If this is so, what am I missing?
It's true. While the tasklet can be scheduled (i.e. tasklet execution requested) on any number of CPUs, it will only be executed on one.
The reason for this is I believe to simplify the development model: to make it easier to implement what is essentially an interrupt handler without needing to worry about races due to simultaneous execution on multiple processors -- and while not disabling other interrupts. (Obviously there are still many other opportunities for races that a driver developer needs to be aware of, but these are among the most difficult to solve.)
If you're asking about the implementation, it's actually pretty simple. In tasklet_action
, tasklet_trylock
is called. It uses the guaranteed-atomic function test_and_set_bit
to set the TASKLET_STATE_RUN
bit. This can only succeed on one processor. Hence, all other processors are prevented from executing the tasklet until the bit has been cleared -- which is only done by the processor that set it after the tasklet has completed.
EDIT:
Clarifying: calling tasklet_schedule
on any number of CPUs (prior to execution) results in the tasklet being executed exactly once: on the first CPU that made the call. The same mechanism (test_and_set_bit
) ensures that if the tasklet has already been scheduled on some other CPU but has not yet been executed, it will not be added to the tasklets-to-run queue on the later CPU (and hence won't be executed on the later CPU at all).
On the other hand, if it has already begun executing on the first CPU, the TASKLET_STATE_SCHEDULE
bit will have been cleared (and hence may be set again), and so another call to tasklet_schedule
ensures that the tasklet will eventually be re-executed on the later CPU, but not until after it has run to completion on the first CPU.