4.1.1.1.3. Tasklet Handling Example
static void tasklet_action (struct softirq_action *a)
{
struct tasklet_struct *list;
// Get the entire tasklet queue
local_irq_disable ();
list = __get_cpu_var (tasklet_vec).head;
__get_cpu_var (tasklet_vec).head = NULL;
__get_cpu_var (tasklet_vec).tail = &__get_cpu_var (tasklet_vec).head;
local_irq_enable ();
// Go through the queue tasklet by tasklet
while (list) {
struct tasklet_struct *t = list;
list = list->next;
// Necessary synchronization with other processors
if (tasklet_trylock (t)) {
if (!atomic_read (&t->count)) {
if (!test_and_clear_bit (TASKLET_STATE_SCHED, &t->state))
BUG ();
t->func (t->data);
tasklet_unlock (t);
continue;
}
tasklet_unlock (t);
}
// Put the executed tasklets back into queue
local_irq_disable();
t->next = NULL;
*__get_cpu_var(tasklet_vec).tail = t;
__get_cpu_var(tasklet_vec).tail = &(t->next);
__raise_softirq_irqoff(TASKLET_SOFTIRQ);
local_irq_enable();
}
}