Monday 2 December 2013

Tasklet Vs Work queues [Part-II]

For Tasklet Vs Work queues [Part-I], please click here.

Work queues

Work queues are added in linux kernel 2.6 version. And, one major difference between Work queues and Tasklets is that the handler function of work queues can sleep but not possible in the case of Tasklet's handler function.

Another difference is that the Work queues have higher latency than Tasklet.

We should look at two main data structures in the Work queue mechanism.
  1. struct workqueue_struct
  2. struct work_struct
The core work queue is represented by structure struct workqueue_struct, which is the structure onto which work is placed. This work is added to queue in the top half (Interrupt context) and execution of this work happened in the bottom half (Kernel context).

The work is represented by structure struct work_struct, which identifies the work and the deferral function.

Kernel threads named "events/X" will extract work from the core work queue and activates the work's handler function.

Work queue APIs

Create and destroy work queue structure

struct workqueue_struct *create_workqueue(name); /* Creates core workqueue */
void destroy_workqueue(struct workqueue_struct *); /* Destroy the workqueue */

Initialization of work structure

Work queue API provides 3 macros which initializes the work and also set the function handler.

INIT_WORK(work, function);
INIT_DELAYED_WORK(work, function); /* if we add any delay before adding this work into work queue structure */
INIT_DELAYED_WORK_DEFERRABLE(work, function);

EnQueue work on to work queue

Below are work queue APIs used for adding queue on to work queue.

int queue_work (struct workqueue_struct *wq, struct work_struct *work);
int queue_work_on (int cpu, struct workqueue_struct *wq, struct work_struct *work); /*  specify the CPU on which the handler should run */
int queue_delayed_work (struct workqueue_struct *wq, struct delayed_work *work), unsigned long delay); /* Queue specified work on to specified work queue after delay */
int queue_delayed_work_on (int cpu, struct workqueue_struct *wq, struct delayed_work *work), unsigned long delay);

The below functions doesn't require workqueue structure defined. These functions uses kernel-global work queue. So, no need to pass workqueue_struct in the argument list.

int schedule_work (struct work_struct *):
int schedule_work_on (int cpu, struct work_struct *):
int scheduled_delayed_work (struct delayed_work *, unsigned long delay);
int scheduled_delayed_work_on (int cpu, struct delayed_work *, unsigned long delay);

Cancel work

/* terminate work in the queue, which is not already executing in the handler */
int cancel_work_sync (struct work_struct *); 
int cancel_delayed_work_sync (struct delayed_work *);

Flush work

Below functions are used to flush the work and works in the specified workqueue.
/* Flush a particular work and block until it is completed */
int flush_work (struct work_struct *);
/* Flush all works in given workqueue and block until it is completed */
int flush_workqueue (struct workqueue_struct *);
/* Flush  kernel-global work queue */
void flush_scheduled_work (void);

Status of work

We can use below two functions to know whether the given work is pending i.e. its handler function is not yet started.
work_pending(work);
delayed_work_pending (work);

Next: Will share running examples for Tasklet and work queues.

No comments:

Post a Comment

You might also like

Related Posts Plugin for WordPress, Blogger...