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.
36 .Nd asynchronous task execution
44 typedef void (*task_fn_t)(void *context, int pending);
46 typedef void (*taskqueue_enqueue_fn)(void *context);
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 */
56 enum taskqueue_callback_type {
57 TASKQUEUE_CALLBACK_TYPE_INIT,
58 TASKQUEUE_CALLBACK_TYPE_SHUTDOWN,
61 typedef void (*taskqueue_callback_fn)(void *context);
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"
70 .Fn taskqueue_start_threads "struct taskqueue **tqp" "int count" "int pri" "const char *name" "..."
72 .Fo taskqueue_start_threads_pinned
73 .Fa "struct taskqueue **tqp" "int count" "int pri" "int cpu_id"
74 .Fa "const char *name" "..."
77 .Fn taskqueue_set_callback "struct taskqueue *queue" "enum taskqueue_callback_type cb_type" "taskqueue_callback_fn callback" "void *context"
79 .Fn taskqueue_free "struct taskqueue *queue"
81 .Fn taskqueue_enqueue "struct taskqueue *queue" "struct task *task"
83 .Fn taskqueue_enqueue_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" "int ticks"
85 .Fn taskqueue_enqueue_timeout_sbt "struct taskqueue *queue" "struct timeout_task *timeout_task" "sbintime_t sbt" "sbintime_t pr" "int flags"
87 .Fn taskqueue_cancel "struct taskqueue *queue" "struct task *task" "u_int *pendp"
89 .Fn taskqueue_cancel_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" "u_int *pendp"
91 .Fn taskqueue_drain "struct taskqueue *queue" "struct task *task"
93 .Fn taskqueue_drain_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task"
95 .Fn taskqueue_drain_all "struct taskqueue *queue"
97 .Fn taskqueue_quiesce "struct taskqueue *queue"
99 .Fn taskqueue_block "struct taskqueue *queue"
101 .Fn taskqueue_unblock "struct taskqueue *queue"
103 .Fn taskqueue_member "struct taskqueue *queue" "struct thread *td"
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"
115 These functions provide a simple interface for asynchronous execution
120 is used to create new queues.
123 include a name that should be unique,
126 flags that specify whether the call to
129 a function that is called from
130 .Fn taskqueue_enqueue
131 when a task is added to the queue,
132 and a pointer to the memory location where the identity of the
133 thread that services the queue is recorded.
134 .\" XXX The rest of the sentence gets lots in relation to the first part.
135 The function called from
136 .Fn taskqueue_enqueue
137 must arrange for the queue to be processed
138 (for instance by scheduling a software interrupt or waking a kernel
140 The memory location where the thread identity is recorded is used
141 to signal the service thread(s) to terminate--when this value is set to
142 zero and the thread is signaled it will terminate.
143 If the queue is intended for use in fast interrupt handlers
144 .Fn taskqueue_create_fast
145 should be used in place of
146 .Fn taskqueue_create .
150 should be used to free the memory used by the queue.
151 Any tasks that are on the queue will be executed at this time after
152 which the thread servicing the queue will be signaled that it should exit.
154 Once a taskqueue has been created, its threads should be started using
155 .Fn taskqueue_start_threads
157 .Fn taskqueue_start_threads_pinned .
158 .Fn taskqueue_start_threads_pinned
161 argument which will cause the threads which are started for the taskqueue
162 to be pinned to run on the given CPU.
163 Callbacks may optionally be registered using
164 .Fn taskqueue_set_callback .
165 Currently, callbacks may be registered for the following purposes:
166 .Bl -tag -width TASKQUEUE_CALLBACK_TYPE_SHUTDOWN
167 .It Dv TASKQUEUE_CALLBACK_TYPE_INIT
168 This callback is called by every thread in the taskqueue, before it executes
170 This callback must be set before the taskqueue's threads are started.
171 .It Dv TASKQUEUE_CALLBACK_TYPE_SHUTDOWN
172 This callback is called by every thread in the taskqueue, after it executes
174 This callback will always be called before the taskqueue structure is
178 To add a task to the list of tasks queued on a taskqueue, call
179 .Fn taskqueue_enqueue
180 with pointers to the queue and task.
184 then it is simply incremented to reflect the number of times the task
185 was enqueued, up to a cap of USHRT_MAX.
187 the task is added to the list before the first task which has a lower
189 value or at the end of the list if no tasks have a lower priority.
190 Enqueueing a task does not perform any memory allocation which makes
191 it suitable for calling from an interrupt handler.
192 This function will return
194 if the queue is being freed.
196 When a task is executed,
197 first it is removed from the queue,
200 is recorded and then the field is zeroed.
203 from the task structure is called with the value of the field
205 as its first argument
208 as its second argument.
213 is called on the task pointer passed to
214 .Fn taskqueue_enqueue .
217 .Fn taskqueue_enqueue_timeout
218 function is used to schedule the enqueue after the specified number of
221 .Fn taskqueue_enqueue_timeout_sbt
222 function provides finer control over the scheduling based on
229 Only non-fast task queues can be used for
234 argument is negative, the already scheduled enqueueing is not re-scheduled.
235 Otherwise, the task is scheduled for enqueueing in the future,
236 after the absolute value of
239 This function returns -1 if the task is being drained.
240 Otherwise, the number of pending calls is returned.
244 function is used to cancel a task.
247 count is cleared, and the old value returned in the reference
252 If the task is currently running,
254 is returned, otherwise 0.
255 To implement a blocking
257 that waits for a running task to finish, it could look like:
258 .Bd -literal -offset indent
259 while (taskqueue_cancel(tq, task, NULL) != 0)
260 taskqueue_drain(tq, task);
264 .Fn taskqueue_drain ,
265 the caller is responsible for ensuring that the task is not re-enqueued
266 after being canceled.
269 .Fn taskqueue_cancel_timeout
270 function is used to cancel the scheduled task execution.
274 function is used to wait for the task to finish, and
276 .Fn taskqueue_drain_timeout
277 function is used to wait for the scheduled task to finish.
278 There is no guarantee that the task will not be
279 enqueued after call to
280 .Fn taskqueue_drain .
281 If the caller wants to put the task into a known state,
284 the caller should use out-of-band means to ensure that the task
285 would not be enqueued.
286 For example, if the task is enqueued by an interrupt filter, then
287 the interrupt could be disabled.
290 .Fn taskqueue_drain_all
291 function is used to wait for all pending and running tasks that
292 are enqueued on the taskqueue to finish.
293 Tasks posted to the taskqueue after
294 .Fn taskqueue_drain_all
296 including pending enqueues scheduled by a previous call to
297 .Fn taskqueue_enqueue_timeout ,
298 do not extend the wait time of
299 .Fn taskqueue_drain_all
300 and may complete after
301 .Fn taskqueue_drain_all
304 .Fn taskqueue_quiesce
305 function is used to wait for the queue to become empty and for all
306 running tasks to finish.
307 To avoid blocking indefinitely, the caller must ensure by some mechanism
308 that tasks will eventually stop being posted to the queue.
312 function blocks the taskqueue.
313 It prevents any enqueued but not running tasks from being executed.
315 .Fn taskqueue_enqueue
316 will enqueue tasks, but the tasks will not be run until
317 .Fn taskqueue_unblock
321 does not wait for any currently running tasks to finish.
324 does not provide a guarantee that
328 returns, but it does provide a guarantee that
330 will not be called again
332 .Fn taskqueue_unblock
334 If the caller requires a guarantee that
336 is not running, then this must be arranged by the caller.
339 is called on a task that is enqueued on a taskqueue that is blocked by
340 .Fn taskqueue_block ,
343 can not return until the taskqueue is unblocked.
344 This can result in a deadlock if the thread blocked in
346 is the thread that is supposed to call
347 .Fn taskqueue_unblock .
352 is discouraged, because the state of the task can not be known in advance.
353 The same caveat applies to
354 .Fn taskqueue_drain_all .
357 .Fn taskqueue_unblock
358 function unblocks the previously blocked taskqueue.
359 All enqueued tasks can be run after this call.
367 is part of the given taskqueue
375 function will run all pending tasks in the specified
377 Normally this function is only used internally.
380 .Fn TASK_INIT "task" "priority" "func" "context"
381 is provided to initialise a
386 macro generates an initializer for a task structure.
388 .Fn TIMEOUT_TASK_INIT "queue" "timeout_task" "priority" "func" "context"
397 are simply copied into the task structure fields and the
402 .Fn TASKQUEUE_DECLARE "name" ,
403 .Fn TASKQUEUE_DEFINE "name" "enqueue" "context" "init" ,
404 .Fn TASKQUEUE_FAST_DEFINE "name" "enqueue" "context" "init" ,
406 .Fn TASKQUEUE_DEFINE_THREAD "name"
407 .Fn TASKQUEUE_FAST_DEFINE_THREAD "name"
408 are used to declare a reference to a global queue, to define the
409 implementation of the queue, and declare a queue that uses its own thread.
412 macro arranges to call
414 with the values of its
419 arguments during system initialisation.
421 .Fn taskqueue_create ,
424 argument to the macro is executed as a C statement,
425 allowing any further initialisation to be performed
426 (such as registering an interrupt handler, etc.).
429 .Fn TASKQUEUE_DEFINE_THREAD
430 macro defines a new taskqueue with its own kernel thread to serve tasks.
432 .Vt struct taskqueue *taskqueue_name
433 is used to enqueue tasks onto the queue.
435 .Fn TASKQUEUE_FAST_DEFINE
437 .Fn TASKQUEUE_FAST_DEFINE_THREAD
441 .Fn TASKQUEUE_DEFINE_THREAD
442 respectively but taskqueue is created with
443 .Fn taskqueue_create_fast .
444 .Ss Predefined Task Queues
445 The system provides four global taskqueues,
448 .Va taskqueue_swi_giant ,
450 .Va taskqueue_thread .
453 queue is for swi handlers dispatched from fast interrupt handlers,
454 where sleep mutexes cannot be used.
455 The swi taskqueues are run via a software interrupt mechanism.
458 queue runs without the protection of the
461 .Va taskqueue_swi_giant
462 queue runs with the protection of the
467 runs in a kernel thread context, and tasks run from this thread do
471 If the caller wants to run under
473 he should explicitly acquire and release
475 in his taskqueue handler routine.
479 .Fn taskqueue_enqueue
480 with the value of the global taskqueue variable for the queue you wish to
483 The software interrupt queues can be used,
484 for instance, for implementing interrupt handlers which must perform a
485 significant amount of processing in the handler.
486 The hardware interrupt handler would perform minimal processing of the
487 interrupt and then enqueue a task to finish the work.
488 This reduces to a minimum
489 the amount of time spent with interrupts disabled.
491 The thread queue can be used, for instance, by interrupt level routines
492 that need to call kernel functions that do things that can only be done
493 from a thread context.
494 (e.g., call malloc with the M_WAITOK flag.)
496 Note that tasks queued on shared taskqueues such as
498 may be delayed an indeterminate amount of time before execution.
499 If queueing delays cannot be tolerated then a private taskqueue should
500 be created with a dedicated processing thread.
507 This interface first appeared in
509 There is a similar facility called work_queue in the Linux kernel.
511 This manual page was written by