xref: /dflybsd-src/share/man/man9/taskqueue.9 (revision 4fd5682d8a55982ddf3ff3b6f569250f409487d6)
1a247c996SSascha Wildner.\"
2a247c996SSascha Wildner.\" Copyright (c) 2000 Doug Rabson
3a247c996SSascha Wildner.\"
4a247c996SSascha Wildner.\" All rights reserved.
5a247c996SSascha Wildner.\"
6a247c996SSascha Wildner.\" This program is free software.
7a247c996SSascha Wildner.\"
8a247c996SSascha Wildner.\" Redistribution and use in source and binary forms, with or without
9a247c996SSascha Wildner.\" modification, are permitted provided that the following conditions
10a247c996SSascha Wildner.\" are met:
11a247c996SSascha Wildner.\" 1. Redistributions of source code must retain the above copyright
12a247c996SSascha Wildner.\"    notice, this list of conditions and the following disclaimer.
13a247c996SSascha Wildner.\" 2. Redistributions in binary form must reproduce the above copyright
14a247c996SSascha Wildner.\"    notice, this list of conditions and the following disclaimer in the
15a247c996SSascha Wildner.\"    documentation and/or other materials provided with the distribution.
16a247c996SSascha Wildner.\"
17a247c996SSascha Wildner.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
18a247c996SSascha Wildner.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19a247c996SSascha Wildner.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20a247c996SSascha Wildner.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
21a247c996SSascha Wildner.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22a247c996SSascha Wildner.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23a247c996SSascha Wildner.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24a247c996SSascha Wildner.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25a247c996SSascha Wildner.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26a247c996SSascha Wildner.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27a247c996SSascha Wildner.\"
28a247c996SSascha Wildner.\" $FreeBSD: src/share/man/man9/taskqueue.9,v 1.21 2007/07/09 06:24:10 jmg Exp $
29a247c996SSascha Wildner.\"
30ba36e674SFrançois Tigeot.Dd July 24, 2013
31a247c996SSascha Wildner.Dt TASKQUEUE 9
32a247c996SSascha Wildner.Os
33a247c996SSascha Wildner.Sh NAME
34cb24fcd4SSascha Wildner.Nm taskqueue_block ,
35ba36e674SFrançois Tigeot.Nm taskqueue_cancel ,
36ba36e674SFrançois Tigeot.Nm taskqueue_cancel_timeout ,
37a247c996SSascha Wildner.Nm taskqueue_create ,
387704a16fSSascha Wildner.Nm taskqueue_drain ,
39ba36e674SFrançois Tigeot.Nm taskqueue_drain_timeout ,
40cb24fcd4SSascha Wildner.Nm taskqueue_enqueue ,
41ba36e674SFrançois Tigeot.Nm taskqueue_enqueue_timeout ,
42a247c996SSascha Wildner.Nm taskqueue_free ,
43a247c996SSascha Wildner.Nm taskqueue_find ,
44a247c996SSascha Wildner.Nm taskqueue_run ,
45cb24fcd4SSascha Wildner.Nm taskqueue_start_threads ,
46cb24fcd4SSascha Wildner.Nm taskqueue_unblock ,
47a247c996SSascha Wildner.Nm TASK_INIT ,
48a247c996SSascha Wildner.Nm TASKQUEUE_DECLARE ,
49a247c996SSascha Wildner.Nm TASKQUEUE_DEFINE
50a247c996SSascha Wildner.Nd asynchronous task execution
51a247c996SSascha Wildner.Sh SYNOPSIS
52a247c996SSascha Wildner.In sys/param.h
53a247c996SSascha Wildner.In sys/kernel.h
54a247c996SSascha Wildner.In sys/malloc.h
55a247c996SSascha Wildner.In sys/queue.h
56a247c996SSascha Wildner.In sys/taskqueue.h
57a247c996SSascha Wildner.Bd -literal
58a247c996SSascha Wildnertypedef void (*task_fn_t)(void *context, int pending);
59a247c996SSascha Wildner
60a247c996SSascha Wildnertypedef void (*taskqueue_enqueue_fn)(void *context);
61a247c996SSascha Wildner
62a247c996SSascha Wildnerstruct task {
63a247c996SSascha Wildner	STAILQ_ENTRY(task)	ta_link;	/* link for queue */
64a247c996SSascha Wildner	int			ta_pending;	/* count times queued */
65a247c996SSascha Wildner	int			ta_priority;	/* priority of task in queue */
66a247c996SSascha Wildner	task_fn_t		ta_func;	/* task handler */
67a247c996SSascha Wildner	void			*ta_context;	/* argument for handler */
68a247c996SSascha Wildner};
69a247c996SSascha Wildner.Ed
70a247c996SSascha Wildner.Ft struct taskqueue *
71a247c996SSascha Wildner.Fn taskqueue_create "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context"
72a247c996SSascha Wildner.Ft void
73a247c996SSascha Wildner.Fn taskqueue_free "struct taskqueue *queue"
74a247c996SSascha Wildner.Ft struct taskqueue *
75a247c996SSascha Wildner.Fn taskqueue_find "const char *name"
76a247c996SSascha Wildner.Ft int
77a247c996SSascha Wildner.Fn taskqueue_enqueue "struct taskqueue *queue" "struct task *task"
78ba36e674SFrançois Tigeot.Ft int
79ba36e674SFrançois Tigeot.Fn taskqueue_enqueue_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" "int ticks"
80ba36e674SFrançois Tigeot.Ft int
81ba36e674SFrançois Tigeot.Fn taskqueue_cancel "struct taskqueue *queue" "struct task *task" "u_int *pendp"
82ba36e674SFrançois Tigeot.Ft int
83ba36e674SFrançois Tigeot.Fn taskqueue_cancel_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" "u_int *pendp"
84a247c996SSascha Wildner.Ft void
85a247c996SSascha Wildner.Fn taskqueue_run "struct taskqueue *queue"
86a0d61755SAlex Hornung.Ft void
87a0d61755SAlex Hornung.Fn taskqueue_drain "struct taskqueue *queue" "struct task *task"
88a0d61755SAlex Hornung.Ft void
89ba36e674SFrançois Tigeot.Fn taskqueue_drain_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task"
90ba36e674SFrançois Tigeot.Ft void
91a0d61755SAlex Hornung.Fn taskqueue_block "struct taskqueue *queue"
92a0d61755SAlex Hornung.Ft void
93a0d61755SAlex Hornung.Fn taskqueue_unblock "struct taskqueue *queue"
94a0d61755SAlex Hornung.Ft int
9514ae2e95SAlex Hornung.Fn taskqueue_start_threads "struct taskqueue **tqp" "int count" "int pri" "int ncpu" "const char *fmt" "..."
96a247c996SSascha Wildner.Fn TASK_INIT "struct task *task" "int priority" "task_fn_t *func" "void *context"
97a247c996SSascha Wildner.Fn TASKQUEUE_DECLARE "name"
98a247c996SSascha Wildner.Fn TASKQUEUE_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init"
99a247c996SSascha Wildner.Sh DESCRIPTION
100a247c996SSascha WildnerThese functions provide a simple interface for asynchronous execution
101a247c996SSascha Wildnerof code.
102a247c996SSascha Wildner.Pp
103a247c996SSascha WildnerThe function
104a247c996SSascha Wildner.Fn taskqueue_create
105a247c996SSascha Wildneris used to create new queues.
106a247c996SSascha WildnerThe arguments to
107a247c996SSascha Wildner.Fn taskqueue_create
108a247c996SSascha Wildnerinclude a name that should be unique,
109a247c996SSascha Wildnera set of
11087909ed3SSascha Wildner.Xr kmalloc 9
111a247c996SSascha Wildnerflags that specify whether the call to
112a247c996SSascha Wildner.Fn malloc
113a247c996SSascha Wildneris allowed to sleep,
114a247c996SSascha Wildnerand a function which is called from
115a247c996SSascha Wildner.Fn taskqueue_enqueue
116a247c996SSascha Wildnerwhen a task is added to the queue
117a247c996SSascha Wildner.\" XXX	The rest of the sentence gets lots in relation to the first part.
118a247c996SSascha Wildnerto allow the queue to arrange to be run later
119a247c996SSascha Wildner(for instance by scheduling a software interrupt or waking a kernel
120a247c996SSascha Wildnerthread).
121a247c996SSascha Wildner.Pp
122a247c996SSascha WildnerThe function
123a247c996SSascha Wildner.Fn taskqueue_free
124a247c996SSascha Wildnershould be used to remove the queue from the global list of queues
125a247c996SSascha Wildnerand free the memory used by the queue.
126a247c996SSascha WildnerAny tasks that are on the queue will be executed at this time.
127a247c996SSascha Wildner.Pp
128a247c996SSascha WildnerThe system maintains a list of all queues which can be searched using
129a247c996SSascha Wildner.Fn taskqueue_find .
130a247c996SSascha WildnerThe first queue whose name matches is returned, otherwise
131a247c996SSascha Wildner.Dv NULL .
132a247c996SSascha Wildner.Pp
133a247c996SSascha WildnerTo add a task to the list of tasks queued on a taskqueue, call
134a247c996SSascha Wildner.Fn taskqueue_enqueue
135a247c996SSascha Wildnerwith pointers to the queue and task.
136a247c996SSascha WildnerIf the task's
137a247c996SSascha Wildner.Fa ta_pending
138a247c996SSascha Wildnerfield is non-zero,
139a247c996SSascha Wildnerthen it is simply incremented to reflect the number of times the task
140a247c996SSascha Wildnerwas enqueued.
141a247c996SSascha WildnerOtherwise,
142a247c996SSascha Wildnerthe task is added to the list before the first task which has a lower
143a247c996SSascha Wildner.Fa ta_priority
144a247c996SSascha Wildnervalue or at the end of the list if no tasks have a lower priority.
145a247c996SSascha WildnerEnqueueing a task does not perform any memory allocation which makes
146a247c996SSascha Wildnerit suitable for calling from an interrupt handler.
147a247c996SSascha WildnerThis function will return
148a247c996SSascha Wildner.Er EPIPE
149a247c996SSascha Wildnerif the queue is being freed.
150a247c996SSascha Wildner.Pp
151a247c996SSascha WildnerTo execute all the tasks on a queue,
152a247c996SSascha Wildnercall
153a247c996SSascha Wildner.Fn taskqueue_run .
154a247c996SSascha WildnerWhen a task is executed,
155a247c996SSascha Wildnerfirst it is removed from the queue,
156a247c996SSascha Wildnerthe value of
157a247c996SSascha Wildner.Fa ta_pending
158a247c996SSascha Wildneris recorded and then the field is zeroed.
159a247c996SSascha WildnerThe function
160a247c996SSascha Wildner.Fa ta_func
161a247c996SSascha Wildnerfrom the task structure is called with the value of the field
162a247c996SSascha Wildner.Fa ta_context
163a247c996SSascha Wildneras its first argument
164a247c996SSascha Wildnerand the value of
165a247c996SSascha Wildner.Fa ta_pending
166a247c996SSascha Wildneras its second argument.
167a247c996SSascha Wildner.Pp
168a0d61755SAlex HornungThe
169ba36e674SFrançois Tigeot.Fn taskqueue_enqueue_timeout
170ba36e674SFrançois Tigeotis used to schedule the enqueue after the specified amount of
171ba36e674SFrançois Tigeot.Va ticks .
172ba36e674SFrançois TigeotIf the
173ba36e674SFrançois Tigeot.Va ticks
174ba36e674SFrançois Tigeotargument is negative, the already scheduled enqueueing is not re-scheduled.
175ba36e674SFrançois TigeotOtherwise, the task is scheduled for enqueueing in the future,
176ba36e674SFrançois Tigeotafter the absolute value of
177ba36e674SFrançois Tigeot.Va ticks
178ba36e674SFrançois Tigeotis passed.
179ba36e674SFrançois Tigeot.Pp
180ba36e674SFrançois TigeotThe
181ba36e674SFrançois Tigeot.Fn taskqueue_cancel
182ba36e674SFrançois Tigeotfunction is used to cancel a task.
183ba36e674SFrançois TigeotThe
184ba36e674SFrançois Tigeot.Va ta_pending
185ba36e674SFrançois Tigeotcount is cleared, and the old value returned in the reference
186ba36e674SFrançois Tigeotparameter
187ba36e674SFrançois Tigeot.Fa pendp ,
188ba36e674SFrançois Tigeotif it is
189ba36e674SFrançois Tigeot.Pf non- Dv NULL .
190ba36e674SFrançois TigeotIf the task is currently running,
191*4fd5682dSSascha Wildner.Er EBUSY
192ba36e674SFrançois Tigeotis returned, otherwise 0.
193ba36e674SFrançois TigeotTo implement a blocking
194ba36e674SFrançois Tigeot.Fn taskqueue_cancel
195ba36e674SFrançois Tigeotthat waits for a running task to finish, it could look like:
196ba36e674SFrançois Tigeot.Bd -literal -offset indent
197ba36e674SFrançois Tigeotwhile (taskqueue_cancel(tq, task, NULL) != 0)
198ba36e674SFrançois Tigeot	taskqueue_drain(tq, task);
199ba36e674SFrançois Tigeot.Ed
200ba36e674SFrançois Tigeot.Pp
201ba36e674SFrançois TigeotNote that, as with
202ba36e674SFrançois Tigeot.Fn taskqueue_drain ,
203ba36e674SFrançois Tigeotthe caller is responsible for ensuring that the task is not re-enqueued
204ba36e674SFrançois Tigeotafter being canceled.
205ba36e674SFrançois Tigeot.Pp
206ba36e674SFrançois TigeotSimilarly, the
207ba36e674SFrançois Tigeot.Fn taskqueue_cancel_timeout
208ba36e674SFrançois Tigeotfunction is used to cancel the scheduled task execution.
209ba36e674SFrançois Tigeot.Pp
210ba36e674SFrançois TigeotThe
211a0d61755SAlex Hornung.Fn taskqueue_drain
212ba36e674SFrançois Tigeotfunction is used to wait for the task to finish, and
213ba36e674SFrançois Tigeotthe
214ba36e674SFrançois Tigeot.Fn taskqueue_drain_timeout
215ba36e674SFrançois Tigeotfunction is used to wait for the scheduled task to finish.
216a0d61755SAlex HornungThere is no guarantee that the task will not be
217a0d61755SAlex Hornungenqueued after call to
218a0d61755SAlex Hornung.Fn taskqueue_drain .
219a0d61755SAlex Hornung.Pp
220a0d61755SAlex HornungThe
221a0d61755SAlex Hornung.Fn taskqueue_block
222cb24fcd4SSascha Wildnerfunction is used to block a taskqueue.
223cb24fcd4SSascha WildnerWhen a taskqueue is blocked, calls to
224cb24fcd4SSascha Wildner.Fn taskqueue_enqueue
225cb24fcd4SSascha Wildnerwill still enqueue tasks but
226cb24fcd4SSascha Wildnerthey will not be run until the taskqueue is unblocked by calling
227a0d61755SAlex Hornung.Fn taskqueue_unblock .
228a0d61755SAlex Hornung.Pp
229a0d61755SAlex HornungThe
230a0d61755SAlex Hornung.Fn taskqueue_start_threads
231a0d61755SAlex Hornungfunction is used to create and start
232a0d61755SAlex Hornung.Fa count
233a0d61755SAlex Hornungdedicated threads for the taskqueue specified by
234a0d61755SAlex Hornung.Fa tqp .
235a0d61755SAlex HornungThese threads will be created with the priority specified by
236a0d61755SAlex Hornung.Fa pri
237a0d61755SAlex Hornungand the name given by
238a0d61755SAlex Hornung.Fa fmt
239a0d61755SAlex Hornungwith _N appended to it, where N is the number of the thread.
24014ae2e95SAlex HornungIf
24114ae2e95SAlex Hornung.Fa count
242cb24fcd4SSascha Wildner\*(Gt 1 and
24314ae2e95SAlex Hornung.Fa ncpu
24414ae2e95SAlex Hornungis -1, each of the
24514ae2e95SAlex Hornung.Fa count
24614ae2e95SAlex Hornungthreads will be allocated to a different
24714ae2e95SAlex HornungCPU among all available CPUs in a round robin fashion.
248a0d61755SAlex HornungThe taskqueue specified by
249a0d61755SAlex Hornung.Fa tqp
250a0d61755SAlex Hornungmust be created previously by calling
251a0d61755SAlex Hornung.Fn taskqueue_create
252a0d61755SAlex Hornungwith the argument
253a0d61755SAlex Hornung.Fa enqueue
254a0d61755SAlex Hornungset to
255a0d61755SAlex Hornung.Fa taskqueue_thread_enqueue .
256a0d61755SAlex Hornung.Pp
257a247c996SSascha WildnerA convenience macro,
258a247c996SSascha Wildner.Fn TASK_INIT
259a247c996SSascha Wildneris provided to initialise a
260a247c996SSascha Wildner.Vt task
261a247c996SSascha Wildnerstructure.
262a247c996SSascha WildnerThe values of
263a247c996SSascha Wildner.Fa priority ,
264a247c996SSascha Wildner.Fa func ,
265a247c996SSascha Wildnerand
266a247c996SSascha Wildner.Fa context
267a247c996SSascha Wildnerare simply copied into the task structure fields and the
268a247c996SSascha Wildner.Fa ta_pending
269a247c996SSascha Wildnerfield is cleared.
270a247c996SSascha Wildner.Pp
271a247c996SSascha WildnerTwo macros,
272a247c996SSascha Wildner.Fn TASKQUEUE_DECLARE
273a247c996SSascha Wildnerand
274a247c996SSascha Wildner.Fn TASKQUEUE_DEFINE
275a247c996SSascha Wildnerare used to declare a reference to a global queue,
276a247c996SSascha Wildnerand to define the implementation of the queue.
277a247c996SSascha WildnerThe
278a247c996SSascha Wildner.Fn TASKQUEUE_DEFINE
279a247c996SSascha Wildnermacro arranges to call
280a247c996SSascha Wildner.Fn taskqueue_create
281a247c996SSascha Wildnerwith the values of its
282a247c996SSascha Wildner.Fa name ,
283a247c996SSascha Wildner.Fa enqueue
284a247c996SSascha Wildnerand
285a247c996SSascha Wildner.Fa context
286a247c996SSascha Wildnerarguments during system initialisation.
287a247c996SSascha WildnerAfter calling
288a247c996SSascha Wildner.Fn taskqueue_create ,
289a247c996SSascha Wildnerthe
290a247c996SSascha Wildner.Fa init
291a247c996SSascha Wildnerargument to the macro is executed as a C statement,
292a247c996SSascha Wildnerallowing any further initialisation to be performed
293a247c996SSascha Wildner(such as registering an interrupt handler etc.)
294a247c996SSascha Wildner.Pp
295a0d61755SAlex HornungThe system provides two global taskqueues,
296cb24fcd4SSascha Wildner.Va taskqueue_swi
297cb24fcd4SSascha Wildnerand
298a0d61755SAlex Hornung.Va taskqueue_swi_mp ,
299a0d61755SAlex Hornungwhich are run via a software interrupt mechanism.
300a0d61755SAlex HornungTo use these queues, call
301a247c996SSascha Wildner.Fn taskqueue_enqueue
302a247c996SSascha Wildnerwith the value of the global variable
303cb24fcd4SSascha Wildner.Va taskqueue_swi
304cb24fcd4SSascha Wildneror
305a0d61755SAlex Hornung.Va taskqueue_swi_mp .
306a247c996SSascha Wildner.Pp
307a0d61755SAlex HornungWhile
308a0d61755SAlex Hornung.Va taskqueue_swi
309a0d61755SAlex Hornungacquires the mplock for its tasks,
310a0d61755SAlex Hornung.Va taskqueue_swi_mp
311a0d61755SAlex Hornungis intended for mpsafe tasks and no mplock will be acquired for them.
312a0d61755SAlex HornungThese queues can be used,
313a247c996SSascha Wildnerfor instance, for implementing interrupt handlers which must perform a
314a247c996SSascha Wildnersignificant amount of processing in the handler.
315a247c996SSascha WildnerThe hardware interrupt handler would perform minimal processing of the
316a247c996SSascha Wildnerinterrupt and then enqueue a task to finish the work.
317a247c996SSascha WildnerThis reduces to a minimum
318a247c996SSascha Wildnerthe amount of time spent with interrupts disabled.
319a247c996SSascha Wildner.\".Sh SEE ALSO
320a247c996SSascha Wildner.\".Xr ithread 9 ,
321a247c996SSascha Wildner.\".Xr kthread 9 ,
322a247c996SSascha Wildner.\".Xr swi 9
323a247c996SSascha Wildner.Sh HISTORY
324a247c996SSascha WildnerThis interface first appeared in
325a247c996SSascha Wildner.Fx 5.0 .
326ba36e674SFrançois TigeotThere is a similar facility called work_queue in the Linux kernel.
327a247c996SSascha Wildner.Sh AUTHORS
328a247c996SSascha WildnerThis manual page was written by
329a247c996SSascha Wildner.An Doug Rabson .
330