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