3 .\" Copyright (c) 2000 Doug Rabson
5 .\" All rights reserved.
7 .\" This program is free software.
9 .\" Redistribution and use in source and binary forms, with or without
10 .\" modification, are permitted provided that the following conditions
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.
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.
34 .Nd asynchronous task execution
42 typedef void (*task_fn_t)(void *context, int pending);
44 typedef void (*taskqueue_enqueue_fn)(void *context);
47 STAILQ_ENTRY(task) ta_link; /* link for queue */
48 u_short ta_pending; /* count times queued */
49 u_short ta_priority; /* priority of task in queue */
50 task_fn_t ta_func; /* task handler */
51 void *ta_context; /* argument for handler */
54 enum taskqueue_callback_type {
55 TASKQUEUE_CALLBACK_TYPE_INIT,
56 TASKQUEUE_CALLBACK_TYPE_SHUTDOWN,
59 typedef void (*taskqueue_callback_fn)(void *context);
63 .Ft struct taskqueue *
64 .Fn taskqueue_create "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context"
65 .Ft struct taskqueue *
66 .Fn taskqueue_create_fast "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context"
68 .Fn taskqueue_start_threads "struct taskqueue **tqp" "int count" "int pri" "const char *name" "..."
70 .Fo taskqueue_start_threads_cpuset
71 .Fa "struct taskqueue **tqp" "int count" "int pri" "cpuset_t *mask"
72 .Fa "const char *name" "..."
75 .Fo taskqueue_start_threads_in_proc
76 .Fa "struct taskqueue **tqp" "int count" "int pri" "struct proc *proc"
77 .Fa "const char *name" "..."
80 .Fn taskqueue_set_callback "struct taskqueue *queue" "enum taskqueue_callback_type cb_type" "taskqueue_callback_fn callback" "void *context"
82 .Fn taskqueue_free "struct taskqueue *queue"
84 .Fn taskqueue_enqueue "struct taskqueue *queue" "struct task *task"
86 .Fn taskqueue_enqueue_flags "struct taskqueue *queue" "struct task *task" "int flags"
88 .Fn taskqueue_enqueue_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" "int ticks"
90 .Fn taskqueue_enqueue_timeout_sbt "struct taskqueue *queue" "struct timeout_task *timeout_task" "sbintime_t sbt" "sbintime_t pr" "int flags"
92 .Fn taskqueue_cancel "struct taskqueue *queue" "struct task *task" "u_int *pendp"
94 .Fn taskqueue_cancel_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" "u_int *pendp"
96 .Fn taskqueue_drain "struct taskqueue *queue" "struct task *task"
98 .Fn taskqueue_drain_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task"
100 .Fn taskqueue_drain_all "struct taskqueue *queue"
102 .Fn taskqueue_quiesce "struct taskqueue *queue"
104 .Fn taskqueue_block "struct taskqueue *queue"
106 .Fn taskqueue_unblock "struct taskqueue *queue"
108 .Fn taskqueue_member "struct taskqueue *queue" "struct thread *td"
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"
120 These functions provide a simple interface for asynchronous execution
125 is used to create new queues.
128 include a name that should be unique,
131 flags that specify whether the call to
134 a function that is called from
135 .Fn taskqueue_enqueue
136 when a task is added to the queue,
137 and a pointer to the memory location where the identity of the
138 thread that services the queue is recorded.
139 .\" XXX The rest of the sentence gets lots in relation to the first part.
140 The function called from
141 .Fn taskqueue_enqueue
142 must arrange for the queue to be processed
143 (for instance by scheduling a software interrupt or waking a kernel
145 The memory location where the thread identity is recorded is used
146 to signal the service thread(s) to terminate--when this value is set to
147 zero and the thread is signaled it will terminate.
148 If the queue is intended for use in fast interrupt handlers
149 .Fn taskqueue_create_fast
150 should be used in place of
151 .Fn taskqueue_create .
155 should be used to free the memory used by the queue.
156 Any tasks that are on the queue will be executed at this time after
157 which the thread servicing the queue will be signaled that it should exit.
159 Once a taskqueue has been created, its threads should be started using
160 .Fn taskqueue_start_threads ,
161 .Fn taskqueue_start_threads_cpuset
163 .Fn taskqueue_start_threads_in_proc .
164 .Fn taskqueue_start_threads_cpuset
167 argument which will cause the threads which are started for the taskqueue
168 to be restricted to run on the given CPUs.
169 .Fn taskqueue_start_threads_in_proc
172 argument which will cause the threads which are started for the taskqueue
173 to be assigned to the given kernel process.
174 Callbacks may optionally be registered using
175 .Fn taskqueue_set_callback .
176 Currently, callbacks may be registered for the following purposes:
177 .Bl -tag -width TASKQUEUE_CALLBACK_TYPE_SHUTDOWN
178 .It Dv TASKQUEUE_CALLBACK_TYPE_INIT
179 This callback is called by every thread in the taskqueue, before it executes
181 This callback must be set before the taskqueue's threads are started.
182 .It Dv TASKQUEUE_CALLBACK_TYPE_SHUTDOWN
183 This callback is called by every thread in the taskqueue, after it executes
185 This callback will always be called before the taskqueue structure is
189 To add a task to the list of tasks queued on a taskqueue, call
190 .Fn taskqueue_enqueue
191 with pointers to the queue and task.
195 then it is simply incremented to reflect the number of times the task
196 was enqueued, up to a cap of USHRT_MAX.
198 the task is added to the list before the first task which has a lower
200 value or at the end of the list if no tasks have a lower priority.
201 Enqueueing a task does not perform any memory allocation which makes
202 it suitable for calling from an interrupt handler.
203 This function will return
205 if the queue is being freed.
207 When a task is executed,
208 first it is removed from the queue,
211 is recorded and then the field is zeroed.
214 from the task structure is called with the value of the field
216 as its first argument
219 as its second argument.
224 is called on the task pointer passed to
225 .Fn taskqueue_enqueue .
228 .Fn taskqueue_enqueue_flags
231 parameter which specifies a set of optional flags to alter the behavior of
232 .Fn taskqueue_enqueue .
233 It contains one or more of the following flags:
234 .Bl -tag -width TASKQUEUE_FAIL_IF_CANCELING
235 .It Dv TASKQUEUE_FAIL_IF_PENDING
236 .Fn taskqueue_enqueue_flags
237 fails if the task is already scheduled for execution.
241 counter value remains unchanged.
242 .It Dv TASKQUEUE_FAIL_IF_CANCELING
243 .Fn taskqueue_enqueue_flags
244 fails if the task is in the canceling state and
250 .Fn taskqueue_enqueue_timeout
251 function is used to schedule the enqueue after the specified number of
254 .Fn taskqueue_enqueue_timeout_sbt
255 function provides finer control over the scheduling based on
264 argument is negative, the already scheduled enqueueing is not re-scheduled.
265 Otherwise, the task is scheduled for enqueueing in the future,
266 after the absolute value of
269 This function returns -1 if the task is being drained.
270 Otherwise, the number of pending calls is returned.
274 function is used to cancel a task.
277 count is cleared, and the old value returned in the reference
282 If the task is currently running,
284 is returned, otherwise 0.
285 To implement a blocking
287 that waits for a running task to finish, it could look like:
288 .Bd -literal -offset indent
289 while (taskqueue_cancel(tq, task, NULL) != 0)
290 taskqueue_drain(tq, task);
294 .Fn taskqueue_drain ,
295 the caller is responsible for ensuring that the task is not re-enqueued
296 after being canceled.
299 .Fn taskqueue_cancel_timeout
300 function is used to cancel the scheduled task execution.
304 function is used to wait for the task to finish, and
306 .Fn taskqueue_drain_timeout
307 function is used to wait for the scheduled task to finish.
308 There is no guarantee that the task will not be
309 enqueued after call to
310 .Fn taskqueue_drain .
311 If the caller wants to put the task into a known state,
314 the caller should use out-of-band means to ensure that the task
315 would not be enqueued.
316 For example, if the task is enqueued by an interrupt filter, then
317 the interrupt could be disabled.
320 .Fn taskqueue_drain_all
321 function is used to wait for all pending and running tasks that
322 are enqueued on the taskqueue to finish.
323 Tasks posted to the taskqueue after
324 .Fn taskqueue_drain_all
326 including pending enqueues scheduled by a previous call to
327 .Fn taskqueue_enqueue_timeout ,
328 do not extend the wait time of
329 .Fn taskqueue_drain_all
330 and may complete after
331 .Fn taskqueue_drain_all
334 .Fn taskqueue_quiesce
335 function is used to wait for the queue to become empty and for all
336 running tasks to finish.
337 To avoid blocking indefinitely, the caller must ensure by some mechanism
338 that tasks will eventually stop being posted to the queue.
342 function blocks the taskqueue.
343 It prevents any enqueued but not running tasks from being executed.
345 .Fn taskqueue_enqueue
346 will enqueue tasks, but the tasks will not be run until
347 .Fn taskqueue_unblock
351 does not wait for any currently running tasks to finish.
354 does not provide a guarantee that
358 returns, but it does provide a guarantee that
360 will not be called again
362 .Fn taskqueue_unblock
364 If the caller requires a guarantee that
366 is not running, then this must be arranged by the caller.
369 is called on a task that is enqueued on a taskqueue that is blocked by
370 .Fn taskqueue_block ,
373 can not return until the taskqueue is unblocked.
374 This can result in a deadlock if the thread blocked in
376 is the thread that is supposed to call
377 .Fn taskqueue_unblock .
382 is discouraged, because the state of the task can not be known in advance.
383 The same caveat applies to
384 .Fn taskqueue_drain_all .
387 .Fn taskqueue_unblock
388 function unblocks the previously blocked taskqueue.
389 All enqueued tasks can be run after this call.
397 is part of the given taskqueue
405 function will run all pending tasks in the specified
407 Normally this function is only used internally.
410 .Fn TASK_INIT "task" "priority" "func" "context"
411 is provided to initialise a
416 macro generates an initializer for a task structure.
418 .Fn TIMEOUT_TASK_INIT "queue" "timeout_task" "priority" "func" "context"
427 are simply copied into the task structure fields and the
432 .Fn TASKQUEUE_DECLARE "name" ,
433 .Fn TASKQUEUE_DEFINE "name" "enqueue" "context" "init" ,
434 .Fn TASKQUEUE_FAST_DEFINE "name" "enqueue" "context" "init" ,
436 .Fn TASKQUEUE_DEFINE_THREAD "name"
437 .Fn TASKQUEUE_FAST_DEFINE_THREAD "name"
438 are used to declare a reference to a global queue, to define the
439 implementation of the queue, and declare a queue that uses its own thread.
442 macro arranges to call
444 with the values of its
449 arguments during system initialisation.
451 .Fn taskqueue_create ,
454 argument to the macro is executed as a C statement,
455 allowing any further initialisation to be performed
456 (such as registering an interrupt handler, etc.).
459 .Fn TASKQUEUE_DEFINE_THREAD
460 macro defines a new taskqueue with its own kernel thread to serve tasks.
462 .Vt struct taskqueue *taskqueue_name
463 is used to enqueue tasks onto the queue.
465 .Fn TASKQUEUE_FAST_DEFINE
467 .Fn TASKQUEUE_FAST_DEFINE_THREAD
471 .Fn TASKQUEUE_DEFINE_THREAD
472 respectively but taskqueue is created with
473 .Fn taskqueue_create_fast .
474 .Ss Predefined Task Queues
475 The system provides four global taskqueues,
478 .Va taskqueue_swi_giant ,
480 .Va taskqueue_thread .
483 queue is for swi handlers dispatched from fast interrupt handlers,
484 where sleep mutexes cannot be used.
485 The swi taskqueues are run via a software interrupt mechanism.
488 queue runs without the protection of the
491 .Va taskqueue_swi_giant
492 queue runs with the protection of the
497 runs in a kernel thread context, and tasks run from this thread do
501 If the caller wants to run under
503 he should explicitly acquire and release
505 in his taskqueue handler routine.
509 .Fn taskqueue_enqueue
510 with the value of the global taskqueue variable for the queue you wish to
513 The software interrupt queues can be used,
514 for instance, for implementing interrupt handlers which must perform a
515 significant amount of processing in the handler.
516 The hardware interrupt handler would perform minimal processing of the
517 interrupt and then enqueue a task to finish the work.
518 This reduces to a minimum
519 the amount of time spent with interrupts disabled.
521 The thread queue can be used, for instance, by interrupt level routines
522 that need to call kernel functions that do things that can only be done
523 from a thread context.
524 (e.g., call malloc with the M_WAITOK flag.)
526 Note that tasks queued on shared taskqueues such as
528 may be delayed an indeterminate amount of time before execution.
529 If queueing delays cannot be tolerated then a private taskqueue should
530 be created with a dedicated processing thread.
537 This interface first appeared in
539 There is a similar facility called work_queue in the Linux kernel.
541 This manual page was written by