1.\" 2.\" Copyright (c) 2000 Doug Rabson 3.\" 4.\" All rights reserved. 5.\" 6.\" This program is free software. 7.\" 8.\" Redistribution and use in source and binary forms, with or without 9.\" modification, are permitted provided that the following conditions 10.\" are met: 11.\" 1. Redistributions of source code must retain the above copyright 12.\" notice, this list of conditions and the following disclaimer. 13.\" 2. Redistributions in binary form must reproduce the above copyright 14.\" notice, this list of conditions and the following disclaimer in the 15.\" documentation and/or other materials provided with the distribution. 16.\" 17.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR 18.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT, 21.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27.\" 28.\" $FreeBSD: src/share/man/man9/taskqueue.9,v 1.21 2007/07/09 06:24:10 jmg Exp $ 29.\" 30.Dd July 24, 2013 31.Dt TASKQUEUE 9 32.Os 33.Sh NAME 34.Nm taskqueue_block , 35.Nm taskqueue_cancel , 36.Nm taskqueue_cancel_timeout , 37.Nm taskqueue_create , 38.Nm taskqueue_drain , 39.Nm taskqueue_drain_timeout , 40.Nm taskqueue_enqueue , 41.Nm taskqueue_enqueue_timeout , 42.Nm taskqueue_free , 43.Nm taskqueue_find , 44.Nm taskqueue_run , 45.Nm taskqueue_start_threads , 46.Nm taskqueue_unblock , 47.Nm TASK_INIT , 48.Nm TASKQUEUE_DECLARE , 49.Nm TASKQUEUE_DEFINE 50.Nd asynchronous task execution 51.Sh SYNOPSIS 52.In sys/param.h 53.In sys/kernel.h 54.In sys/malloc.h 55.In sys/queue.h 56.In sys/taskqueue.h 57.Bd -literal 58typedef void (*task_fn_t)(void *context, int pending); 59 60typedef void (*taskqueue_enqueue_fn)(void *context); 61 62struct task { 63 STAILQ_ENTRY(task) ta_link; /* link for queue */ 64 int ta_pending; /* count times queued */ 65 int ta_priority; /* priority of task in queue */ 66 task_fn_t ta_func; /* task handler */ 67 void *ta_context; /* argument for handler */ 68}; 69.Ed 70.Ft struct taskqueue * 71.Fn taskqueue_create "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context" 72.Ft void 73.Fn taskqueue_free "struct taskqueue *queue" 74.Ft struct taskqueue * 75.Fn taskqueue_find "const char *name" 76.Ft int 77.Fn taskqueue_enqueue "struct taskqueue *queue" "struct task *task" 78.Ft int 79.Fn taskqueue_enqueue_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" "int ticks" 80.Ft int 81.Fn taskqueue_cancel "struct taskqueue *queue" "struct task *task" "u_int *pendp" 82.Ft int 83.Fn taskqueue_cancel_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" "u_int *pendp" 84.Ft void 85.Fn taskqueue_run "struct taskqueue *queue" 86.Ft void 87.Fn taskqueue_drain "struct taskqueue *queue" "struct task *task" 88.Ft void 89.Fn taskqueue_drain_timeout "struct taskqueue *queue" "struct timeout_task *timeout_task" 90.Ft void 91.Fn taskqueue_block "struct taskqueue *queue" 92.Ft void 93.Fn taskqueue_unblock "struct taskqueue *queue" 94.Ft int 95.Fn taskqueue_start_threads "struct taskqueue **tqp" "int count" "int pri" "int ncpu" "const char *fmt" "..." 96.Fn TASK_INIT "struct task *task" "int priority" "task_fn_t *func" "void *context" 97.Fn TASKQUEUE_DECLARE "name" 98.Fn TASKQUEUE_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init" 99.Sh DESCRIPTION 100These functions provide a simple interface for asynchronous execution 101of code. 102.Pp 103The function 104.Fn taskqueue_create 105is used to create new queues. 106The arguments to 107.Fn taskqueue_create 108include a name that should be unique, 109a set of 110.Xr kmalloc 9 111flags that specify whether the call to 112.Fn malloc 113is allowed to sleep, 114and a function which is called from 115.Fn taskqueue_enqueue 116when a task is added to the queue 117.\" XXX The rest of the sentence gets lots in relation to the first part. 118to allow the queue to arrange to be run later 119(for instance by scheduling a software interrupt or waking a kernel 120thread). 121.Pp 122The function 123.Fn taskqueue_free 124should be used to remove the queue from the global list of queues 125and free the memory used by the queue. 126Any tasks that are on the queue will be executed at this time. 127.Pp 128The system maintains a list of all queues which can be searched using 129.Fn taskqueue_find . 130The first queue whose name matches is returned, otherwise 131.Dv NULL . 132.Pp 133To add a task to the list of tasks queued on a taskqueue, call 134.Fn taskqueue_enqueue 135with pointers to the queue and task. 136If the task's 137.Fa ta_pending 138field is non-zero, 139then it is simply incremented to reflect the number of times the task 140was enqueued. 141Otherwise, 142the task is added to the list before the first task which has a lower 143.Fa ta_priority 144value or at the end of the list if no tasks have a lower priority. 145Enqueueing a task does not perform any memory allocation which makes 146it suitable for calling from an interrupt handler. 147This function will return 148.Er EPIPE 149if the queue is being freed. 150.Pp 151To execute all the tasks on a queue, 152call 153.Fn taskqueue_run . 154When a task is executed, 155first it is removed from the queue, 156the value of 157.Fa ta_pending 158is recorded and then the field is zeroed. 159The function 160.Fa ta_func 161from the task structure is called with the value of the field 162.Fa ta_context 163as its first argument 164and the value of 165.Fa ta_pending 166as its second argument. 167.Pp 168The 169.Fn taskqueue_enqueue_timeout 170is used to schedule the enqueue after the specified amount of 171.Va ticks . 172If the 173.Va ticks 174argument is negative, the already scheduled enqueueing is not re-scheduled. 175Otherwise, the task is scheduled for enqueueing in the future, 176after the absolute value of 177.Va ticks 178is passed. 179.Pp 180The 181.Fn taskqueue_cancel 182function is used to cancel a task. 183The 184.Va ta_pending 185count is cleared, and the old value returned in the reference 186parameter 187.Fa pendp , 188if it is 189.Pf non- Dv NULL . 190If the task is currently running, 191.Er EBUSY 192is returned, otherwise 0. 193To implement a blocking 194.Fn taskqueue_cancel 195that waits for a running task to finish, it could look like: 196.Bd -literal -offset indent 197while (taskqueue_cancel(tq, task, NULL) != 0) 198 taskqueue_drain(tq, task); 199.Ed 200.Pp 201Note that, as with 202.Fn taskqueue_drain , 203the caller is responsible for ensuring that the task is not re-enqueued 204after being canceled. 205.Pp 206Similarly, the 207.Fn taskqueue_cancel_timeout 208function is used to cancel the scheduled task execution. 209.Pp 210The 211.Fn taskqueue_drain 212function is used to wait for the task to finish, and 213the 214.Fn taskqueue_drain_timeout 215function is used to wait for the scheduled task to finish. 216There is no guarantee that the task will not be 217enqueued after call to 218.Fn taskqueue_drain . 219.Pp 220The 221.Fn taskqueue_block 222function is used to block a taskqueue. 223When a taskqueue is blocked, calls to 224.Fn taskqueue_enqueue 225will still enqueue tasks but 226they will not be run until the taskqueue is unblocked by calling 227.Fn taskqueue_unblock . 228.Pp 229The 230.Fn taskqueue_start_threads 231function is used to create and start 232.Fa count 233dedicated threads for the taskqueue specified by 234.Fa tqp . 235These threads will be created with the priority specified by 236.Fa pri 237and the name given by 238.Fa fmt 239with _N appended to it, where N is the number of the thread. 240If 241.Fa count 242\*(Gt 1 and 243.Fa ncpu 244is -1, each of the 245.Fa count 246threads will be allocated to a different 247CPU among all available CPUs in a round robin fashion. 248The taskqueue specified by 249.Fa tqp 250must be created previously by calling 251.Fn taskqueue_create 252with the argument 253.Fa enqueue 254set to 255.Fa taskqueue_thread_enqueue . 256.Pp 257A convenience macro, 258.Fn TASK_INIT 259is provided to initialise a 260.Vt task 261structure. 262The values of 263.Fa priority , 264.Fa func , 265and 266.Fa context 267are simply copied into the task structure fields and the 268.Fa ta_pending 269field is cleared. 270.Pp 271Two macros, 272.Fn TASKQUEUE_DECLARE 273and 274.Fn TASKQUEUE_DEFINE 275are used to declare a reference to a global queue, 276and to define the implementation of the queue. 277The 278.Fn TASKQUEUE_DEFINE 279macro arranges to call 280.Fn taskqueue_create 281with the values of its 282.Fa name , 283.Fa enqueue 284and 285.Fa context 286arguments during system initialisation. 287After calling 288.Fn taskqueue_create , 289the 290.Fa init 291argument to the macro is executed as a C statement, 292allowing any further initialisation to be performed 293(such as registering an interrupt handler etc.) 294.Pp 295The system provides two global taskqueues, 296.Va taskqueue_swi 297and 298.Va taskqueue_swi_mp , 299which are run via a software interrupt mechanism. 300To use these queues, call 301.Fn taskqueue_enqueue 302with the value of the global variable 303.Va taskqueue_swi 304or 305.Va taskqueue_swi_mp . 306.Pp 307While 308.Va taskqueue_swi 309acquires the mplock for its tasks, 310.Va taskqueue_swi_mp 311is intended for mpsafe tasks and no mplock will be acquired for them. 312These queues can be used, 313for instance, for implementing interrupt handlers which must perform a 314significant amount of processing in the handler. 315The hardware interrupt handler would perform minimal processing of the 316interrupt and then enqueue a task to finish the work. 317This reduces to a minimum 318the amount of time spent with interrupts disabled. 319.\".Sh SEE ALSO 320.\".Xr ithread 9 , 321.\".Xr kthread 9 , 322.\".Xr swi 9 323.Sh HISTORY 324This interface first appeared in 325.Fx 5.0 . 326There is a similar facility called work_queue in the Linux kernel. 327.Sh AUTHORS 328This manual page was written by 329.An Doug Rabson . 330