Pages

Difference between tasklet and workqueue


In the last few posts we saw the basics of tasklets and workqueues with examples. Both tasklet and workqueue are used for similar purposes, but they are not the same and can not be used instead of each other. Let us look at the differences between them.

This is biggest difference between the two  :

A tasklet always runs in the interrupt context, that means when a tasklet executes it is as if the processor is executing an interrupt service routine.
Thus while executing a tasklet a task can not got to sleep or can not hold a semaphore as neither of them are allowed while in a interrupt service routine.
On the other hand a workqueue executes as a normal process and not a interrupt, hence a worqueue can go to sleep it can hold semaphores.


The above difference will help in deciding when should a tasklet be used and when should a workqueue be used. To see this difference practically we will make use of a function "in_interrupt() ". When called, the function returns true if the task is executing as an interrupt i.e. in interrupt context else it returns false.

We will add this function call to the exaples of tasklet_init and workqueue_runtime and try to find out if tasklet runs in a interrupt context or not.

We only need to modify the tasklet and workqueue functions from the previous example and here are the modified functions

tasklet :  Modified task_fn

void task_fn(unsigned long arg)
{


printk(KERN_INFO "In tasklet function");
if(in_interrupt())
        printk(KERN_INFO "Running as an interrupt");
else
        printk(KERN_INFO "Running as a process");
printk(KERN_INFO "\n The state is %d",task->state);
printk(KERN_INFO "\n The count is %d",task->count);
}

workqueue: Modified work_fn

void workq_fn(unsigned long arg)
{


if(in_interrupt())
        printk(KERN_INFO "Running as an interrupt");
else
        printk(KERN_INFO "Running as a process");
atomic_long_set(&(workq->data),10);


printk(KERN_INFO "In workq function %u",atomic_long_read(&(workq->data)));
}



Modify the tasklet_init.c and workq_runtime.c as shown above. Compile and insert both the modules . If there are no errors in compiling and inserting
we can see the difference betwee the tasklet and worqueue as follows

$ cat /proc/initask
$ dmesg | tail -6
In proc initask
 In tasklet function
Running as an interrupt


 The state is 2

 The count is 0


$ cat /proc/sched_work
$ demsg | tail -4

In proc sched workq
Running as a processIn workq function 10


As we can see in the above output, when we run the tasklet we see that the task is running in the interrupt context and when we run the task in a workqueue it does not run as a interrupt but as a process.



No comments:

Post a Comment