xref: /freebsd/share/man/man9/taskqueue.9 (revision d786719d90df3240f8f893dd8e19edd46f4273ee)
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 March 1, 2016
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
56enum taskqueue_callback_type {
57	TASKQUEUE_CALLBACK_TYPE_INIT,
58	TASKQUEUE_CALLBACK_TYPE_SHUTDOWN,
59};
60
61typedef void (*taskqueue_callback_fn)(void *context);
62
63struct timeout_task;
64.Ed
65.Ft struct taskqueue *
66.Fn taskqueue_create "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context"
67.Ft struct taskqueue *
68.Fn taskqueue_create_fast "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context"
69.Ft int
70.Fn taskqueue_start_threads "struct taskqueue **tqp" "int count" "int pri" "const char *name" "..."
71.Ft int
72.Fo taskqueue_start_threads_pinned
73.Fa "struct taskqueue **tqp" "int count" "int pri" "int cpu_id"
74.Fa "const char *name" "..."
75.Fc
76.Ft void
77.Fn taskqueue_set_callback "struct taskqueue *queue" "enum taskqueue_callback_type cb_type" "taskqueue_callback_fn callback" "void *context"
78.Ft void
79.Fn taskqueue_free "struct taskqueue *queue"
80.Ft int
81.Fn taskqueue_enqueue "struct taskqueue *queue" "struct task *task"
82.Ft int
83.Fn taskqueue_enqueue_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" "int ticks"
84.Ft int
85.Fn taskqueue_cancel "struct taskqueue *queue" "struct task *task" "u_int *pendp"
86.Ft int
87.Fn taskqueue_cancel_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" "u_int *pendp"
88.Ft void
89.Fn taskqueue_drain "struct taskqueue *queue" "struct task *task"
90.Ft void
91.Fn taskqueue_drain_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task"
92.Ft void
93.Fn taskqueue_drain_all "struct taskqueue *queue"
94.Ft void
95.Fn taskqueue_block "struct taskqueue *queue"
96.Ft void
97.Fn taskqueue_unblock "struct taskqueue *queue"
98.Ft int
99.Fn taskqueue_member "struct taskqueue *queue" "struct thread *td"
100.Ft void
101.Fn taskqueue_run "struct taskqueue *queue"
102.Fn TASK_INIT "struct task *task" "int priority" "task_fn_t func" "void *context"
103.Fn TASK_INITIALIZER "int priority" "task_fn_t func" "void *context"
104.Fn TASKQUEUE_DECLARE "name"
105.Fn TASKQUEUE_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init"
106.Fn TASKQUEUE_FAST_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init"
107.Fn TASKQUEUE_DEFINE_THREAD "name"
108.Fn TASKQUEUE_FAST_DEFINE_THREAD "name"
109.Fn TIMEOUT_TASK_INIT "struct taskqueue *queue" "struct timeout_task *timeout_task" "int priority" "task_fn_t func" "void *context"
110.Sh DESCRIPTION
111These functions provide a simple interface for asynchronous execution
112of code.
113.Pp
114The function
115.Fn taskqueue_create
116is used to create new queues.
117The arguments to
118.Fn taskqueue_create
119include a name that should be unique,
120a set of
121.Xr malloc 9
122flags that specify whether the call to
123.Fn malloc
124is allowed to sleep,
125a function that is called from
126.Fn taskqueue_enqueue
127when a task is added to the queue,
128and a pointer to the memory location where the identity of the
129thread that services the queue is recorded.
130.\" XXX	The rest of the sentence gets lots in relation to the first part.
131The function called from
132.Fn taskqueue_enqueue
133must arrange for the queue to be processed
134(for instance by scheduling a software interrupt or waking a kernel
135thread).
136The memory location where the thread identity is recorded is used
137to signal the service thread(s) to terminate--when this value is set to
138zero and the thread is signaled it will terminate.
139If the queue is intended for use in fast interrupt handlers
140.Fn taskqueue_create_fast
141should be used in place of
142.Fn taskqueue_create .
143.Pp
144The function
145.Fn taskqueue_free
146should be used to free the memory used by the queue.
147Any tasks that are on the queue will be executed at this time after
148which the thread servicing the queue will be signaled that it should exit.
149.Pp
150Once a taskqueue has been created, its threads should be started using
151.Fn taskqueue_start_threads
152or
153.Fn taskqueue_start_threads_pinned .
154.Fn taskqueue_start_threads_pinned
155takes a
156.Va cpu_id
157argument which will cause the threads which are started for the taskqueue
158to be pinned to run on the given CPU.
159Callbacks may optionally be registered using
160.Fn taskqueue_set_callback .
161Currently, callbacks may be registered for the following purposes:
162.Bl -tag -width TASKQUEUE_CALLBACK_TYPE_SHUTDOWN
163.It Dv TASKQUEUE_CALLBACK_TYPE_INIT
164This callback is called by every thread in the taskqueue, before it executes
165any tasks.
166This callback must be set before the taskqueue's threads are started.
167.It Dv TASKQUEUE_CALLBACK_TYPE_SHUTDOWN
168This callback is called by every thread in the taskqueue, after it executes
169its last task.
170This callback will always be called before the taskqueue structure is
171reclaimed.
172.El
173.Pp
174To add a task to the list of tasks queued on a taskqueue, call
175.Fn taskqueue_enqueue
176with pointers to the queue and task.
177If the task's
178.Va ta_pending
179field is non-zero,
180then it is simply incremented to reflect the number of times the task
181was enqueued, up to a cap of USHRT_MAX.
182Otherwise,
183the task is added to the list before the first task which has a lower
184.Va ta_priority
185value or at the end of the list if no tasks have a lower priority.
186Enqueueing a task does not perform any memory allocation which makes
187it suitable for calling from an interrupt handler.
188This function will return
189.Er EPIPE
190if the queue is being freed.
191.Pp
192When a task is executed,
193first it is removed from the queue,
194the value of
195.Va ta_pending
196is recorded and then the field is zeroed.
197The function
198.Va ta_func
199from the task structure is called with the value of the field
200.Va ta_context
201as its first argument
202and the value of
203.Va ta_pending
204as its second argument.
205After the function
206.Va ta_func
207returns,
208.Xr wakeup 9
209is called on the task pointer passed to
210.Fn taskqueue_enqueue .
211.Pp
212The
213.Fn taskqueue_enqueue_timeout
214is used to schedule the enqueue after the specified amount of
215.Va ticks .
216Only non-fast task queues can be used for
217.Va timeout_task
218scheduling.
219If the
220.Va ticks
221argument is negative, the already scheduled enqueueing is not re-scheduled.
222Otherwise, the task is scheduled for enqueueing in the future,
223after the absolute value of
224.Va ticks
225is passed.
226This function returns -1 if the task is being drained.
227Otherwise, the number of pending calls is returned.
228.Pp
229The
230.Fn taskqueue_cancel
231function is used to cancel a task.
232The
233.Va ta_pending
234count is cleared, and the old value returned in the reference
235parameter
236.Fa pendp ,
237if it is
238.Pf non- Dv NULL .
239If the task is currently running,
240.Dv EBUSY
241is returned, otherwise 0.
242To implement a blocking
243.Fn taskqueue_cancel
244that waits for a running task to finish, it could look like:
245.Bd -literal -offset indent
246while (taskqueue_cancel(tq, task, NULL) != 0)
247	taskqueue_drain(tq, task);
248.Ed
249.Pp
250Note that, as with
251.Fn taskqueue_drain ,
252the caller is responsible for ensuring that the task is not re-enqueued
253after being canceled.
254.Pp
255Similarly, the
256.Fn taskqueue_cancel_timeout
257function is used to cancel the scheduled task execution.
258.Pp
259The
260.Fn taskqueue_drain
261function is used to wait for the task to finish, and
262the
263.Fn taskqueue_drain_timeout
264function is used to wait for the scheduled task to finish.
265There is no guarantee that the task will not be
266enqueued after call to
267.Fn taskqueue_drain .
268If the caller wants to put the task into a known state,
269then before calling
270.Fn taskqueue_drain
271the caller should use out-of-band means to ensure that the task
272would not be enqueued.
273For example, if the task is enqueued by an interrupt filter, then
274the interrupt could be disabled.
275.Pp
276The
277.Fn taskqueue_drain_all
278function is used to wait for all pending and running tasks that
279are enqueued on the taskqueue to finish.
280Tasks posted to the taskqueue after
281.Fn taskqueue_drain_all
282begins processing,
283including pending enqueues scheduled by a previous call to
284.Fn taskqueue_enqueue_timeout ,
285do not extend the wait time of
286.Fn taskqueue_drain_all
287and may complete after
288.Fn taskqueue_drain_all
289returns.
290.Pp
291The
292.Fn taskqueue_block
293function blocks the taskqueue.
294It prevents any enqueued but not running tasks from being executed.
295Future calls to
296.Fn taskqueue_enqueue
297will enqueue tasks, but the tasks will not be run until
298.Fn taskqueue_unblock
299is called.
300Please note that
301.Fn taskqueue_block
302does not wait for any currently running tasks to finish.
303Thus, the
304.Fn taskqueue_block
305does not provide a guarantee that
306.Fn taskqueue_run
307is not running after
308.Fn taskqueue_block
309returns, but it does provide a guarantee that
310.Fn taskqueue_run
311will not be called again
312until
313.Fn taskqueue_unblock
314is called.
315If the caller requires a guarantee that
316.Fn taskqueue_run
317is not running, then this must be arranged by the caller.
318Note that if
319.Fn taskqueue_drain
320is called on a task that is enqueued on a taskqueue that is blocked by
321.Fn taskqueue_block ,
322then
323.Fn taskqueue_drain
324can not return until the taskqueue is unblocked.
325This can result in a deadlock if the thread blocked in
326.Fn taskqueue_drain
327is the thread that is supposed to call
328.Fn taskqueue_unblock .
329Thus, use of
330.Fn taskqueue_drain
331after
332.Fn taskqueue_block
333is discouraged, because the state of the task can not be known in advance.
334The same caveat applies to
335.Fn taskqueue_drain_all .
336.Pp
337The
338.Fn taskqueue_unblock
339function unblocks the previously blocked taskqueue.
340All enqueued tasks can be run after this call.
341.Pp
342The
343.Fn taskqueue_member
344function returns
345.No 1
346if the given thread
347.Fa td
348is part of the given taskqueue
349.Fa queue
350and
351.No 0
352otherwise.
353.Pp
354The
355.Fn taskqueue_run
356function will run all pending tasks in the specified
357.Fa queue .
358Normally this function is only used internally.
359.Pp
360A convenience macro,
361.Fn TASK_INIT "task" "priority" "func" "context"
362is provided to initialise a
363.Va task
364structure.
365The
366.Fn TASK_INITIALIZER
367macro generates an initializer for a task structure.
368A macro
369.Fn TIMEOUT_TASK_INIT "queue" "timeout_task" "priority" "func" "context"
370initializes the
371.Va timeout_task
372structure.
373The values of
374.Va priority ,
375.Va func ,
376and
377.Va context
378are simply copied into the task structure fields and the
379.Va ta_pending
380field is cleared.
381.Pp
382Five macros
383.Fn TASKQUEUE_DECLARE "name" ,
384.Fn TASKQUEUE_DEFINE "name" "enqueue" "context" "init" ,
385.Fn TASKQUEUE_FAST_DEFINE "name" "enqueue" "context" "init" ,
386and
387.Fn TASKQUEUE_DEFINE_THREAD "name"
388.Fn TASKQUEUE_FAST_DEFINE_THREAD "name"
389are used to declare a reference to a global queue, to define the
390implementation of the queue, and declare a queue that uses its own thread.
391The
392.Fn TASKQUEUE_DEFINE
393macro arranges to call
394.Fn taskqueue_create
395with the values of its
396.Va name ,
397.Va enqueue
398and
399.Va context
400arguments during system initialisation.
401After calling
402.Fn taskqueue_create ,
403the
404.Va init
405argument to the macro is executed as a C statement,
406allowing any further initialisation to be performed
407(such as registering an interrupt handler etc.)
408.Pp
409The
410.Fn TASKQUEUE_DEFINE_THREAD
411macro defines a new taskqueue with its own kernel thread to serve tasks.
412The variable
413.Vt struct taskqueue *taskqueue_name
414is used to enqueue tasks onto the queue.
415.Pp
416.Fn TASKQUEUE_FAST_DEFINE
417and
418.Fn TASKQUEUE_FAST_DEFINE_THREAD
419act just like
420.Fn TASKQUEUE_DEFINE
421and
422.Fn TASKQUEUE_DEFINE_THREAD
423respectively but taskqueue is created with
424.Fn taskqueue_create_fast .
425.Ss Predefined Task Queues
426The system provides four global taskqueues,
427.Va taskqueue_fast ,
428.Va taskqueue_swi ,
429.Va taskqueue_swi_giant ,
430and
431.Va taskqueue_thread .
432The
433.Va taskqueue_fast
434queue is for swi handlers dispatched from fast interrupt handlers,
435where sleep mutexes cannot be used.
436The swi taskqueues are run via a software interrupt mechanism.
437The
438.Va taskqueue_swi
439queue runs without the protection of the
440.Va Giant
441kernel lock, and the
442.Va taskqueue_swi_giant
443queue runs with the protection of the
444.Va Giant
445kernel lock.
446The thread taskqueue
447.Va taskqueue_thread
448runs in a kernel thread context, and tasks run from this thread do
449not run under the
450.Va Giant
451kernel lock.
452If the caller wants to run under
453.Va Giant ,
454he should explicitly acquire and release
455.Va Giant
456in his taskqueue handler routine.
457.Pp
458To use these queues,
459call
460.Fn taskqueue_enqueue
461with the value of the global taskqueue variable for the queue you wish to
462use.
463.Pp
464The software interrupt queues can be used,
465for instance, for implementing interrupt handlers which must perform a
466significant amount of processing in the handler.
467The hardware interrupt handler would perform minimal processing of the
468interrupt and then enqueue a task to finish the work.
469This reduces to a minimum
470the amount of time spent with interrupts disabled.
471.Pp
472The thread queue can be used, for instance, by interrupt level routines
473that need to call kernel functions that do things that can only be done
474from a thread context.
475(e.g., call malloc with the M_WAITOK flag.)
476.Pp
477Note that tasks queued on shared taskqueues such as
478.Va taskqueue_swi
479may be delayed an indeterminate amount of time before execution.
480If queueing delays cannot be tolerated then a private taskqueue should
481be created with a dedicated processing thread.
482.Sh SEE ALSO
483.Xr ithread 9 ,
484.Xr kthread 9 ,
485.Xr swi 9
486.Sh HISTORY
487This interface first appeared in
488.Fx 5.0 .
489There is a similar facility called work_queue in the Linux kernel.
490.Sh AUTHORS
491This manual page was written by
492.An Doug Rabson .
493