diff options
| author | Jacob McDonnell <jacob@jacobmcdonnell.com> | 2026-04-25 19:55:43 -0400 |
|---|---|---|
| committer | Jacob McDonnell <jacob@jacobmcdonnell.com> | 2026-04-25 19:55:43 -0400 |
| commit | ac5e55f5f2af5b92794c2aded46c6bae85b5f5ed (patch) | |
| tree | 9367490586c84cba28652e443e3166d66c33b0d9 /static/freebsd/man9/taskqueue.9 4.html | |
| parent | 253e67c8b3a72b3a4757fdbc5845297628db0a4a (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.html | 494 |
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> — + <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 + <<a class="In">sys/param.h</a>></code> + <br/> + <code class="In">#include <<a class="In">sys/kernel.h</a>></code> + <br/> + <code class="In">#include <<a class="In">sys/malloc.h</a>></code> + <br/> + <code class="In">#include <<a class="In">sys/queue.h</a>></code> + <br/> + <code class="In">#include <<a class="In">sys/taskqueue.h</a>></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> |
