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 .Ft struct taskqueue *
57 .Fn taskqueue_create "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context"
58 .Ft struct taskqueue *
59 .Fn taskqueue_create_fast "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context"
61 .Fn taskqueue_free "struct taskqueue *queue"
63 .Fn taskqueue_enqueue "struct taskqueue *queue" "struct task *task"
65 .Fn taskqueue_enqueue_fast "struct taskqueue *queue" "struct task *task"
67 .Fn taskqueue_run "struct taskqueue *queue"
69 .Fn taskqueue_run_fast "struct taskqueue *queue"
71 .Fn taskqueue_drain "struct taskqueue *queue" "struct task *task"
73 .Fn taskqueue_drain_all "struct taskqueue *queue"
75 .Fn taskqueue_block "struct taskqueue *queue"
77 .Fn taskqueue_unblock "struct taskqueue *queue"
79 .Fn taskqueue_member "struct taskqueue *queue" "struct thread *td"
80 .Fn TASK_INIT "struct task *task" "int priority" "task_fn_t *func" "void *context"
81 .Fn TASK_INITIALIZER "int priority" "task_fn_t func" "void *context"
82 .Fn TASKQUEUE_DECLARE "name"
83 .Fn TASKQUEUE_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init"
84 .Fn TASKQUEUE_FAST_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init"
85 .Fn TASKQUEUE_DEFINE_THREAD "name"
86 .Fn TASKQUEUE_FAST_DEFINE_THREAD "name"
88 These functions provide a simple interface for asynchronous execution
93 is used to create new queues.
96 include a name that should be unique,
99 flags that specify whether the call to
102 a function that is called from
103 .Fn taskqueue_enqueue
104 when a task is added to the queue,
105 and a pointer to the memory location where the identity of the
106 thread that services the queue is recorded.
107 .\" XXX The rest of the sentence gets lots in relation to the first part.
108 The function called from
109 .Fn taskqueue_enqueue
110 must arrange for the queue to be processed
111 (for instance by scheduling a software interrupt or waking a kernel
113 The memory location where the thread identity is recorded is used
114 to signal the service thread(s) to terminate--when this value is set to
115 zero and the thread is signaled it will terminate.
116 If the queue is intended for use in fast interrupt handlers
117 .Fn taskqueue_create_fast
118 should be used in place of
119 .Fn taskqueue_create .
123 should be used to free the memory used by the queue.
124 Any tasks that are on the queue will be executed at this time after
125 which the thread servicing the queue will be signaled that it should exit.
127 To add a task to the list of tasks queued on a taskqueue, call
128 .Fn taskqueue_enqueue
129 with pointers to the queue and task.
133 then it is simply incremented to reflect the number of times the task
134 was enqueued, up to a cap of USHRT_MAX.
136 the task is added to the list before the first task which has a lower
138 value or at the end of the list if no tasks have a lower priority.
139 Enqueueing a task does not perform any memory allocation which makes
140 it suitable for calling from an interrupt handler.
141 This function will return
143 if the queue is being freed.
146 .Fn taskqueue_enqueue_fast
147 should be used in place of
148 .Fn taskqueue_enqueue
149 when the enqueuing must happen from a fast interrupt handler.
150 This method uses spin locks to avoid the possibility of sleeping in the fast
153 To execute all the tasks on a queue,
157 .Fn taskqueue_run_fast
158 depending on the flavour of the queue.
159 When a task is executed,
160 first it is removed from the queue,
163 is recorded and then the field is zeroed.
166 from the task structure is called with the value of the field
168 as its first argument
171 as its second argument.
176 is called on the task pointer passed to
177 .Fn taskqueue_enqueue .
181 function is used to wait for the task to finish.
182 There is no guarantee that the task will not be
183 enqueued after call to
184 .Fn taskqueue_drain .
185 If the caller wants to put the task into a known state,
188 the caller should use out-of-band means to ensure that the task
189 would not be enqueued.
190 For example, if the task is enqueued by an interrupt filter, then
191 the interrupt could be disabled.
194 .Fn taskqueue_drain_all
195 function is used to wait for all pending and running tasks that
196 are enqueued on the taskqueue to finish.
197 The caller must arrange that the tasks are not re-enqueued.
199 .Fn taskqueue_drain_all
200 currently does not handle tasks with delayed enqueueing.
204 function blocks the taskqueue.
205 It prevents any enqueued but not running tasks from being executed.
207 .Fn taskqueue_enqueue
208 will enqueue tasks, but the tasks will not be run until
209 .Fn taskqueue_unblock
213 does not wait for any currently running tasks to finish.
216 does not provide a guarantee that
220 returns, but it does provide a guarantee that
222 will not be called again
224 .Fn taskqueue_unblock
226 If the caller requires a guarantee that
228 is not running, then this must be arranged by the caller.
231 is called on a task that is enqueued on a taskqueue that is blocked by
232 .Fn taskqueue_block ,
235 can not return until the taskqueue is unblocked.
236 This can result in a deadlock if the thread blocked in
238 is the thread that is supposed to call
239 .Fn taskqueue_unblock .
244 is discouraged, because the state of the task can not be known in advance.
245 The same caveat applies to
246 .Fn taskqueue_drain_all .
249 .Fn taskqueue_unblock
250 function unblocks the previously blocked taskqueue.
251 All enqueued tasks can be run after this call.
259 is part of the given taskqeueue
266 .Fn TASK_INIT "task" "priority" "func" "context"
267 is provided to initialise a
272 macro generates an initializer for a task structure.
278 are simply copied into the task structure fields and the
283 .Fn TASKQUEUE_DECLARE "name" ,
284 .Fn TASKQUEUE_DEFINE "name" "enqueue" "context" "init" ,
285 .Fn TASKQUEUE_FAST_DEFINE "name" "enqueue" "context" "init" ,
287 .Fn TASKQUEUE_DEFINE_THREAD "name"
288 .Fn TASKQUEUE_FAST_DEFINE_THREAD "name"
289 are used to declare a reference to a global queue, to define the
290 implementation of the queue, and declare a queue that uses its own thread.
293 macro arranges to call
295 with the values of its
300 arguments during system initialisation.
302 .Fn taskqueue_create ,
305 argument to the macro is executed as a C statement,
306 allowing any further initialisation to be performed
307 (such as registering an interrupt handler etc.)
310 .Fn TASKQUEUE_DEFINE_THREAD
311 macro defines a new taskqueue with its own kernel thread to serve tasks.
313 .Vt struct taskqueue *taskqueue_name
314 is used to enqueue tasks onto the queue.
316 .Fn TASKQUEUE_FAST_DEFINE
318 .Fn TASKQUEUE_FAST_DEFINE_THREAD
322 .Fn TASKQUEUE_DEFINE_THREAD
323 respectively but taskqueue is created with
324 .Fn taskqueue_create_fast .
325 .Ss Predefined Task Queues
326 The system provides four global taskqueues,
329 .Va taskqueue_swi_giant ,
331 .Va taskqueue_thread .
334 queue is for swi handlers dispatched from fast interrupt handlers,
335 where sleep mutexes cannot be used.
336 The swi taskqueues are run via a software interrupt mechanism.
339 queue runs without the protection of the
342 .Va taskqueue_swi_giant
343 queue runs with the protection of the
348 runs in a kernel thread context, and tasks run from this thread do
352 If the caller wants to run under
354 he should explicitly acquire and release
356 in his taskqueue handler routine.
360 .Fn taskqueue_enqueue
361 with the value of the global taskqueue variable for the queue you wish to
363 .Va ( taskqueue_swi ,
364 .Va taskqueue_swi_giant ,
366 .Va taskqueue_thread ) .
368 .Fn taskqueue_enqueue_fast
369 for the global taskqueue variable
372 The software interrupt queues can be used,
373 for instance, for implementing interrupt handlers which must perform a
374 significant amount of processing in the handler.
375 The hardware interrupt handler would perform minimal processing of the
376 interrupt and then enqueue a task to finish the work.
377 This reduces to a minimum
378 the amount of time spent with interrupts disabled.
380 The thread queue can be used, for instance, by interrupt level routines
381 that need to call kernel functions that do things that can only be done
382 from a thread context.
383 (e.g., call malloc with the M_WAITOK flag.)
385 Note that tasks queued on shared taskqueues such as
387 may be delayed an indeterminate amount of time before execution.
388 If queueing delays cannot be tolerated then a private taskqueue should
389 be created with a dedicated processing thread.
395 This interface first appeared in
397 There is a similar facility called tqueue in the Linux kernel.
399 This manual page was written by