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 March 1, 2016 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_cancel "struct taskqueue *queue" "struct task *task" "u_int *pendp" 86.Ft int 87.Fn taskqueue_cancel_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" "u_int *pendp" 88.Ft void 89.Fn taskqueue_drain "struct taskqueue *queue" "struct task *task" 90.Ft void 91.Fn taskqueue_drain_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" 92.Ft void 93.Fn taskqueue_drain_all "struct taskqueue *queue" 94.Ft void 95.Fn taskqueue_block "struct taskqueue *queue" 96.Ft void 97.Fn taskqueue_unblock "struct taskqueue *queue" 98.Ft int 99.Fn taskqueue_member "struct taskqueue *queue" "struct thread *td" 100.Ft void 101.Fn taskqueue_run "struct taskqueue *queue" 102.Fn TASK_INIT "struct task *task" "int priority" "task_fn_t func" "void *context" 103.Fn TASK_INITIALIZER "int priority" "task_fn_t func" "void *context" 104.Fn TASKQUEUE_DECLARE "name" 105.Fn TASKQUEUE_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init" 106.Fn TASKQUEUE_FAST_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init" 107.Fn TASKQUEUE_DEFINE_THREAD "name" 108.Fn TASKQUEUE_FAST_DEFINE_THREAD "name" 109.Fn TIMEOUT_TASK_INIT "struct taskqueue *queue" "struct timeout_task *timeout_task" "int priority" "task_fn_t func" "void *context" 110.Sh DESCRIPTION 111These functions provide a simple interface for asynchronous execution 112of code. 113.Pp 114The function 115.Fn taskqueue_create 116is used to create new queues. 117The arguments to 118.Fn taskqueue_create 119include a name that should be unique, 120a set of 121.Xr malloc 9 122flags that specify whether the call to 123.Fn malloc 124is allowed to sleep, 125a function that is called from 126.Fn taskqueue_enqueue 127when a task is added to the queue, 128and a pointer to the memory location where the identity of the 129thread that services the queue is recorded. 130.\" XXX The rest of the sentence gets lots in relation to the first part. 131The function called from 132.Fn taskqueue_enqueue 133must arrange for the queue to be processed 134(for instance by scheduling a software interrupt or waking a kernel 135thread). 136The memory location where the thread identity is recorded is used 137to signal the service thread(s) to terminate--when this value is set to 138zero and the thread is signaled it will terminate. 139If the queue is intended for use in fast interrupt handlers 140.Fn taskqueue_create_fast 141should be used in place of 142.Fn taskqueue_create . 143.Pp 144The function 145.Fn taskqueue_free 146should be used to free the memory used by the queue. 147Any tasks that are on the queue will be executed at this time after 148which the thread servicing the queue will be signaled that it should exit. 149.Pp 150Once a taskqueue has been created, its threads should be started using 151.Fn taskqueue_start_threads 152or 153.Fn taskqueue_start_threads_pinned . 154.Fn taskqueue_start_threads_pinned 155takes a 156.Va cpu_id 157argument which will cause the threads which are started for the taskqueue 158to be pinned to run on the given CPU. 159Callbacks may optionally be registered using 160.Fn taskqueue_set_callback . 161Currently, callbacks may be registered for the following purposes: 162.Bl -tag -width TASKQUEUE_CALLBACK_TYPE_SHUTDOWN 163.It Dv TASKQUEUE_CALLBACK_TYPE_INIT 164This callback is called by every thread in the taskqueue, before it executes 165any tasks. 166This callback must be set before the taskqueue's threads are started. 167.It Dv TASKQUEUE_CALLBACK_TYPE_SHUTDOWN 168This callback is called by every thread in the taskqueue, after it executes 169its last task. 170This callback will always be called before the taskqueue structure is 171reclaimed. 172.El 173.Pp 174To add a task to the list of tasks queued on a taskqueue, call 175.Fn taskqueue_enqueue 176with pointers to the queue and task. 177If the task's 178.Va ta_pending 179field is non-zero, 180then it is simply incremented to reflect the number of times the task 181was enqueued, up to a cap of USHRT_MAX. 182Otherwise, 183the task is added to the list before the first task which has a lower 184.Va ta_priority 185value or at the end of the list if no tasks have a lower priority. 186Enqueueing a task does not perform any memory allocation which makes 187it suitable for calling from an interrupt handler. 188This function will return 189.Er EPIPE 190if the queue is being freed. 191.Pp 192When a task is executed, 193first it is removed from the queue, 194the value of 195.Va ta_pending 196is recorded and then the field is zeroed. 197The function 198.Va ta_func 199from the task structure is called with the value of the field 200.Va ta_context 201as its first argument 202and the value of 203.Va ta_pending 204as its second argument. 205After the function 206.Va ta_func 207returns, 208.Xr wakeup 9 209is called on the task pointer passed to 210.Fn taskqueue_enqueue . 211.Pp 212The 213.Fn taskqueue_enqueue_timeout 214is used to schedule the enqueue after the specified amount of 215.Va ticks . 216Only non-fast task queues can be used for 217.Va timeout_task 218scheduling. 219If the 220.Va ticks 221argument is negative, the already scheduled enqueueing is not re-scheduled. 222Otherwise, the task is scheduled for enqueueing in the future, 223after the absolute value of 224.Va ticks 225is passed. 226This function returns -1 if the task is being drained. 227Otherwise, the number of pending calls is returned. 228.Pp 229The 230.Fn taskqueue_cancel 231function is used to cancel a task. 232The 233.Va ta_pending 234count is cleared, and the old value returned in the reference 235parameter 236.Fa pendp , 237if it is 238.Pf non- Dv NULL . 239If the task is currently running, 240.Dv EBUSY 241is returned, otherwise 0. 242To implement a blocking 243.Fn taskqueue_cancel 244that waits for a running task to finish, it could look like: 245.Bd -literal -offset indent 246while (taskqueue_cancel(tq, task, NULL) != 0) 247 taskqueue_drain(tq, task); 248.Ed 249.Pp 250Note that, as with 251.Fn taskqueue_drain , 252the caller is responsible for ensuring that the task is not re-enqueued 253after being canceled. 254.Pp 255Similarly, the 256.Fn taskqueue_cancel_timeout 257function is used to cancel the scheduled task execution. 258.Pp 259The 260.Fn taskqueue_drain 261function is used to wait for the task to finish, and 262the 263.Fn taskqueue_drain_timeout 264function is used to wait for the scheduled task to finish. 265There is no guarantee that the task will not be 266enqueued after call to 267.Fn taskqueue_drain . 268If the caller wants to put the task into a known state, 269then before calling 270.Fn taskqueue_drain 271the caller should use out-of-band means to ensure that the task 272would not be enqueued. 273For example, if the task is enqueued by an interrupt filter, then 274the interrupt could be disabled. 275.Pp 276The 277.Fn taskqueue_drain_all 278function is used to wait for all pending and running tasks that 279are enqueued on the taskqueue to finish. 280Tasks posted to the taskqueue after 281.Fn taskqueue_drain_all 282begins processing, 283including pending enqueues scheduled by a previous call to 284.Fn taskqueue_enqueue_timeout , 285do not extend the wait time of 286.Fn taskqueue_drain_all 287and may complete after 288.Fn taskqueue_drain_all 289returns. 290.Pp 291The 292.Fn taskqueue_block 293function blocks the taskqueue. 294It prevents any enqueued but not running tasks from being executed. 295Future calls to 296.Fn taskqueue_enqueue 297will enqueue tasks, but the tasks will not be run until 298.Fn taskqueue_unblock 299is called. 300Please note that 301.Fn taskqueue_block 302does not wait for any currently running tasks to finish. 303Thus, the 304.Fn taskqueue_block 305does not provide a guarantee that 306.Fn taskqueue_run 307is not running after 308.Fn taskqueue_block 309returns, but it does provide a guarantee that 310.Fn taskqueue_run 311will not be called again 312until 313.Fn taskqueue_unblock 314is called. 315If the caller requires a guarantee that 316.Fn taskqueue_run 317is not running, then this must be arranged by the caller. 318Note that if 319.Fn taskqueue_drain 320is called on a task that is enqueued on a taskqueue that is blocked by 321.Fn taskqueue_block , 322then 323.Fn taskqueue_drain 324can not return until the taskqueue is unblocked. 325This can result in a deadlock if the thread blocked in 326.Fn taskqueue_drain 327is the thread that is supposed to call 328.Fn taskqueue_unblock . 329Thus, use of 330.Fn taskqueue_drain 331after 332.Fn taskqueue_block 333is discouraged, because the state of the task can not be known in advance. 334The same caveat applies to 335.Fn taskqueue_drain_all . 336.Pp 337The 338.Fn taskqueue_unblock 339function unblocks the previously blocked taskqueue. 340All enqueued tasks can be run after this call. 341.Pp 342The 343.Fn taskqueue_member 344function returns 345.No 1 346if the given thread 347.Fa td 348is part of the given taskqueue 349.Fa queue 350and 351.No 0 352otherwise. 353.Pp 354The 355.Fn taskqueue_run 356function will run all pending tasks in the specified 357.Fa queue . 358Normally this function is only used internally. 359.Pp 360A convenience macro, 361.Fn TASK_INIT "task" "priority" "func" "context" 362is provided to initialise a 363.Va task 364structure. 365The 366.Fn TASK_INITIALIZER 367macro generates an initializer for a task structure. 368A macro 369.Fn TIMEOUT_TASK_INIT "queue" "timeout_task" "priority" "func" "context" 370initializes the 371.Va timeout_task 372structure. 373The values of 374.Va priority , 375.Va func , 376and 377.Va context 378are simply copied into the task structure fields and the 379.Va ta_pending 380field is cleared. 381.Pp 382Five macros 383.Fn TASKQUEUE_DECLARE "name" , 384.Fn TASKQUEUE_DEFINE "name" "enqueue" "context" "init" , 385.Fn TASKQUEUE_FAST_DEFINE "name" "enqueue" "context" "init" , 386and 387.Fn TASKQUEUE_DEFINE_THREAD "name" 388.Fn TASKQUEUE_FAST_DEFINE_THREAD "name" 389are used to declare a reference to a global queue, to define the 390implementation of the queue, and declare a queue that uses its own thread. 391The 392.Fn TASKQUEUE_DEFINE 393macro arranges to call 394.Fn taskqueue_create 395with the values of its 396.Va name , 397.Va enqueue 398and 399.Va context 400arguments during system initialisation. 401After calling 402.Fn taskqueue_create , 403the 404.Va init 405argument to the macro is executed as a C statement, 406allowing any further initialisation to be performed 407(such as registering an interrupt handler etc.) 408.Pp 409The 410.Fn TASKQUEUE_DEFINE_THREAD 411macro defines a new taskqueue with its own kernel thread to serve tasks. 412The variable 413.Vt struct taskqueue *taskqueue_name 414is used to enqueue tasks onto the queue. 415.Pp 416.Fn TASKQUEUE_FAST_DEFINE 417and 418.Fn TASKQUEUE_FAST_DEFINE_THREAD 419act just like 420.Fn TASKQUEUE_DEFINE 421and 422.Fn TASKQUEUE_DEFINE_THREAD 423respectively but taskqueue is created with 424.Fn taskqueue_create_fast . 425.Ss Predefined Task Queues 426The system provides four global taskqueues, 427.Va taskqueue_fast , 428.Va taskqueue_swi , 429.Va taskqueue_swi_giant , 430and 431.Va taskqueue_thread . 432The 433.Va taskqueue_fast 434queue is for swi handlers dispatched from fast interrupt handlers, 435where sleep mutexes cannot be used. 436The swi taskqueues are run via a software interrupt mechanism. 437The 438.Va taskqueue_swi 439queue runs without the protection of the 440.Va Giant 441kernel lock, and the 442.Va taskqueue_swi_giant 443queue runs with the protection of the 444.Va Giant 445kernel lock. 446The thread taskqueue 447.Va taskqueue_thread 448runs in a kernel thread context, and tasks run from this thread do 449not run under the 450.Va Giant 451kernel lock. 452If the caller wants to run under 453.Va Giant , 454he should explicitly acquire and release 455.Va Giant 456in his taskqueue handler routine. 457.Pp 458To use these queues, 459call 460.Fn taskqueue_enqueue 461with the value of the global taskqueue variable for the queue you wish to 462use. 463.Pp 464The software interrupt queues can be used, 465for instance, for implementing interrupt handlers which must perform a 466significant amount of processing in the handler. 467The hardware interrupt handler would perform minimal processing of the 468interrupt and then enqueue a task to finish the work. 469This reduces to a minimum 470the amount of time spent with interrupts disabled. 471.Pp 472The thread queue can be used, for instance, by interrupt level routines 473that need to call kernel functions that do things that can only be done 474from a thread context. 475(e.g., call malloc with the M_WAITOK flag.) 476.Pp 477Note that tasks queued on shared taskqueues such as 478.Va taskqueue_swi 479may be delayed an indeterminate amount of time before execution. 480If queueing delays cannot be tolerated then a private taskqueue should 481be created with a dedicated processing thread. 482.Sh SEE ALSO 483.Xr ithread 9 , 484.Xr kthread 9 , 485.Xr swi 9 486.Sh HISTORY 487This interface first appeared in 488.Fx 5.0 . 489There is a similar facility called work_queue in the Linux kernel. 490.Sh AUTHORS 491This manual page was written by 492.An Doug Rabson . 493