The longstanding task queue interface was removed in 2.5.41; in its place
is a new "workqueue" mechanism. Workqueues are very similar to task
queues, but there are some important differences. Among other things, each
workqueue has one or more dedicated worker threads (one per CPU, by default)
associated with it. So all tasks running out of workqueues have a process
context, and can thus sleep. Note that access to user space is not
possible from code running out of a workqueue; there simply is no user
space to access. Drivers can create their own work queues - with their own
worker threads - but there is a default queue (for each processor) provided
by the kernel that will work in most situations.
Workqueues are created with one of:
struct workqueue_struct *create_workqueue(const char *name);
struct workqueue_struct *create_singlethread_workqueue(const char *name);
A workqueue created with create_workqueue()
will have one worker
thread for each CPU on the system;
, instead, creates a workqueue with
a single worker process.
The name of the queue is limited to ten characters; it is only used for
generating the "command" for the kernel thread(s) (which can be seen in
Tasks to be run out of a workqueue need to be packaged in a
struct work_struct structure. This structure may be declared
and initialized at compile time as follows:
DECLARE_WORK(name, void (*function)(void *), void *data);
is the name of the resulting work_struct
is the function to call to execute the work, and
is a pointer to pass to that function.
To set up a work_struct structure at run time, instead, use the following two
INIT_WORK(struct work_struct *work,
void (*function)(void *), void *data);
PREPARE_WORK(struct work_struct *work,
void (*function)(void *), void *data);
The difference between the two is that INIT_WORK
linked list pointers within the work_struct
changes only the function and data pointers.
must be used at least once before queueing the
structure, but should not
be used if the
might already be in a workqueue.
Actually queueing a job to be executed is simple:
int queue_work(struct workqueue_struct *queue,
struct work_struct *work);
int queue_delayed_work(struct workqueue_struct *queue,
struct work_struct *work,
unsigned long delay);
The second form of the call ensures that a minimum delay (in jiffies)
passes before the work is actually executed.
The return value from both functions
is nonzero if the work_struct
was actually added to
(otherwise, it may have already been there and will not be
added a second time).
Entries in workqueues are executed at some undefined time in the future,
when the associated worker thread is scheduled to run (and after the delay
period, if any, has passed). If it is necessary to cancel a delayed task,
you can do so with:
int cancel_delayed_work(struct work_struct *work);
Note that this workqueue entry could actually be executing when
returns; all this function will do is keep
it from starting after the call.
To ensure that none of your workqueue entries are running, call:
void flush_workqueue(struct workqueue_struct *queue);
This would be a good thing to do, for example, in a device
driver shutdown routine. Note that if the queue contains work with long
delays this call could take a long time to complete. This function will
(as of 2.5.68) wait for any work entries submitted after the
call was first made; you should ensure that, for example, any outstanding
work queue entries will not resubmit themselves. You should also cancel
any delayed entries (with cancel_delayed_work()
) first if need be.
Work queues can be destroyed with:
void destroy_workqueue(struct workqueue_struct *queue);
This operation will flush the queue, then delete it.
Finally, for tasks that do not justify their own workqueue, a "default"
work queue (called "events") is defined. work_struct
structures can be added to this queue with:
int schedule_work(struct work_struct *work);
int schedule_delayed_work(struct work_struct *work, unsigned long delay);
Most users of workqueues can probably use the predefined queue, but one
should bear in mind that it is a shared resource. Long delays in the
worker function will slow down other users of the queue, and should be
There is a flush_scheduled_work()
function which will wait for
everything on this queue to be executed. If your module uses the default
queue, it should almost certainly call flush_scheduled_work()
before allowing itself to be unloaded.
One final note: schedule_work(), schedule_delayed_work()
and flush_scheduled_work() are exported to any modules which wish
to use them. The other functions (for working with separate workqueues)
are exported to GPL-licensed modules only.
to post comments)