summaryrefslogtreecommitdiff
path: root/static/freebsd/man9/taskqueue.9 4.html
blob: d9c314eee1987619d5d8505110ab5f7754562158 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
<table class="head">
  <tr>
    <td class="head-ltitle">TASKQUEUE(9)</td>
    <td class="head-vol">Kernel Developer's Manual</td>
    <td class="head-rtitle">TASKQUEUE(9)</td>
  </tr>
</table>
<div class="manual-text">
<section class="Sh">
<h1 class="Sh" id="NAME"><a class="permalink" href="#NAME">NAME</a></h1>
<p class="Pp"><code class="Nm">taskqueue</code> &#x2014;
    <span class="Nd">asynchronous task execution</span></p>
</section>
<section class="Sh">
<h1 class="Sh" id="SYNOPSIS"><a class="permalink" href="#SYNOPSIS">SYNOPSIS</a></h1>
<p class="Pp"><code class="In">#include
    &lt;<a class="In">sys/param.h</a>&gt;</code>
  <br/>
  <code class="In">#include &lt;<a class="In">sys/kernel.h</a>&gt;</code>
  <br/>
  <code class="In">#include &lt;<a class="In">sys/malloc.h</a>&gt;</code>
  <br/>
  <code class="In">#include &lt;<a class="In">sys/queue.h</a>&gt;</code>
  <br/>
  <code class="In">#include &lt;<a class="In">sys/taskqueue.h</a>&gt;</code></p>
<div class="Bd Pp Li">
<pre>typedef void (*task_fn_t)(void *context, int pending);

typedef void (*taskqueue_enqueue_fn)(void *context);

struct task {
	STAILQ_ENTRY(task)	ta_link;	/* link for queue */
	u_short			ta_pending;	/* count times queued */
	u_short			ta_priority;	/* priority of task in queue */
	task_fn_t		ta_func;	/* task handler */
	void			*ta_context;	/* argument for handler */
};

enum taskqueue_callback_type {
	TASKQUEUE_CALLBACK_TYPE_INIT,
	TASKQUEUE_CALLBACK_TYPE_SHUTDOWN,
};

typedef void (*taskqueue_callback_fn)(void *context);

struct timeout_task;</pre>
</div>
<br/>
<var class="Ft">struct taskqueue *</var>
<br/>
<code class="Fn">taskqueue_create</code>(<var class="Fa" style="white-space: nowrap;">const
  char *name</var>, <var class="Fa" style="white-space: nowrap;">int
  mflags</var>,
  <var class="Fa" style="white-space: nowrap;">taskqueue_enqueue_fn
  enqueue</var>, <var class="Fa" style="white-space: nowrap;">void
  *context</var>);
<p class="Pp"><var class="Ft">struct taskqueue *</var>
  <br/>
  <code class="Fn">taskqueue_create_fast</code>(<var class="Fa" style="white-space: nowrap;">const
    char *name</var>, <var class="Fa" style="white-space: nowrap;">int
    mflags</var>,
    <var class="Fa" style="white-space: nowrap;">taskqueue_enqueue_fn
    enqueue</var>, <var class="Fa" style="white-space: nowrap;">void
    *context</var>);</p>
<p class="Pp"><var class="Ft">int</var>
  <br/>
  <code class="Fn">taskqueue_start_threads</code>(<var class="Fa" style="white-space: nowrap;">struct
    taskqueue **tqp</var>, <var class="Fa" style="white-space: nowrap;">int
    count</var>, <var class="Fa" style="white-space: nowrap;">int pri</var>,
    <var class="Fa" style="white-space: nowrap;">const char *name</var>,
    <var class="Fa" style="white-space: nowrap;">...</var>);</p>
<p class="Pp"><var class="Ft">int</var>
  <br/>
  <code class="Fn">taskqueue_start_threads_cpuset</code>(<var class="Fa">struct
    taskqueue **tqp</var>, <var class="Fa">int count</var>, <var class="Fa">int
    pri</var>, <var class="Fa">cpuset_t *mask</var>, <var class="Fa">const char
    *name</var>, <var class="Fa">...</var>);</p>
<p class="Pp"><var class="Ft">int</var>
  <br/>
  <code class="Fn">taskqueue_start_threads_in_proc</code>(<var class="Fa">struct
    taskqueue **tqp</var>, <var class="Fa">int count</var>, <var class="Fa">int
    pri</var>, <var class="Fa">struct proc *proc</var>, <var class="Fa">const
    char *name</var>, <var class="Fa">...</var>);</p>
<p class="Pp"><var class="Ft">void</var>
  <br/>
  <code class="Fn">taskqueue_set_callback</code>(<var class="Fa" style="white-space: nowrap;">struct
    taskqueue *queue</var>, <var class="Fa" style="white-space: nowrap;">enum
    taskqueue_callback_type cb_type</var>,
    <var class="Fa" style="white-space: nowrap;">taskqueue_callback_fn
    callback</var>, <var class="Fa" style="white-space: nowrap;">void
    *context</var>);</p>
<p class="Pp"><var class="Ft">void</var>
  <br/>
  <code class="Fn">taskqueue_free</code>(<var class="Fa" style="white-space: nowrap;">struct
    taskqueue *queue</var>);</p>
<p class="Pp"><var class="Ft">int</var>
  <br/>
  <code class="Fn">taskqueue_enqueue</code>(<var class="Fa" style="white-space: nowrap;">struct
    taskqueue *queue</var>, <var class="Fa" style="white-space: nowrap;">struct
    task *task</var>);</p>
<p class="Pp"><var class="Ft">int</var>
  <br/>
  <code class="Fn">taskqueue_enqueue_flags</code>(<var class="Fa" style="white-space: nowrap;">struct
    taskqueue *queue</var>, <var class="Fa" style="white-space: nowrap;">struct
    task *task</var>, <var class="Fa" style="white-space: nowrap;">int
    flags</var>);</p>
<p class="Pp"><var class="Ft">int</var>
  <br/>
  <code class="Fn">taskqueue_enqueue_timeout</code>(<var class="Fa" style="white-space: nowrap;">struct
    taskqueue *queue</var>, <var class="Fa" style="white-space: nowrap;">struct
    timeout_task *timeout_task</var>,
    <var class="Fa" style="white-space: nowrap;">int ticks</var>);</p>
<p class="Pp"><var class="Ft">int</var>
  <br/>
  <code class="Fn">taskqueue_enqueue_timeout_sbt</code>(<var class="Fa" style="white-space: nowrap;">struct
    taskqueue *queue</var>, <var class="Fa" style="white-space: nowrap;">struct
    timeout_task *timeout_task</var>,
    <var class="Fa" style="white-space: nowrap;">sbintime_t sbt</var>,
    <var class="Fa" style="white-space: nowrap;">sbintime_t pr</var>,
    <var class="Fa" style="white-space: nowrap;">int flags</var>);</p>
<p class="Pp"><var class="Ft">int</var>
  <br/>
  <code class="Fn">taskqueue_cancel</code>(<var class="Fa" style="white-space: nowrap;">struct
    taskqueue *queue</var>, <var class="Fa" style="white-space: nowrap;">struct
    task *task</var>, <var class="Fa" style="white-space: nowrap;">u_int
    *pendp</var>);</p>
<p class="Pp"><var class="Ft">int</var>
  <br/>
  <code class="Fn">taskqueue_cancel_timeout</code>(<var class="Fa" style="white-space: nowrap;">struct
    taskqueue *queue</var>, <var class="Fa" style="white-space: nowrap;">struct
    timeout_task *timeout_task</var>,
    <var class="Fa" style="white-space: nowrap;">u_int *pendp</var>);</p>
<p class="Pp"><var class="Ft">void</var>
  <br/>
  <code class="Fn">taskqueue_drain</code>(<var class="Fa" style="white-space: nowrap;">struct
    taskqueue *queue</var>, <var class="Fa" style="white-space: nowrap;">struct
    task *task</var>);</p>
<p class="Pp"><var class="Ft">void</var>
  <br/>
  <code class="Fn">taskqueue_drain_timeout</code>(<var class="Fa" style="white-space: nowrap;">struct
    taskqueue *queue</var>, <var class="Fa" style="white-space: nowrap;">struct
    timeout_task *timeout_task</var>);</p>
<p class="Pp"><var class="Ft">void</var>
  <br/>
  <code class="Fn">taskqueue_drain_all</code>(<var class="Fa" style="white-space: nowrap;">struct
    taskqueue *queue</var>);</p>
<p class="Pp"><var class="Ft">void</var>
  <br/>
  <code class="Fn">taskqueue_quiesce</code>(<var class="Fa" style="white-space: nowrap;">struct
    taskqueue *queue</var>);</p>
<p class="Pp"><var class="Ft">void</var>
  <br/>
  <code class="Fn">taskqueue_block</code>(<var class="Fa" style="white-space: nowrap;">struct
    taskqueue *queue</var>);</p>
<p class="Pp"><var class="Ft">void</var>
  <br/>
  <code class="Fn">taskqueue_unblock</code>(<var class="Fa" style="white-space: nowrap;">struct
    taskqueue *queue</var>);</p>
<p class="Pp"><var class="Ft">int</var>
  <br/>
  <code class="Fn">taskqueue_member</code>(<var class="Fa" style="white-space: nowrap;">struct
    taskqueue *queue</var>, <var class="Fa" style="white-space: nowrap;">struct
    thread *td</var>);</p>
<p class="Pp"><var class="Ft">void</var>
  <br/>
  <code class="Fn">taskqueue_run</code>(<var class="Fa" style="white-space: nowrap;">struct
    taskqueue *queue</var>);</p>
<p class="Pp"><code class="Fn">TASK_INIT</code>(<var class="Fa" style="white-space: nowrap;">struct
    task *task</var>, <var class="Fa" style="white-space: nowrap;">int
    priority</var>, <var class="Fa" style="white-space: nowrap;">task_fn_t
    func</var>, <var class="Fa" style="white-space: nowrap;">void
    *context</var>);</p>
<p class="Pp"><code class="Fn">TASK_INITIALIZER</code>(<var class="Fa" style="white-space: nowrap;">int
    priority</var>, <var class="Fa" style="white-space: nowrap;">task_fn_t
    func</var>, <var class="Fa" style="white-space: nowrap;">void
    *context</var>);</p>
<p class="Pp"><code class="Fn">TASKQUEUE_DECLARE</code>(<var class="Fa" style="white-space: nowrap;">name</var>);</p>
<p class="Pp"><code class="Fn">TASKQUEUE_DEFINE</code>(<var class="Fa" style="white-space: nowrap;">name</var>,
    <var class="Fa" style="white-space: nowrap;">taskqueue_enqueue_fn
    enqueue</var>, <var class="Fa" style="white-space: nowrap;">void
    *context</var>,
  <var class="Fa" style="white-space: nowrap;">init</var>);</p>
<p class="Pp"><code class="Fn">TASKQUEUE_FAST_DEFINE</code>(<var class="Fa" style="white-space: nowrap;">name</var>,
    <var class="Fa" style="white-space: nowrap;">taskqueue_enqueue_fn
    enqueue</var>, <var class="Fa" style="white-space: nowrap;">void
    *context</var>,
  <var class="Fa" style="white-space: nowrap;">init</var>);</p>
<p class="Pp"><code class="Fn">TASKQUEUE_DEFINE_THREAD</code>(<var class="Fa" style="white-space: nowrap;">name</var>);</p>
<p class="Pp"><code class="Fn">TASKQUEUE_FAST_DEFINE_THREAD</code>(<var class="Fa" style="white-space: nowrap;">name</var>);</p>
<p class="Pp"><code class="Fn">TIMEOUT_TASK_INIT</code>(<var class="Fa" style="white-space: nowrap;">struct
    taskqueue *queue</var>, <var class="Fa" style="white-space: nowrap;">struct
    timeout_task *timeout_task</var>,
    <var class="Fa" style="white-space: nowrap;">int priority</var>,
    <var class="Fa" style="white-space: nowrap;">task_fn_t func</var>,
    <var class="Fa" style="white-space: nowrap;">void *context</var>);</p>
</section>
<section class="Sh">
<h1 class="Sh" id="DESCRIPTION"><a class="permalink" href="#DESCRIPTION">DESCRIPTION</a></h1>
<p class="Pp">These functions provide a simple interface for asynchronous
    execution of code.</p>
<p class="Pp" id="taskqueue_create">The function
    <a class="permalink" href="#taskqueue_create"><code class="Fn">taskqueue_create</code></a>()
    is used to create new queues. The arguments to
    <code class="Fn">taskqueue_create</code>() include a name that should be
    unique, a set of <a class="Xr">malloc(9)</a> flags that specify whether the
    call to
    <a class="permalink" href="#malloc"><code class="Fn" id="malloc">malloc</code></a>()
    is allowed to sleep, a function that is called from
    <code class="Fn">taskqueue_enqueue</code>() when a task is added to the
    queue, and a pointer to the memory location where the identity of the thread
    that services the queue is recorded. The function called from
    <code class="Fn">taskqueue_enqueue</code>() must arrange for the queue to be
    processed (for instance by scheduling a software interrupt or waking a
    kernel thread). The memory location where the thread identity is recorded is
    used to signal the service thread(s) to terminate--when this value is set to
    zero and the thread is signaled it will terminate. If the queue is intended
    for use in fast interrupt handlers
    <code class="Fn">taskqueue_create_fast</code>() should be used in place of
    <code class="Fn">taskqueue_create</code>().</p>
<p class="Pp" id="taskqueue_free">The function
    <a class="permalink" href="#taskqueue_free"><code class="Fn">taskqueue_free</code></a>()
    should be used to free the memory used by the queue. Any tasks that are on
    the queue will be executed at this time after which the thread servicing the
    queue will be signaled that it should exit.</p>
<p class="Pp" id="taskqueue_start_threads">Once a taskqueue has been created,
    its threads should be started using
    <a class="permalink" href="#taskqueue_start_threads"><code class="Fn">taskqueue_start_threads</code></a>(),
    <a class="permalink" href="#taskqueue_start_threads_cpuset"><code class="Fn" id="taskqueue_start_threads_cpuset">taskqueue_start_threads_cpuset</code></a>()
    or
    <a class="permalink" href="#taskqueue_start_threads_in_proc"><code class="Fn" id="taskqueue_start_threads_in_proc">taskqueue_start_threads_in_proc</code></a>().
    <code class="Fn">taskqueue_start_threads_cpuset</code>() takes a
    <var class="Va">cpuset</var> argument which will cause the threads which are
    started for the taskqueue to be restricted to run on the given CPUs.
    <code class="Fn">taskqueue_start_threads_in_proc</code>() takes a
    <var class="Va">proc</var> argument which will cause the threads which are
    started for the taskqueue to be assigned to the given kernel process.
    Callbacks may optionally be registered using
    <a class="permalink" href="#taskqueue_set_callback"><code class="Fn" id="taskqueue_set_callback">taskqueue_set_callback</code></a>().
    Currently, callbacks may be registered for the following purposes:</p>
<dl class="Bl-tag">
  <dt id="TASKQUEUE_CALLBACK_TYPE_INIT"><a class="permalink" href="#TASKQUEUE_CALLBACK_TYPE_INIT"><code class="Dv">TASKQUEUE_CALLBACK_TYPE_INIT</code></a></dt>
  <dd>This callback is called by every thread in the taskqueue, before it
      executes any tasks. This callback must be set before the taskqueue's
      threads are started.</dd>
  <dt id="TASKQUEUE_CALLBACK_TYPE_SHUTDOWN"><a class="permalink" href="#TASKQUEUE_CALLBACK_TYPE_SHUTDOWN"><code class="Dv">TASKQUEUE_CALLBACK_TYPE_SHUTDOWN</code></a></dt>
  <dd>This callback is called by every thread in the taskqueue, after it
      executes its last task. This callback will always be called before the
      taskqueue structure is reclaimed.</dd>
</dl>
<p class="Pp" id="taskqueue_enqueue">To add a task to the list of tasks queued
    on a taskqueue, call
    <a class="permalink" href="#taskqueue_enqueue"><code class="Fn">taskqueue_enqueue</code></a>()
    with pointers to the queue and task. If the task's
    <var class="Va">ta_pending</var> field is non-zero, then it is simply
    incremented to reflect the number of times the task was enqueued, up to a
    cap of USHRT_MAX. Otherwise, the task is added to the list before the first
    task which has a lower <var class="Va">ta_priority</var> value or at the end
    of the list if no tasks have a lower priority. Enqueueing a task does not
    perform any memory allocation which makes it suitable for calling from an
    interrupt handler. This function will return <code class="Er">EPIPE</code>
    if the queue is being freed.</p>
<p class="Pp" id="taskqueue_enqueue~2">When a task is executed, first it is
    removed from the queue, the value of <var class="Va">ta_pending</var> is
    recorded and then the field is zeroed. The function
    <var class="Va">ta_func</var> from the task structure is called with the
    value of the field <var class="Va">ta_context</var> as its first argument
    and the value of <var class="Va">ta_pending</var> as its second argument.
    After the function <var class="Va">ta_func</var> returns,
    <a class="Xr">wakeup(9)</a> is called on the task pointer passed to
    <a class="permalink" href="#taskqueue_enqueue~2"><code class="Fn">taskqueue_enqueue</code></a>().</p>
<p class="Pp" id="taskqueue_enqueue_flags">The
    <a class="permalink" href="#taskqueue_enqueue_flags"><code class="Fn">taskqueue_enqueue_flags</code></a>()
    accepts an extra <var class="Va">flags</var> parameter which specifies a set
    of optional flags to alter the behavior of
    <code class="Fn">taskqueue_enqueue</code>(). It contains one or more of the
    following flags:</p>
<dl class="Bl-tag">
  <dt id="TASKQUEUE_FAIL_IF_PENDING"><a class="permalink" href="#TASKQUEUE_FAIL_IF_PENDING"><code class="Dv">TASKQUEUE_FAIL_IF_PENDING</code></a></dt>
  <dd><code class="Fn">taskqueue_enqueue_flags</code>() fails if the task is
      already scheduled for execution. <code class="Er">EEXIST</code> is
      returned and the <var class="Va">ta_pending</var> counter value remains
      unchanged.</dd>
  <dt id="TASKQUEUE_FAIL_IF_CANCELING"><a class="permalink" href="#TASKQUEUE_FAIL_IF_CANCELING"><code class="Dv">TASKQUEUE_FAIL_IF_CANCELING</code></a></dt>
  <dd><code class="Fn">taskqueue_enqueue_flags</code>() fails if the task is in
      the canceling state and <code class="Er">ECANCELED</code> is
    returned.</dd>
</dl>
<p class="Pp" id="taskqueue_enqueue_timeout">The
    <a class="permalink" href="#taskqueue_enqueue_timeout"><code class="Fn">taskqueue_enqueue_timeout</code></a>()
    function is used to schedule the enqueue after the specified number of
    <var class="Va">ticks</var>. The
    <a class="permalink" href="#taskqueue_enqueue_timeout_sbt"><code class="Fn" id="taskqueue_enqueue_timeout_sbt">taskqueue_enqueue_timeout_sbt</code></a>()
    function provides finer control over the scheduling based on
    <var class="Va">sbt</var>, <var class="Va">pr</var>, and
    <var class="Va">flags</var>, as detailed in <a class="Xr">callout(9)</a>. If
    the <var class="Va">ticks</var> argument is negative, the already scheduled
    enqueueing is not re-scheduled. Otherwise, the task is scheduled for
    enqueueing in the future, after the absolute value of
    <var class="Va">ticks</var> is passed. This function returns -1 if the task
    is being drained. Otherwise, the number of pending calls is returned.</p>
<p class="Pp" id="taskqueue_cancel">The
    <a class="permalink" href="#taskqueue_cancel"><code class="Fn">taskqueue_cancel</code></a>()
    function is used to cancel a task. The <var class="Va">ta_pending</var>
    count is cleared, and the old value returned in the reference parameter
    <var class="Fa">pendp</var>, if it is non-<code class="Dv">NULL</code>. If
    the task is currently running, <code class="Dv">EBUSY</code> is returned,
    otherwise 0. To implement a blocking
    <code class="Fn">taskqueue_cancel</code>() that waits for a running task to
    finish, it could look like:</p>
<div class="Bd Pp Bd-indent Li">
<pre>while (taskqueue_cancel(tq, task, NULL) != 0)
	taskqueue_drain(tq, task);</pre>
</div>
<p class="Pp" id="taskqueue_drain">Note that, as with
    <a class="permalink" href="#taskqueue_drain"><code class="Fn">taskqueue_drain</code></a>(),
    the caller is responsible for ensuring that the task is not re-enqueued
    after being canceled.</p>
<p class="Pp" id="taskqueue_cancel_timeout">Similarly, the
    <a class="permalink" href="#taskqueue_cancel_timeout"><code class="Fn">taskqueue_cancel_timeout</code></a>()
    function is used to cancel the scheduled task execution.</p>
<p class="Pp" id="taskqueue_drain~2">The
    <a class="permalink" href="#taskqueue_drain~2"><code class="Fn">taskqueue_drain</code></a>()
    function is used to wait for the task to finish, and the
    <a class="permalink" href="#taskqueue_drain_timeout"><code class="Fn" id="taskqueue_drain_timeout">taskqueue_drain_timeout</code></a>()
    function is used to wait for the scheduled task to finish. There is no
    guarantee that the task will not be enqueued after call to
    <code class="Fn">taskqueue_drain</code>(). If the caller wants to put the
    task into a known state, then before calling
    <code class="Fn">taskqueue_drain</code>() the caller should use out-of-band
    means to ensure that the task would not be enqueued. For example, if the
    task is enqueued by an interrupt filter, then the interrupt could be
    disabled.</p>
<p class="Pp" id="taskqueue_drain_all">The
    <a class="permalink" href="#taskqueue_drain_all"><code class="Fn">taskqueue_drain_all</code></a>()
    function is used to wait for all pending and running tasks that are enqueued
    on the taskqueue to finish. Tasks posted to the taskqueue after
    <code class="Fn">taskqueue_drain_all</code>() begins processing, including
    pending enqueues scheduled by a previous call to
    <code class="Fn">taskqueue_enqueue_timeout</code>(), do not extend the wait
    time of <code class="Fn">taskqueue_drain_all</code>() and may complete after
    <code class="Fn">taskqueue_drain_all</code>() returns. The
    <a class="permalink" href="#taskqueue_quiesce"><code class="Fn" id="taskqueue_quiesce">taskqueue_quiesce</code></a>()
    function is used to wait for the queue to become empty and for all running
    tasks to finish. To avoid blocking indefinitely, the caller must ensure by
    some mechanism that tasks will eventually stop being posted to the
  queue.</p>
<p class="Pp" id="taskqueue_block">The
    <a class="permalink" href="#taskqueue_block"><code class="Fn">taskqueue_block</code></a>()
    function blocks the taskqueue. It prevents any enqueued but not running
    tasks from being executed. Future calls to
    <code class="Fn">taskqueue_enqueue</code>() will enqueue tasks, but the
    tasks will not be run until <code class="Fn">taskqueue_unblock</code>() is
    called. Please note that <code class="Fn">taskqueue_block</code>() does not
    wait for any currently running tasks to finish. Thus, the
    <code class="Fn">taskqueue_block</code>() does not provide a guarantee that
    <code class="Fn">taskqueue_run</code>() is not running after
    <code class="Fn">taskqueue_block</code>() returns, but it does provide a
    guarantee that <code class="Fn">taskqueue_run</code>() will not be called
    again until <code class="Fn">taskqueue_unblock</code>() is called. If the
    caller requires a guarantee that <code class="Fn">taskqueue_run</code>() is
    not running, then this must be arranged by the caller. Note that if
    <code class="Fn">taskqueue_drain</code>() is called on a task that is
    enqueued on a taskqueue that is blocked by
    <code class="Fn">taskqueue_block</code>(), then
    <code class="Fn">taskqueue_drain</code>() can not return until the taskqueue
    is unblocked. This can result in a deadlock if the thread blocked in
    <code class="Fn">taskqueue_drain</code>() is the thread that is supposed to
    call <code class="Fn">taskqueue_unblock</code>(). Thus, use of
    <code class="Fn">taskqueue_drain</code>() after
    <code class="Fn">taskqueue_block</code>() is discouraged, because the state
    of the task can not be known in advance. The same caveat applies to
    <code class="Fn">taskqueue_drain_all</code>().</p>
<p class="Pp" id="taskqueue_unblock">The
    <a class="permalink" href="#taskqueue_unblock"><code class="Fn">taskqueue_unblock</code></a>()
    function unblocks the previously blocked taskqueue. All enqueued tasks can
    be run after this call.</p>
<p class="Pp" id="taskqueue_member">The
    <a class="permalink" href="#taskqueue_member"><code class="Fn">taskqueue_member</code></a>()
    function returns <span class="No">1</span> if the given thread
    <var class="Fa">td</var> is part of the given taskqueue
    <var class="Fa">queue</var> and <span class="No">0</span> otherwise.</p>
<p class="Pp" id="taskqueue_run">The
    <a class="permalink" href="#taskqueue_run"><code class="Fn">taskqueue_run</code></a>()
    function will run all pending tasks in the specified
    <var class="Fa">queue</var>. Normally this function is only used
  internally.</p>
<p class="Pp" id="TASK_INIT">A convenience macro,
    <a class="permalink" href="#TASK_INIT"><code class="Fn">TASK_INIT</code></a>(<var class="Fa">task</var>,
    <var class="Fa">priority</var>, <var class="Fa">func</var>,
    <var class="Fa">context</var>) is provided to initialise a
    <var class="Va">task</var> structure. The
    <a class="permalink" href="#TASK_INITIALIZER"><code class="Fn" id="TASK_INITIALIZER">TASK_INITIALIZER</code></a>()
    macro generates an initializer for a task structure. A macro
    <a class="permalink" href="#TIMEOUT_TASK_INIT"><code class="Fn" id="TIMEOUT_TASK_INIT">TIMEOUT_TASK_INIT</code></a>(<var class="Fa">queue</var>,
    <var class="Fa">timeout_task</var>, <var class="Fa">priority</var>,
    <var class="Fa">func</var>, <var class="Fa">context</var>) initializes the
    <var class="Va">timeout_task</var> structure. The values of
    <var class="Va">priority</var>, <var class="Va">func</var>, and
    <var class="Va">context</var> are simply copied into the task structure
    fields and the <var class="Va">ta_pending</var> field is cleared.</p>
<p class="Pp" id="TASKQUEUE_DECLARE">Five macros
    <a class="permalink" href="#TASKQUEUE_DECLARE"><code class="Fn">TASKQUEUE_DECLARE</code></a>(<var class="Fa">name</var>),
    <a class="permalink" href="#TASKQUEUE_DEFINE"><code class="Fn" id="TASKQUEUE_DEFINE">TASKQUEUE_DEFINE</code></a>(<var class="Fa">name</var>,
    <var class="Fa">enqueue</var>, <var class="Fa">context</var>,
    <var class="Fa">init</var>),
    <code class="Fn">TASKQUEUE_FAST_DEFINE</code>(<var class="Fa">name</var>,
    <var class="Fa">enqueue</var>, <var class="Fa">context</var>,
    <var class="Fa">init</var>), and
    <code class="Fn">TASKQUEUE_DEFINE_THREAD</code>(<var class="Fa">name</var>)
    <code class="Fn">TASKQUEUE_FAST_DEFINE_THREAD</code>(<var class="Fa">name</var>)
    are used to declare a reference to a global queue, to define the
    implementation of the queue, and declare a queue that uses its own thread.
    The <code class="Fn">TASKQUEUE_DEFINE</code>() macro arranges to call
    <code class="Fn">taskqueue_create</code>() with the values of its
    <var class="Va">name</var>, <var class="Va">enqueue</var> and
    <var class="Va">context</var> arguments during system initialisation. After
    calling <code class="Fn">taskqueue_create</code>(), the
    <var class="Va">init</var> argument to the macro is executed as a C
    statement, allowing any further initialisation to be performed (such as
    registering an interrupt handler, etc.).</p>
<p class="Pp" id="TASKQUEUE_DEFINE_THREAD">The
    <a class="permalink" href="#TASKQUEUE_DEFINE_THREAD"><code class="Fn">TASKQUEUE_DEFINE_THREAD</code></a>()
    macro defines a new taskqueue with its own kernel thread to serve tasks. The
    variable <var class="Vt">struct taskqueue *taskqueue_name</var> is used to
    enqueue tasks onto the queue.</p>
<p class="Pp" id="TASKQUEUE_FAST_DEFINE"><a class="permalink" href="#TASKQUEUE_FAST_DEFINE"><code class="Fn">TASKQUEUE_FAST_DEFINE</code></a>()
    and
    <a class="permalink" href="#TASKQUEUE_FAST_DEFINE_THREAD"><code class="Fn" id="TASKQUEUE_FAST_DEFINE_THREAD">TASKQUEUE_FAST_DEFINE_THREAD</code></a>()
    act just like <code class="Fn">TASKQUEUE_DEFINE</code>() and
    <code class="Fn">TASKQUEUE_DEFINE_THREAD</code>() respectively but taskqueue
    is created with
    <a class="permalink" href="#taskqueue_create_fast"><code class="Fn" id="taskqueue_create_fast">taskqueue_create_fast</code></a>().</p>
<section class="Ss">
<h2 class="Ss" id="Predefined_Task_Queues"><a class="permalink" href="#Predefined_Task_Queues">Predefined
  Task Queues</a></h2>
<p class="Pp">The system provides four global taskqueues,
    <var class="Va">taskqueue_fast</var>, <var class="Va">taskqueue_swi</var>,
    <var class="Va">taskqueue_swi_giant</var>, and
    <var class="Va">taskqueue_thread</var>. The
    <var class="Va">taskqueue_fast</var> queue is for swi handlers dispatched
    from fast interrupt handlers, where sleep mutexes cannot be used. The swi
    taskqueues are run via a software interrupt mechanism. The
    <var class="Va">taskqueue_swi</var> queue runs without the protection of the
    <var class="Va">Giant</var> kernel lock, and the
    <var class="Va">taskqueue_swi_giant</var> queue runs with the protection of
    the <var class="Va">Giant</var> kernel lock. The thread taskqueue
    <var class="Va">taskqueue_thread</var> runs in a kernel thread context, and
    tasks run from this thread do not run under the <var class="Va">Giant</var>
    kernel lock. If the caller wants to run under <var class="Va">Giant</var>,
    he should explicitly acquire and release <var class="Va">Giant</var> in his
    taskqueue handler routine.</p>
<p class="Pp" id="taskqueue_enqueue~3">To use these queues, call
    <a class="permalink" href="#taskqueue_enqueue~3"><code class="Fn">taskqueue_enqueue</code></a>()
    with the value of the global taskqueue variable for the queue you wish to
    use.</p>
<p class="Pp">The software interrupt queues can be used, for instance, for
    implementing interrupt handlers which must perform a significant amount of
    processing in the handler. The hardware interrupt handler would perform
    minimal processing of the interrupt and then enqueue a task to finish the
    work. This reduces to a minimum the amount of time spent with interrupts
    disabled.</p>
<p class="Pp">The thread queue can be used, for instance, by interrupt level
    routines that need to call kernel functions that do things that can only be
    done from a thread context. (e.g., call malloc with the M_WAITOK flag.)</p>
<p class="Pp">Note that tasks queued on shared taskqueues such as
    <var class="Va">taskqueue_swi</var> may be delayed an indeterminate amount
    of time before execution. If queueing delays cannot be tolerated then a
    private taskqueue should be created with a dedicated processing thread.</p>
</section>
</section>
<section class="Sh">
<h1 class="Sh" id="SEE_ALSO"><a class="permalink" href="#SEE_ALSO">SEE
  ALSO</a></h1>
<p class="Pp"><a class="Xr">callout(9)</a>, <a class="Xr">intr_event(9)</a>,
    <a class="Xr">kthread(9)</a>, <a class="Xr">swi(9)</a></p>
</section>
<section class="Sh">
<h1 class="Sh" id="HISTORY"><a class="permalink" href="#HISTORY">HISTORY</a></h1>
<p class="Pp">This interface first appeared in <span class="Ux">FreeBSD
    5.0</span>. There is a similar facility called work_queue in the Linux
    kernel.</p>
</section>
<section class="Sh">
<h1 class="Sh" id="AUTHORS"><a class="permalink" href="#AUTHORS">AUTHORS</a></h1>
<p class="Pp">This manual page was written by <span class="An">Doug
    Rabson</span>.</p>
</section>
</div>
<table class="foot">
  <tr>
    <td class="foot-date">April 25, 2022</td>
    <td class="foot-os">FreeBSD 15.0</td>
  </tr>
</table>