1.\" -*- nroff -*- 2.\" 3.\" Copyright (c) 2000 Doug Rabson 4.\" 5.\" All rights reserved. 6.\" 7.\" This program is free software. 8.\" 9.\" Redistribution and use in source and binary forms, with or without 10.\" modification, are permitted provided that the following conditions 11.\" are met: 12.\" 1. Redistributions of source code must retain the above copyright 13.\" notice, this list of conditions and the following disclaimer. 14.\" 2. Redistributions in binary form must reproduce the above copyright 15.\" notice, this list of conditions and the following disclaimer in the 16.\" documentation and/or other materials provided with the distribution. 17.\" 18.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR 19.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT, 22.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28.\" 29.\" $FreeBSD$ 30.\" 31.Dd November 21, 2018 32.Dt TASKQUEUE 9 33.Os 34.Sh NAME 35.Nm taskqueue 36.Nd asynchronous task execution 37.Sh SYNOPSIS 38.In sys/param.h 39.In sys/kernel.h 40.In sys/malloc.h 41.In sys/queue.h 42.In sys/taskqueue.h 43.Bd -literal 44typedef void (*task_fn_t)(void *context, int pending); 45 46typedef void (*taskqueue_enqueue_fn)(void *context); 47 48struct task { 49 STAILQ_ENTRY(task) ta_link; /* link for queue */ 50 u_short ta_pending; /* count times queued */ 51 u_short ta_priority; /* priority of task in queue */ 52 task_fn_t ta_func; /* task handler */ 53 void *ta_context; /* argument for handler */ 54}; 55 56enum taskqueue_callback_type { 57 TASKQUEUE_CALLBACK_TYPE_INIT, 58 TASKQUEUE_CALLBACK_TYPE_SHUTDOWN, 59}; 60 61typedef void (*taskqueue_callback_fn)(void *context); 62 63struct timeout_task; 64.Ed 65.Ft struct taskqueue * 66.Fn taskqueue_create "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context" 67.Ft struct taskqueue * 68.Fn taskqueue_create_fast "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context" 69.Ft int 70.Fn taskqueue_start_threads "struct taskqueue **tqp" "int count" "int pri" "const char *name" "..." 71.Ft int 72.Fo taskqueue_start_threads_pinned 73.Fa "struct taskqueue **tqp" "int count" "int pri" "int cpu_id" 74.Fa "const char *name" "..." 75.Fc 76.Ft void 77.Fn taskqueue_set_callback "struct taskqueue *queue" "enum taskqueue_callback_type cb_type" "taskqueue_callback_fn callback" "void *context" 78.Ft void 79.Fn taskqueue_free "struct taskqueue *queue" 80.Ft int 81.Fn taskqueue_enqueue "struct taskqueue *queue" "struct task *task" 82.Ft int 83.Fn taskqueue_enqueue_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" "int ticks" 84.Ft int 85.Fn taskqueue_enqueue_timeout_sbt "struct taskqueue *queue" "struct timeout_task *timeout_task" "sbintime_t sbt" "sbintime_t pr" "int flags" 86.Ft int 87.Fn taskqueue_cancel "struct taskqueue *queue" "struct task *task" "u_int *pendp" 88.Ft int 89.Fn taskqueue_cancel_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" "u_int *pendp" 90.Ft void 91.Fn taskqueue_drain "struct taskqueue *queue" "struct task *task" 92.Ft void 93.Fn taskqueue_drain_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" 94.Ft void 95.Fn taskqueue_drain_all "struct taskqueue *queue" 96.Ft void 97.Fn taskqueue_quiesce "struct taskqueue *queue" 98.Ft void 99.Fn taskqueue_block "struct taskqueue *queue" 100.Ft void 101.Fn taskqueue_unblock "struct taskqueue *queue" 102.Ft int 103.Fn taskqueue_member "struct taskqueue *queue" "struct thread *td" 104.Ft void 105.Fn taskqueue_run "struct taskqueue *queue" 106.Fn TASK_INIT "struct task *task" "int priority" "task_fn_t func" "void *context" 107.Fn TASK_INITIALIZER "int priority" "task_fn_t func" "void *context" 108.Fn TASKQUEUE_DECLARE "name" 109.Fn TASKQUEUE_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init" 110.Fn TASKQUEUE_FAST_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init" 111.Fn TASKQUEUE_DEFINE_THREAD "name" 112.Fn TASKQUEUE_FAST_DEFINE_THREAD "name" 113.Fn TIMEOUT_TASK_INIT "struct taskqueue *queue" "struct timeout_task *timeout_task" "int priority" "task_fn_t func" "void *context" 114.Sh DESCRIPTION 115These functions provide a simple interface for asynchronous execution 116of code. 117.Pp 118The function 119.Fn taskqueue_create 120is used to create new queues. 121The arguments to 122.Fn taskqueue_create 123include a name that should be unique, 124a set of 125.Xr malloc 9 126flags that specify whether the call to 127.Fn malloc 128is allowed to sleep, 129a function that is called from 130.Fn taskqueue_enqueue 131when a task is added to the queue, 132and a pointer to the memory location where the identity of the 133thread that services the queue is recorded. 134.\" XXX The rest of the sentence gets lots in relation to the first part. 135The function called from 136.Fn taskqueue_enqueue 137must arrange for the queue to be processed 138(for instance by scheduling a software interrupt or waking a kernel 139thread). 140The memory location where the thread identity is recorded is used 141to signal the service thread(s) to terminate--when this value is set to 142zero and the thread is signaled it will terminate. 143If the queue is intended for use in fast interrupt handlers 144.Fn taskqueue_create_fast 145should be used in place of 146.Fn taskqueue_create . 147.Pp 148The function 149.Fn taskqueue_free 150should be used to free the memory used by the queue. 151Any tasks that are on the queue will be executed at this time after 152which the thread servicing the queue will be signaled that it should exit. 153.Pp 154Once a taskqueue has been created, its threads should be started using 155.Fn taskqueue_start_threads 156or 157.Fn taskqueue_start_threads_pinned . 158.Fn taskqueue_start_threads_pinned 159takes a 160.Va cpu_id 161argument which will cause the threads which are started for the taskqueue 162to be pinned to run on the given CPU. 163Callbacks may optionally be registered using 164.Fn taskqueue_set_callback . 165Currently, callbacks may be registered for the following purposes: 166.Bl -tag -width TASKQUEUE_CALLBACK_TYPE_SHUTDOWN 167.It Dv TASKQUEUE_CALLBACK_TYPE_INIT 168This callback is called by every thread in the taskqueue, before it executes 169any tasks. 170This callback must be set before the taskqueue's threads are started. 171.It Dv TASKQUEUE_CALLBACK_TYPE_SHUTDOWN 172This callback is called by every thread in the taskqueue, after it executes 173its last task. 174This callback will always be called before the taskqueue structure is 175reclaimed. 176.El 177.Pp 178To add a task to the list of tasks queued on a taskqueue, call 179.Fn taskqueue_enqueue 180with pointers to the queue and task. 181If the task's 182.Va ta_pending 183field is non-zero, 184then it is simply incremented to reflect the number of times the task 185was enqueued, up to a cap of USHRT_MAX. 186Otherwise, 187the task is added to the list before the first task which has a lower 188.Va ta_priority 189value or at the end of the list if no tasks have a lower priority. 190Enqueueing a task does not perform any memory allocation which makes 191it suitable for calling from an interrupt handler. 192This function will return 193.Er EPIPE 194if the queue is being freed. 195.Pp 196When a task is executed, 197first it is removed from the queue, 198the value of 199.Va ta_pending 200is recorded and then the field is zeroed. 201The function 202.Va ta_func 203from the task structure is called with the value of the field 204.Va ta_context 205as its first argument 206and the value of 207.Va ta_pending 208as its second argument. 209After the function 210.Va ta_func 211returns, 212.Xr wakeup 9 213is called on the task pointer passed to 214.Fn taskqueue_enqueue . 215.Pp 216The 217.Fn taskqueue_enqueue_timeout 218function is used to schedule the enqueue after the specified number of 219.Va ticks . 220The 221.Fn taskqueue_enqueue_timeout_sbt 222function provides finer control over the scheduling based on 223.Va sbt , 224.Va pr , 225and 226.Va flags , 227as detailed in 228.Xr timeout 9 . 229Only non-fast task queues can be used for 230.Va timeout_task 231scheduling. 232If the 233.Va ticks 234argument is negative, the already scheduled enqueueing is not re-scheduled. 235Otherwise, the task is scheduled for enqueueing in the future, 236after the absolute value of 237.Va ticks 238is passed. 239This function returns -1 if the task is being drained. 240Otherwise, the number of pending calls is returned. 241.Pp 242The 243.Fn taskqueue_cancel 244function is used to cancel a task. 245The 246.Va ta_pending 247count is cleared, and the old value returned in the reference 248parameter 249.Fa pendp , 250if it is 251.Pf non- Dv NULL . 252If the task is currently running, 253.Dv EBUSY 254is returned, otherwise 0. 255To implement a blocking 256.Fn taskqueue_cancel 257that waits for a running task to finish, it could look like: 258.Bd -literal -offset indent 259while (taskqueue_cancel(tq, task, NULL) != 0) 260 taskqueue_drain(tq, task); 261.Ed 262.Pp 263Note that, as with 264.Fn taskqueue_drain , 265the caller is responsible for ensuring that the task is not re-enqueued 266after being canceled. 267.Pp 268Similarly, the 269.Fn taskqueue_cancel_timeout 270function is used to cancel the scheduled task execution. 271.Pp 272The 273.Fn taskqueue_drain 274function is used to wait for the task to finish, and 275the 276.Fn taskqueue_drain_timeout 277function is used to wait for the scheduled task to finish. 278There is no guarantee that the task will not be 279enqueued after call to 280.Fn taskqueue_drain . 281If the caller wants to put the task into a known state, 282then before calling 283.Fn taskqueue_drain 284the caller should use out-of-band means to ensure that the task 285would not be enqueued. 286For example, if the task is enqueued by an interrupt filter, then 287the interrupt could be disabled. 288.Pp 289The 290.Fn taskqueue_drain_all 291function is used to wait for all pending and running tasks that 292are enqueued on the taskqueue to finish. 293Tasks posted to the taskqueue after 294.Fn taskqueue_drain_all 295begins processing, 296including pending enqueues scheduled by a previous call to 297.Fn taskqueue_enqueue_timeout , 298do not extend the wait time of 299.Fn taskqueue_drain_all 300and may complete after 301.Fn taskqueue_drain_all 302returns. 303The 304.Fn taskqueue_quiesce 305function is used to wait for the queue to become empty and for all 306running tasks to finish. 307To avoid blocking indefinitely, the caller must ensure by some mechanism 308that tasks will eventually stop being posted to the queue. 309.Pp 310The 311.Fn taskqueue_block 312function blocks the taskqueue. 313It prevents any enqueued but not running tasks from being executed. 314Future calls to 315.Fn taskqueue_enqueue 316will enqueue tasks, but the tasks will not be run until 317.Fn taskqueue_unblock 318is called. 319Please note that 320.Fn taskqueue_block 321does not wait for any currently running tasks to finish. 322Thus, the 323.Fn taskqueue_block 324does not provide a guarantee that 325.Fn taskqueue_run 326is not running after 327.Fn taskqueue_block 328returns, but it does provide a guarantee that 329.Fn taskqueue_run 330will not be called again 331until 332.Fn taskqueue_unblock 333is called. 334If the caller requires a guarantee that 335.Fn taskqueue_run 336is not running, then this must be arranged by the caller. 337Note that if 338.Fn taskqueue_drain 339is called on a task that is enqueued on a taskqueue that is blocked by 340.Fn taskqueue_block , 341then 342.Fn taskqueue_drain 343can not return until the taskqueue is unblocked. 344This can result in a deadlock if the thread blocked in 345.Fn taskqueue_drain 346is the thread that is supposed to call 347.Fn taskqueue_unblock . 348Thus, use of 349.Fn taskqueue_drain 350after 351.Fn taskqueue_block 352is discouraged, because the state of the task can not be known in advance. 353The same caveat applies to 354.Fn taskqueue_drain_all . 355.Pp 356The 357.Fn taskqueue_unblock 358function unblocks the previously blocked taskqueue. 359All enqueued tasks can be run after this call. 360.Pp 361The 362.Fn taskqueue_member 363function returns 364.No 1 365if the given thread 366.Fa td 367is part of the given taskqueue 368.Fa queue 369and 370.No 0 371otherwise. 372.Pp 373The 374.Fn taskqueue_run 375function will run all pending tasks in the specified 376.Fa queue . 377Normally this function is only used internally. 378.Pp 379A convenience macro, 380.Fn TASK_INIT "task" "priority" "func" "context" 381is provided to initialise a 382.Va task 383structure. 384The 385.Fn TASK_INITIALIZER 386macro generates an initializer for a task structure. 387A macro 388.Fn TIMEOUT_TASK_INIT "queue" "timeout_task" "priority" "func" "context" 389initializes the 390.Va timeout_task 391structure. 392The values of 393.Va priority , 394.Va func , 395and 396.Va context 397are simply copied into the task structure fields and the 398.Va ta_pending 399field is cleared. 400.Pp 401Five macros 402.Fn TASKQUEUE_DECLARE "name" , 403.Fn TASKQUEUE_DEFINE "name" "enqueue" "context" "init" , 404.Fn TASKQUEUE_FAST_DEFINE "name" "enqueue" "context" "init" , 405and 406.Fn TASKQUEUE_DEFINE_THREAD "name" 407.Fn TASKQUEUE_FAST_DEFINE_THREAD "name" 408are used to declare a reference to a global queue, to define the 409implementation of the queue, and declare a queue that uses its own thread. 410The 411.Fn TASKQUEUE_DEFINE 412macro arranges to call 413.Fn taskqueue_create 414with the values of its 415.Va name , 416.Va enqueue 417and 418.Va context 419arguments during system initialisation. 420After calling 421.Fn taskqueue_create , 422the 423.Va init 424argument to the macro is executed as a C statement, 425allowing any further initialisation to be performed 426(such as registering an interrupt handler, etc.). 427.Pp 428The 429.Fn TASKQUEUE_DEFINE_THREAD 430macro defines a new taskqueue with its own kernel thread to serve tasks. 431The variable 432.Vt struct taskqueue *taskqueue_name 433is used to enqueue tasks onto the queue. 434.Pp 435.Fn TASKQUEUE_FAST_DEFINE 436and 437.Fn TASKQUEUE_FAST_DEFINE_THREAD 438act just like 439.Fn TASKQUEUE_DEFINE 440and 441.Fn TASKQUEUE_DEFINE_THREAD 442respectively but taskqueue is created with 443.Fn taskqueue_create_fast . 444.Ss Predefined Task Queues 445The system provides four global taskqueues, 446.Va taskqueue_fast , 447.Va taskqueue_swi , 448.Va taskqueue_swi_giant , 449and 450.Va taskqueue_thread . 451The 452.Va taskqueue_fast 453queue is for swi handlers dispatched from fast interrupt handlers, 454where sleep mutexes cannot be used. 455The swi taskqueues are run via a software interrupt mechanism. 456The 457.Va taskqueue_swi 458queue runs without the protection of the 459.Va Giant 460kernel lock, and the 461.Va taskqueue_swi_giant 462queue runs with the protection of the 463.Va Giant 464kernel lock. 465The thread taskqueue 466.Va taskqueue_thread 467runs in a kernel thread context, and tasks run from this thread do 468not run under the 469.Va Giant 470kernel lock. 471If the caller wants to run under 472.Va Giant , 473he should explicitly acquire and release 474.Va Giant 475in his taskqueue handler routine. 476.Pp 477To use these queues, 478call 479.Fn taskqueue_enqueue 480with the value of the global taskqueue variable for the queue you wish to 481use. 482.Pp 483The software interrupt queues can be used, 484for instance, for implementing interrupt handlers which must perform a 485significant amount of processing in the handler. 486The hardware interrupt handler would perform minimal processing of the 487interrupt and then enqueue a task to finish the work. 488This reduces to a minimum 489the amount of time spent with interrupts disabled. 490.Pp 491The thread queue can be used, for instance, by interrupt level routines 492that need to call kernel functions that do things that can only be done 493from a thread context. 494(e.g., call malloc with the M_WAITOK flag.) 495.Pp 496Note that tasks queued on shared taskqueues such as 497.Va taskqueue_swi 498may be delayed an indeterminate amount of time before execution. 499If queueing delays cannot be tolerated then a private taskqueue should 500be created with a dedicated processing thread. 501.Sh SEE ALSO 502.Xr ithread 9 , 503.Xr kthread 9 , 504.Xr swi 9 505.Xr timeout 9 506.Sh HISTORY 507This interface first appeared in 508.Fx 5.0 . 509There is a similar facility called work_queue in the Linux kernel. 510.Sh AUTHORS 511This manual page was written by 512.An Doug Rabson . 513