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