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