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.
- struct workqueue_struct
- 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