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