summaryrefslogtreecommitdiff
path: root/static/freebsd/man9/taskqueue.9 4.html
diff options
context:
space:
mode:
authorJacob McDonnell <jacob@jacobmcdonnell.com>2026-04-25 19:55:43 -0400
committerJacob McDonnell <jacob@jacobmcdonnell.com>2026-04-25 19:55:43 -0400
commitac5e55f5f2af5b92794c2aded46c6bae85b5f5ed (patch)
tree9367490586c84cba28652e443e3166d66c33b0d9 /static/freebsd/man9/taskqueue.9 4.html
parent253e67c8b3a72b3a4757fdbc5845297628db0a4a (diff)
docs: Added All FreeBSD Manuals
Diffstat (limited to 'static/freebsd/man9/taskqueue.9 4.html')
-rw-r--r--static/freebsd/man9/taskqueue.9 4.html494
1 files changed, 494 insertions, 0 deletions
diff --git a/static/freebsd/man9/taskqueue.9 4.html b/static/freebsd/man9/taskqueue.9 4.html
new file mode 100644
index 00000000..d9c314ee
--- /dev/null
+++ b/static/freebsd/man9/taskqueue.9 4.html
@@ -0,0 +1,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>