xref: /freebsd/share/man/man9/taskqueue.9 (revision 884a2a699669ec61e2366e3e358342dbc94be24a)
1.\" -*- nroff -*-
2.\"
3.\" Copyright (c) 2000 Doug Rabson
4.\"
5.\" All rights reserved.
6.\"
7.\" This program is free software.
8.\"
9.\" Redistribution and use in source and binary forms, with or without
10.\" modification, are permitted provided that the following conditions
11.\" are met:
12.\" 1. Redistributions of source code must retain the above copyright
13.\"    notice, this list of conditions and the following disclaimer.
14.\" 2. Redistributions in binary form must reproduce the above copyright
15.\"    notice, this list of conditions and the following disclaimer in the
16.\"    documentation and/or other materials provided with the distribution.
17.\"
18.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
19.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
22.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28.\"
29.\" $FreeBSD$
30.\"
31.Dd April 26, 2011
32.Dt TASKQUEUE 9
33.Os
34.Sh NAME
35.Nm taskqueue
36.Nd asynchronous task execution
37.Sh SYNOPSIS
38.In sys/param.h
39.In sys/kernel.h
40.In sys/malloc.h
41.In sys/queue.h
42.In sys/taskqueue.h
43.Bd -literal
44typedef void (*task_fn_t)(void *context, int pending);
45
46typedef void (*taskqueue_enqueue_fn)(void *context);
47
48struct task {
49	STAILQ_ENTRY(task)	ta_link;	/* link for queue */
50	u_short			ta_pending;	/* count times queued */
51	u_short			ta_priority;	/* priority of task in queue */
52	task_fn_t		ta_func;	/* task handler */
53	void			*ta_context;	/* argument for handler */
54};
55
56struct timeout_task;
57.Ed
58.Ft struct taskqueue *
59.Fn taskqueue_create "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context"
60.Ft struct taskqueue *
61.Fn taskqueue_create_fast "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context"
62.Ft void
63.Fn taskqueue_free "struct taskqueue *queue"
64.Ft int
65.Fn taskqueue_enqueue "struct taskqueue *queue" "struct task *task"
66.Ft int
67.Fn taskqueue_enqueue_fast "struct taskqueue *queue" "struct task *task"
68.Ft int
69.Fn taskqueue_enqueue_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" "int ticks"
70.Ft int
71.Fn taskqueue_cancel "struct taskqueue *queue" "struct task *task" "u_int *pendp"
72.Ft int
73.Fn taskqueue_cancel_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" "u_int *pendp"
74.Ft void
75.Fn taskqueue_drain "struct taskqueue *queue" "struct task *task"
76.Ft void
77.Fn taskqueue_drain_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task"
78.Ft int
79.Fn taskqueue_member "struct taskqueue *queue" "struct thread *td"
80.Ft void
81.Fn taskqueue_run "struct taskqueue *queue"
82.Fn TASK_INIT "struct task *task" "int priority" "task_fn_t func" "void *context"
83.Fn TASKQUEUE_DECLARE "name"
84.Fn TASKQUEUE_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init"
85.Fn TASKQUEUE_FAST_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init"
86.Fn TASKQUEUE_DEFINE_THREAD "name"
87.Fn TASKQUEUE_FAST_DEFINE_THREAD "name"
88.Fn TIMEOUT_TASK_INIT "struct taskqueue *queue" "struct timeout_task *timeout_task" "int priority" "task_fn_t func" "void *context"
89.Sh DESCRIPTION
90These functions provide a simple interface for asynchronous execution
91of code.
92.Pp
93The function
94.Fn taskqueue_create
95is used to create new queues.
96The arguments to
97.Fn taskqueue_create
98include a name that should be unique,
99a set of
100.Xr malloc 9
101flags that specify whether the call to
102.Fn malloc
103is allowed to sleep,
104a function that is called from
105.Fn taskqueue_enqueue
106when a task is added to the queue,
107and a pointer to the memory location where the identity of the
108thread that services the queue is recorded.
109.\" XXX	The rest of the sentence gets lots in relation to the first part.
110The function called from
111.Fn taskqueue_enqueue
112must arrange for the queue to be processed
113(for instance by scheduling a software interrupt or waking a kernel
114thread).
115The memory location where the thread identity is recorded is used
116to signal the service thread(s) to terminate--when this value is set to
117zero and the thread is signaled it will terminate.
118If the queue is intended for use in fast interrupt handlers
119.Fn taskqueue_create_fast
120should be used in place of
121.Fn taskqueue_create .
122.Pp
123The function
124.Fn taskqueue_free
125should be used to free the memory used by the queue.
126Any tasks that are on the queue will be executed at this time after
127which the thread servicing the queue will be signaled that it should exit.
128.Pp
129To add a task to the list of tasks queued on a taskqueue, call
130.Fn taskqueue_enqueue
131with pointers to the queue and task.
132If the task's
133.Va ta_pending
134field is non-zero,
135then it is simply incremented to reflect the number of times the task
136was enqueued.
137Otherwise,
138the task is added to the list before the first task which has a lower
139.Va ta_priority
140value or at the end of the list if no tasks have a lower priority.
141Enqueueing a task does not perform any memory allocation which makes
142it suitable for calling from an interrupt handler.
143This function will return
144.Er EPIPE
145if the queue is being freed.
146.Pp
147The function
148.Fn taskqueue_enqueue_fast
149should be used in place of
150.Fn taskqueue_enqueue
151when the enqueuing must happen from a fast interrupt handler.
152This method uses spin locks to avoid the possibility of sleeping in the fast
153interrupt context.
154.Pp
155When a task is executed,
156first it is removed from the queue,
157the value of
158.Va ta_pending
159is recorded and then the field is zeroed.
160The function
161.Va ta_func
162from the task structure is called with the value of the field
163.Va ta_context
164as its first argument
165and the value of
166.Va ta_pending
167as its second argument.
168After the function
169.Va ta_func
170returns,
171.Xr wakeup 9
172is called on the task pointer passed to
173.Fn taskqueue_enqueue .
174.Pp
175The
176.Fn taskqueue_enqueue_timeout
177is used to schedule the enqueue after the specified amount of
178.Va ticks .
179Only non-fast task queues can be used for
180.Va timeout_task
181scheduling.
182.Pp
183The
184.Fn taskqueue_cancel
185function is used to cancel a task.
186The
187.Va ta_pending
188count is cleared, and the old value returned in the reference
189parameter
190.Fa pendp ,
191if it is non- Dv NULL .
192If the task is currently running,
193.Dv EBUSY
194is returned, otherwise 0.
195To implement a blocking
196.Fn taskqueue_cancel
197that waits for a running task to finish, it could look like:
198.Bd -literal -offset indent
199while (taskqueue_cancel(tq, task, NULL) != 0)
200	taskqueue_drain(tq, task);
201.Ed
202.Pp
203Note that, as with
204.Fn taskqueue_drain ,
205the caller is responsible for ensuring that the task is not re-enqueued
206after being canceled.
207.Pp
208Similarly, the
209.Fn taskqueue_cancel_timeout
210function is used to cancel the scheduled task execution.
211.Pp
212The
213.Fn taskqueue_drain
214function is used to wait for the task to finish, and
215the
216.Fn taskqueue_drain_timeout
217function is used to wait for the scheduled task to finish.
218There is no guarantee that the task will not be
219enqueued after call to
220.Fn taskqueue_drain .
221.Pp
222The
223.Fn taskqueue_member
224function returns
225.No 1
226if the given thread
227.Fa td
228is part of the given taskqueue
229.Fa queue
230and
231.No 0
232otherwise.
233.Pp
234The
235.Fn taskqueue_run
236function will run all pending tasks in the specified
237.Fa queue .
238Normally this function is only used internally.
239.Pp
240A convenience macro,
241.Fn TASK_INIT "task" "priority" "func" "context"
242is provided to initialise a
243.Va task
244structure.
245A macro
246.Fn TIMEOUT_TASK_INIT "queue" "timeout_task" "priority" "func" "context"
247initializes the timeout_task structure.
248The values of
249.Va priority ,
250.Va func ,
251and
252.Va context
253are simply copied into the task structure fields and the
254.Va ta_pending
255field is cleared.
256.Pp
257Five macros
258.Fn TASKQUEUE_DECLARE "name" ,
259.Fn TASKQUEUE_DEFINE "name" "enqueue" "context" "init" ,
260.Fn TASKQUEUE_FAST_DEFINE "name" "enqueue" "context" "init" ,
261and
262.Fn TASKQUEUE_DEFINE_THREAD "name"
263.Fn TASKQUEUE_FAST_DEFINE_THREAD "name"
264are used to declare a reference to a global queue, to define the
265implementation of the queue, and declare a queue that uses its own thread.
266The
267.Fn TASKQUEUE_DEFINE
268macro arranges to call
269.Fn taskqueue_create
270with the values of its
271.Va name ,
272.Va enqueue
273and
274.Va context
275arguments during system initialisation.
276After calling
277.Fn taskqueue_create ,
278the
279.Va init
280argument to the macro is executed as a C statement,
281allowing any further initialisation to be performed
282(such as registering an interrupt handler etc.)
283.Pp
284The
285.Fn TASKQUEUE_DEFINE_THREAD
286macro defines a new taskqueue with its own kernel thread to serve tasks.
287The variable
288.Vt struct taskqueue *taskqueue_name
289is used to enqueue tasks onto the queue.
290.Pp
291.Fn TASKQUEUE_FAST_DEFINE
292and
293.Fn TASKQUEUE_FAST_DEFINE_THREAD
294act just like
295.Fn TASKQUEUE_DEFINE
296and
297.Fn TASKQUEUE_DEFINE_THREAD
298respectively but taskqueue is created with
299.Fn taskqueue_create_fast .
300.Ss Predefined Task Queues
301The system provides four global taskqueues,
302.Va taskqueue_fast ,
303.Va taskqueue_swi ,
304.Va taskqueue_swi_giant ,
305and
306.Va taskqueue_thread .
307The
308.Va taskqueue_fast
309queue is for swi handlers dispatched from fast interrupt handlers,
310where sleep mutexes cannot be used.
311The swi taskqueues are run via a software interrupt mechanism.
312The
313.Va taskqueue_swi
314queue runs without the protection of the
315.Va Giant
316kernel lock, and the
317.Va taskqueue_swi_giant
318queue runs with the protection of the
319.Va Giant
320kernel lock.
321The thread taskqueue
322.Va taskqueue_thread
323runs in a kernel thread context, and tasks run from this thread do
324not run under the
325.Va Giant
326kernel lock.
327If the caller wants to run under
328.Va Giant ,
329he should explicitly acquire and release
330.Va Giant
331in his taskqueue handler routine.
332.Pp
333To use these queues,
334call
335.Fn taskqueue_enqueue
336with the value of the global taskqueue variable for the queue you wish to
337use
338.Va ( taskqueue_swi ,
339.Va taskqueue_swi_giant ,
340or
341.Va taskqueue_thread ) .
342Use
343.Fn taskqueue_enqueue_fast
344for the global taskqueue variable
345.Va taskqueue_fast .
346.Pp
347The software interrupt queues can be used,
348for instance, for implementing interrupt handlers which must perform a
349significant amount of processing in the handler.
350The hardware interrupt handler would perform minimal processing of the
351interrupt and then enqueue a task to finish the work.
352This reduces to a minimum
353the amount of time spent with interrupts disabled.
354.Pp
355The thread queue can be used, for instance, by interrupt level routines
356that need to call kernel functions that do things that can only be done
357from a thread context.
358(e.g., call malloc with the M_WAITOK flag.)
359.Pp
360Note that tasks queued on shared taskqueues such as
361.Va taskqueue_swi
362may be delayed an indeterminate amount of time before execution.
363If queueing delays cannot be tolerated then a private taskqueue should
364be created with a dedicated processing thread.
365.Sh SEE ALSO
366.Xr ithread 9 ,
367.Xr kthread 9 ,
368.Xr swi 9
369.Sh HISTORY
370This interface first appeared in
371.Fx 5.0 .
372There is a similar facility called work_queue in the Linux kernel.
373.Sh AUTHORS
374This manual page was written by
375.An Doug Rabson .
376