TASK_ADD(9)
π TASK_ADD(9) β task queues π
okay so this page is from the Kernel Developer's Manual, section 9, and it's literally the whole task-queue friend group. no cap, this is the API for deferring work to a process context. it's giving "not right now, but soon, and in the right context" energy π
β¨ NAME β¨
taskq_create,taskq_destroy,taskq_barrier,taskq_del_barrier,task_set,task_add,task_del,task_pending,TASK_INITIALIZERβ task queues π«Ά
π SYNOPSIS π
#include <sys/task.h>
struct taskq *
taskq_create(const char *name, unsigned int nthreads, int ipl,
unsigned int flags);
void
taskq_destroy(struct taskq *tq);
void
taskq_barrier(struct taskq *tq);
void
taskq_del_barrier(struct taskq *tq, struct task *t);
void
task_set(struct task *t, void (*fn)(void *), void *arg);
int
task_add(struct taskq *tq, struct task *t);
int
task_del(struct taskq *tq, struct task *t);
int
task_pending(struct task *t);
extern struct taskq *const systq;
extern struct taskq *const systqmp;
TASK_INITIALIZER(void (*fn)(void *), void *arg);
π¦ DESCRIPTION π¦
The taskq API is the mechanism for deferring work to a process context. lowkey iconic, highkey essential.
taskq_create() allocates a taskq plus a set of threads that are used to complete work that would be inappropriate for the shared system taskq. The name argument specifies the name of the kernel threads that are created to service the work on the taskq. nthreads specifies the number of threads that will be created to handle the work. ipl specifies the highest interrupt protection level at which task_add() and task_del() will be called against the created taskq. See spl(9) for a list of the IPLs. You can alter the operational characteristics of the taskq by OR'ing the following defines into the flags argument:
TASKQ_MPSAFEβ the threads servicing the taskq will be run without the kernel big lock.
taskq_destroy() causes the resources associated with a previously created taskq to be freed. It will wait till all the tasks in the work queue are completed before returning.
π¨ Calling taskq_destroy() against the system taskq is an error and will lead to undefined behaviour or a system fault. do not do this, bestie, fr fr.
taskq_barrier() guarantees that any task that was running on the tq taskq when the barrier was called has finished by the time the barrier returns. it's a whole "wait for your fave to finish their set" situation β¨
taskq_del_barrier() either removes t from the list of pending tasks on the tq taskq, or waits until any running task has completed.
π The caller oftaskq_barrier()ortaskq_del_barrier()must not hold locks that can block the taskq. Otherwise, the system will deadlock. literally the opposite of slay.
It is the responsibility of the caller to provide the task_set(), task_add(), and task_del() functions with pre-allocated task structures.
task_set() prepares the task structure t to be used in future calls to task_add() and task_del(). t will be prepared to call the function fn with the argument specified by arg. Once initialised, the t structure can be used repeatedly in calls to task_add() and task_del() and does not need to be reinitialised unless the function called and/or its argument must change. set it and forget it, but like, responsibly π
task_add() schedules the execution of the work specified by the task structure t on the tq taskq. The task structure must already be initialised by task_set().
task_del() will remove the task structure t from the taskq tq. If the work was already executed or has not been added to the taskq, the call will have no effect.
π¨ Callingtask_del()against a different taskq than the one given in a previous call totask_add()is an error and will lead to undefined behaviour. not the vibe check you want to fail.
The kernel provides two system taskqs: systq, which executes while holding the kernel lock, and systqmp, which does not hold the kernel lock during execution. They can both be used by any subsystem for short lived tasks. They are serviced by a single thread and can therefore provide predictable ordering of work. Work can be scheduled on the system taskqs from callers at or below IPL_HIGH.
The task_pending() macro can be used to check if a task is scheduled to run. main character energy for "is it queued or not?" π«Ά
A task declaration can be initialised with the TASK_INITIALIZER() macro. The task will be prepared to call the function specified by the fn argument with the void * argument given in arg.
π CONTEXT π
taskq_create() and taskq_destroy() can be called during autoconf, or from process context. taskq_barrier() and taskq_del_barrier() can be called from process context. task_set(), task_add(), task_del(), and task_pending() can be called during autoconf, from process context, or from interrupt context. context matters, bestie, always π
β RETURN VALUES β
taskq_create()returns a pointer to a taskq structure on success orNULLon failure.task_add()will return1if the tasktwas added to the taskqtqor0if the task was already queued.task_del()will return1if the tasktwas removed from the taskqtqor0if the task was not already on the queue.task_pending()will return non-zero if the task is queued to run, or0if the task is not queued.
πΈ SEE ALSO πΈ
π HISTORY π
The task API was originally written by David Gwynne <dlg@openbsd.org>. The task API first appeared in OpenBSD 5.5. periodt, a classic π
xoxo, this Debian build of the Kernel Developer's Manual page is dated June 22, 2022 β TASK_ADD(9) πβ¨
π¦ where this page comes from
- nixpkgs unstable: cvs-export
- Copyright (c) 2013 David Gwynne <dlg@openbsd.org>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms