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 December 4, 2012 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 56struct timeout_task; 57.Ed 58.Ft struct taskqueue * 59.Fn taskqueue_create "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context" 60.Ft struct taskqueue * 61.Fn taskqueue_create_fast "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context" 62.Ft void 63.Fn taskqueue_free "struct taskqueue *queue" 64.Ft int 65.Fn taskqueue_enqueue "struct taskqueue *queue" "struct task *task" 66.Ft int 67.Fn taskqueue_enqueue_fast "struct taskqueue *queue" "struct task *task" 68.Ft int 69.Fn taskqueue_enqueue_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" "int ticks" 70.Ft int 71.Fn taskqueue_cancel "struct taskqueue *queue" "struct task *task" "u_int *pendp" 72.Ft int 73.Fn taskqueue_cancel_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" "u_int *pendp" 74.Ft void 75.Fn taskqueue_drain "struct taskqueue *queue" "struct task *task" 76.Ft void 77.Fn taskqueue_drain_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" 78.Ft int 79.Fn taskqueue_member "struct taskqueue *queue" "struct thread *td" 80.Ft void 81.Fn taskqueue_run "struct taskqueue *queue" 82.Fn TASK_INIT "struct task *task" "int priority" "task_fn_t func" "void *context" 83.Fn TASK_INITIALIZER "int priority" "task_fn_t func" "void *context" 84.Fn TASKQUEUE_DECLARE "name" 85.Fn TASKQUEUE_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init" 86.Fn TASKQUEUE_FAST_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init" 87.Fn TASKQUEUE_DEFINE_THREAD "name" 88.Fn TASKQUEUE_FAST_DEFINE_THREAD "name" 89.Fn TIMEOUT_TASK_INIT "struct taskqueue *queue" "struct timeout_task *timeout_task" "int priority" "task_fn_t func" "void *context" 90.Sh DESCRIPTION 91These functions provide a simple interface for asynchronous execution 92of code. 93.Pp 94The function 95.Fn taskqueue_create 96is used to create new queues. 97The arguments to 98.Fn taskqueue_create 99include a name that should be unique, 100a set of 101.Xr malloc 9 102flags that specify whether the call to 103.Fn malloc 104is allowed to sleep, 105a function that is called from 106.Fn taskqueue_enqueue 107when a task is added to the queue, 108and a pointer to the memory location where the identity of the 109thread that services the queue is recorded. 110.\" XXX The rest of the sentence gets lots in relation to the first part. 111The function called from 112.Fn taskqueue_enqueue 113must arrange for the queue to be processed 114(for instance by scheduling a software interrupt or waking a kernel 115thread). 116The memory location where the thread identity is recorded is used 117to signal the service thread(s) to terminate--when this value is set to 118zero and the thread is signaled it will terminate. 119If the queue is intended for use in fast interrupt handlers 120.Fn taskqueue_create_fast 121should be used in place of 122.Fn taskqueue_create . 123.Pp 124The function 125.Fn taskqueue_free 126should be used to free the memory used by the queue. 127Any tasks that are on the queue will be executed at this time after 128which the thread servicing the queue will be signaled that it should exit. 129.Pp 130To add a task to the list of tasks queued on a taskqueue, call 131.Fn taskqueue_enqueue 132with pointers to the queue and task. 133If the task's 134.Va ta_pending 135field is non-zero, 136then it is simply incremented to reflect the number of times the task 137was enqueued, up to a cap of USHRT_MAX. 138Otherwise, 139the task is added to the list before the first task which has a lower 140.Va ta_priority 141value or at the end of the list if no tasks have a lower priority. 142Enqueueing a task does not perform any memory allocation which makes 143it suitable for calling from an interrupt handler. 144This function will return 145.Er EPIPE 146if the queue is being freed. 147.Pp 148The function 149.Fn taskqueue_enqueue_fast 150should be used in place of 151.Fn taskqueue_enqueue 152when the enqueuing must happen from a fast interrupt handler. 153This method uses spin locks to avoid the possibility of sleeping in the fast 154interrupt context. 155.Pp 156When a task is executed, 157first it is removed from the queue, 158the value of 159.Va ta_pending 160is recorded and then the field is zeroed. 161The function 162.Va ta_func 163from the task structure is called with the value of the field 164.Va ta_context 165as its first argument 166and the value of 167.Va ta_pending 168as its second argument. 169After the function 170.Va ta_func 171returns, 172.Xr wakeup 9 173is called on the task pointer passed to 174.Fn taskqueue_enqueue . 175.Pp 176The 177.Fn taskqueue_enqueue_timeout 178is used to schedule the enqueue after the specified amount of 179.Va ticks . 180Only non-fast task queues can be used for 181.Va timeout_task 182scheduling. 183If the 184.Va ticks 185argument is negative, the already scheduled enqueueing is not re-scheduled. 186Otherwise, the task is scheduled for enqueueing in the future, 187after the absolute value of 188.Va ticks 189is passed. 190.Pp 191The 192.Fn taskqueue_cancel 193function is used to cancel a task. 194The 195.Va ta_pending 196count is cleared, and the old value returned in the reference 197parameter 198.Fa pendp , 199if it is 200.Pf non- Dv NULL . 201If the task is currently running, 202.Dv EBUSY 203is returned, otherwise 0. 204To implement a blocking 205.Fn taskqueue_cancel 206that waits for a running task to finish, it could look like: 207.Bd -literal -offset indent 208while (taskqueue_cancel(tq, task, NULL) != 0) 209 taskqueue_drain(tq, task); 210.Ed 211.Pp 212Note that, as with 213.Fn taskqueue_drain , 214the caller is responsible for ensuring that the task is not re-enqueued 215after being canceled. 216.Pp 217Similarly, the 218.Fn taskqueue_cancel_timeout 219function is used to cancel the scheduled task execution. 220.Pp 221The 222.Fn taskqueue_drain 223function is used to wait for the task to finish, and 224the 225.Fn taskqueue_drain_timeout 226function is used to wait for the scheduled task to finish. 227There is no guarantee that the task will not be 228enqueued after call to 229.Fn taskqueue_drain . 230.Pp 231The 232.Fn taskqueue_member 233function returns 234.No 1 235if the given thread 236.Fa td 237is part of the given taskqueue 238.Fa queue 239and 240.No 0 241otherwise. 242.Pp 243The 244.Fn taskqueue_run 245function will run all pending tasks in the specified 246.Fa queue . 247Normally this function is only used internally. 248.Pp 249A convenience macro, 250.Fn TASK_INIT "task" "priority" "func" "context" 251is provided to initialise a 252.Va task 253structure. 254The 255.Fn TASK_INITIALIZER 256macro generates an initializer for a task structure. 257A macro 258.Fn TIMEOUT_TASK_INIT "queue" "timeout_task" "priority" "func" "context" 259initializes the 260.Va timeout_task 261structure. 262The values of 263.Va priority , 264.Va func , 265and 266.Va context 267are simply copied into the task structure fields and the 268.Va ta_pending 269field is cleared. 270.Pp 271Five macros 272.Fn TASKQUEUE_DECLARE "name" , 273.Fn TASKQUEUE_DEFINE "name" "enqueue" "context" "init" , 274.Fn TASKQUEUE_FAST_DEFINE "name" "enqueue" "context" "init" , 275and 276.Fn TASKQUEUE_DEFINE_THREAD "name" 277.Fn TASKQUEUE_FAST_DEFINE_THREAD "name" 278are used to declare a reference to a global queue, to define the 279implementation of the queue, and declare a queue that uses its own thread. 280The 281.Fn TASKQUEUE_DEFINE 282macro arranges to call 283.Fn taskqueue_create 284with the values of its 285.Va name , 286.Va enqueue 287and 288.Va context 289arguments during system initialisation. 290After calling 291.Fn taskqueue_create , 292the 293.Va init 294argument to the macro is executed as a C statement, 295allowing any further initialisation to be performed 296(such as registering an interrupt handler etc.) 297.Pp 298The 299.Fn TASKQUEUE_DEFINE_THREAD 300macro defines a new taskqueue with its own kernel thread to serve tasks. 301The variable 302.Vt struct taskqueue *taskqueue_name 303is used to enqueue tasks onto the queue. 304.Pp 305.Fn TASKQUEUE_FAST_DEFINE 306and 307.Fn TASKQUEUE_FAST_DEFINE_THREAD 308act just like 309.Fn TASKQUEUE_DEFINE 310and 311.Fn TASKQUEUE_DEFINE_THREAD 312respectively but taskqueue is created with 313.Fn taskqueue_create_fast . 314.Ss Predefined Task Queues 315The system provides four global taskqueues, 316.Va taskqueue_fast , 317.Va taskqueue_swi , 318.Va taskqueue_swi_giant , 319and 320.Va taskqueue_thread . 321The 322.Va taskqueue_fast 323queue is for swi handlers dispatched from fast interrupt handlers, 324where sleep mutexes cannot be used. 325The swi taskqueues are run via a software interrupt mechanism. 326The 327.Va taskqueue_swi 328queue runs without the protection of the 329.Va Giant 330kernel lock, and the 331.Va taskqueue_swi_giant 332queue runs with the protection of the 333.Va Giant 334kernel lock. 335The thread taskqueue 336.Va taskqueue_thread 337runs in a kernel thread context, and tasks run from this thread do 338not run under the 339.Va Giant 340kernel lock. 341If the caller wants to run under 342.Va Giant , 343he should explicitly acquire and release 344.Va Giant 345in his taskqueue handler routine. 346.Pp 347To use these queues, 348call 349.Fn taskqueue_enqueue 350with the value of the global taskqueue variable for the queue you wish to 351use 352.Va ( taskqueue_swi , 353.Va taskqueue_swi_giant , 354or 355.Va taskqueue_thread ) . 356Use 357.Fn taskqueue_enqueue_fast 358for the global taskqueue variable 359.Va taskqueue_fast . 360.Pp 361The software interrupt queues can be used, 362for instance, for implementing interrupt handlers which must perform a 363significant amount of processing in the handler. 364The hardware interrupt handler would perform minimal processing of the 365interrupt and then enqueue a task to finish the work. 366This reduces to a minimum 367the amount of time spent with interrupts disabled. 368.Pp 369The thread queue can be used, for instance, by interrupt level routines 370that need to call kernel functions that do things that can only be done 371from a thread context. 372(e.g., call malloc with the M_WAITOK flag.) 373.Pp 374Note that tasks queued on shared taskqueues such as 375.Va taskqueue_swi 376may be delayed an indeterminate amount of time before execution. 377If queueing delays cannot be tolerated then a private taskqueue should 378be created with a dedicated processing thread. 379.Sh SEE ALSO 380.Xr ithread 9 , 381.Xr kthread 9 , 382.Xr swi 9 383.Sh HISTORY 384This interface first appeared in 385.Fx 5.0 . 386There is a similar facility called work_queue in the Linux kernel. 387.Sh AUTHORS 388This manual page was written by 389.An Doug Rabson . 390