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 $ 2987909ed3SSascha Wildner.\" $DragonFly: src/share/man/man9/taskqueue.9,v 1.2 2007/11/07 21:38:00 swildner Exp $ 30a247c996SSascha Wildner.\" 31a247c996SSascha Wildner.Dd August 10, 2007 32a247c996SSascha Wildner.Dt TASKQUEUE 9 33a247c996SSascha Wildner.Os 34a247c996SSascha Wildner.Sh NAME 35a247c996SSascha Wildner.Nm taskqueue_create , 36a247c996SSascha Wildner.Nm taskqueue_free , 37a247c996SSascha Wildner.Nm taskqueue_find , 38a247c996SSascha Wildner.Nm taskqueue_enqueue , 39a247c996SSascha Wildner.Nm taskqueue_run , 40a247c996SSascha Wildner.Nm TASK_INIT , 41a247c996SSascha Wildner.Nm TASKQUEUE_DECLARE , 42a247c996SSascha Wildner.Nm TASKQUEUE_DEFINE 43a247c996SSascha Wildner.Nd asynchronous task execution 44a247c996SSascha Wildner.Sh SYNOPSIS 45a247c996SSascha Wildner.In sys/param.h 46a247c996SSascha Wildner.In sys/kernel.h 47a247c996SSascha Wildner.In sys/malloc.h 48a247c996SSascha Wildner.In sys/queue.h 49a247c996SSascha Wildner.In sys/taskqueue.h 50a247c996SSascha Wildner.Bd -literal 51a247c996SSascha Wildnertypedef void (*task_fn_t)(void *context, int pending); 52a247c996SSascha Wildner 53a247c996SSascha Wildnertypedef void (*taskqueue_enqueue_fn)(void *context); 54a247c996SSascha Wildner 55a247c996SSascha Wildnerstruct task { 56a247c996SSascha Wildner STAILQ_ENTRY(task) ta_link; /* link for queue */ 57a247c996SSascha Wildner int ta_pending; /* count times queued */ 58a247c996SSascha Wildner int ta_priority; /* priority of task in queue */ 59a247c996SSascha Wildner task_fn_t ta_func; /* task handler */ 60a247c996SSascha Wildner void *ta_context; /* argument for handler */ 61a247c996SSascha Wildner}; 62a247c996SSascha Wildner.Ed 63a247c996SSascha Wildner.Ft struct taskqueue * 64a247c996SSascha Wildner.Fn taskqueue_create "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context" 65a247c996SSascha Wildner.Ft void 66a247c996SSascha Wildner.Fn taskqueue_free "struct taskqueue *queue" 67a247c996SSascha Wildner.Ft struct taskqueue * 68a247c996SSascha Wildner.Fn taskqueue_find "const char *name" 69a247c996SSascha Wildner.Ft int 70a247c996SSascha Wildner.Fn taskqueue_enqueue "struct taskqueue *queue" "struct task *task" 71a247c996SSascha Wildner.Ft void 72a247c996SSascha Wildner.Fn taskqueue_run "struct taskqueue *queue" 73*a0d61755SAlex Hornung.Ft void 74*a0d61755SAlex Hornung.Fn taskqueue_drain "struct taskqueue *queue" "struct task *task" 75*a0d61755SAlex Hornung.Ft void 76*a0d61755SAlex Hornung.Fn taskqueue_block "struct taskqueue *queue" 77*a0d61755SAlex Hornung.Ft void 78*a0d61755SAlex Hornung.Fn taskqueue_unblock "struct taskqueue *queue" 79*a0d61755SAlex Hornung.Ft int 80*a0d61755SAlex Hornung.Fn taskqueue_start_threads "struct taskqueue **tqp" "int count" "int pri" "const char *fmt" "..." 81a247c996SSascha Wildner.Fn TASK_INIT "struct task *task" "int priority" "task_fn_t *func" "void *context" 82a247c996SSascha Wildner.Fn TASKQUEUE_DECLARE "name" 83a247c996SSascha Wildner.Fn TASKQUEUE_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init" 84a247c996SSascha Wildner.Sh DESCRIPTION 85a247c996SSascha WildnerThese functions provide a simple interface for asynchronous execution 86a247c996SSascha Wildnerof code. 87a247c996SSascha Wildner.Pp 88a247c996SSascha WildnerThe function 89a247c996SSascha Wildner.Fn taskqueue_create 90a247c996SSascha Wildneris used to create new queues. 91a247c996SSascha WildnerThe arguments to 92a247c996SSascha Wildner.Fn taskqueue_create 93a247c996SSascha Wildnerinclude a name that should be unique, 94a247c996SSascha Wildnera set of 9587909ed3SSascha Wildner.Xr kmalloc 9 96a247c996SSascha Wildnerflags that specify whether the call to 97a247c996SSascha Wildner.Fn malloc 98a247c996SSascha Wildneris allowed to sleep, 99a247c996SSascha Wildnerand a function which is called from 100a247c996SSascha Wildner.Fn taskqueue_enqueue 101a247c996SSascha Wildnerwhen a task is added to the queue 102a247c996SSascha Wildner.\" XXX The rest of the sentence gets lots in relation to the first part. 103a247c996SSascha Wildnerto allow the queue to arrange to be run later 104a247c996SSascha Wildner(for instance by scheduling a software interrupt or waking a kernel 105a247c996SSascha Wildnerthread). 106a247c996SSascha Wildner.Pp 107a247c996SSascha WildnerThe function 108a247c996SSascha Wildner.Fn taskqueue_free 109a247c996SSascha Wildnershould be used to remove the queue from the global list of queues 110a247c996SSascha Wildnerand free the memory used by the queue. 111a247c996SSascha WildnerAny tasks that are on the queue will be executed at this time. 112a247c996SSascha Wildner.Pp 113a247c996SSascha WildnerThe system maintains a list of all queues which can be searched using 114a247c996SSascha Wildner.Fn taskqueue_find . 115a247c996SSascha WildnerThe first queue whose name matches is returned, otherwise 116a247c996SSascha Wildner.Dv NULL . 117a247c996SSascha Wildner.Pp 118a247c996SSascha WildnerTo add a task to the list of tasks queued on a taskqueue, call 119a247c996SSascha Wildner.Fn taskqueue_enqueue 120a247c996SSascha Wildnerwith pointers to the queue and task. 121a247c996SSascha WildnerIf the task's 122a247c996SSascha Wildner.Fa ta_pending 123a247c996SSascha Wildnerfield is non-zero, 124a247c996SSascha Wildnerthen it is simply incremented to reflect the number of times the task 125a247c996SSascha Wildnerwas enqueued. 126a247c996SSascha WildnerOtherwise, 127a247c996SSascha Wildnerthe task is added to the list before the first task which has a lower 128a247c996SSascha Wildner.Fa ta_priority 129a247c996SSascha Wildnervalue or at the end of the list if no tasks have a lower priority. 130a247c996SSascha WildnerEnqueueing a task does not perform any memory allocation which makes 131a247c996SSascha Wildnerit suitable for calling from an interrupt handler. 132a247c996SSascha WildnerThis function will return 133a247c996SSascha Wildner.Er EPIPE 134a247c996SSascha Wildnerif the queue is being freed. 135a247c996SSascha Wildner.Pp 136a247c996SSascha WildnerTo execute all the tasks on a queue, 137a247c996SSascha Wildnercall 138a247c996SSascha Wildner.Fn taskqueue_run . 139a247c996SSascha WildnerWhen a task is executed, 140a247c996SSascha Wildnerfirst it is removed from the queue, 141a247c996SSascha Wildnerthe value of 142a247c996SSascha Wildner.Fa ta_pending 143a247c996SSascha Wildneris recorded and then the field is zeroed. 144a247c996SSascha WildnerThe function 145a247c996SSascha Wildner.Fa ta_func 146a247c996SSascha Wildnerfrom the task structure is called with the value of the field 147a247c996SSascha Wildner.Fa ta_context 148a247c996SSascha Wildneras its first argument 149a247c996SSascha Wildnerand the value of 150a247c996SSascha Wildner.Fa ta_pending 151a247c996SSascha Wildneras its second argument. 152a247c996SSascha Wildner.Pp 153*a0d61755SAlex HornungThe 154*a0d61755SAlex Hornung.Fn taskqueue_drain 155*a0d61755SAlex Hornungfunction is used to wait for the task to finish. 156*a0d61755SAlex HornungThere is no guarantee that the task will not be 157*a0d61755SAlex Hornungenqueued after call to 158*a0d61755SAlex Hornung.Fn taskqueue_drain . 159*a0d61755SAlex Hornung.Pp 160*a0d61755SAlex HornungThe 161*a0d61755SAlex Hornung.Fn taskqueue_block 162*a0d61755SAlex Hornungfunction is used to block a taskqueue. When a taskqueue 163*a0d61755SAlex Hornungis blocked, calls to enqueue will still enqueue tasks but 164*a0d61755SAlex Hornungthey will not be run until the taskqueue is unblocked by 165*a0d61755SAlex Hornungcalling 166*a0d61755SAlex Hornung.Fn taskqueue_unblock . 167*a0d61755SAlex Hornung.Pp 168*a0d61755SAlex HornungThe 169*a0d61755SAlex Hornung.Fn taskqueue_start_threads 170*a0d61755SAlex Hornungfunction is used to create and start 171*a0d61755SAlex Hornung.Fa count 172*a0d61755SAlex Hornungdedicated threads for the taskqueue specified by 173*a0d61755SAlex Hornung.Fa tqp . 174*a0d61755SAlex HornungThese threads will be created with the priority specified by 175*a0d61755SAlex Hornung.Fa pri 176*a0d61755SAlex Hornungand the name given by 177*a0d61755SAlex Hornung.Fa fmt 178*a0d61755SAlex Hornungwith _N appended to it, where N is the number of the thread. 179*a0d61755SAlex HornungThe taskqueue specified by 180*a0d61755SAlex Hornung.Fa tqp 181*a0d61755SAlex Hornungmust be created previously by calling 182*a0d61755SAlex Hornung.Fn taskqueue_create 183*a0d61755SAlex Hornungwith the argument 184*a0d61755SAlex Hornung.Fa enqueue 185*a0d61755SAlex Hornungset to 186*a0d61755SAlex Hornung.Fa taskqueue_thread_enqueue . 187*a0d61755SAlex Hornung.Pp 188a247c996SSascha WildnerA convenience macro, 189a247c996SSascha Wildner.Fn TASK_INIT 190a247c996SSascha Wildneris provided to initialise a 191a247c996SSascha Wildner.Vt task 192a247c996SSascha Wildnerstructure. 193a247c996SSascha WildnerThe values of 194a247c996SSascha Wildner.Fa priority , 195a247c996SSascha Wildner.Fa func , 196a247c996SSascha Wildnerand 197a247c996SSascha Wildner.Fa context 198a247c996SSascha Wildnerare simply copied into the task structure fields and the 199a247c996SSascha Wildner.Fa ta_pending 200a247c996SSascha Wildnerfield is cleared. 201a247c996SSascha Wildner.Pp 202a247c996SSascha WildnerTwo macros, 203a247c996SSascha Wildner.Fn TASKQUEUE_DECLARE 204a247c996SSascha Wildnerand 205a247c996SSascha Wildner.Fn TASKQUEUE_DEFINE 206a247c996SSascha Wildnerare used to declare a reference to a global queue, 207a247c996SSascha Wildnerand to define the implementation of the queue. 208a247c996SSascha WildnerThe 209a247c996SSascha Wildner.Fn TASKQUEUE_DEFINE 210a247c996SSascha Wildnermacro arranges to call 211a247c996SSascha Wildner.Fn taskqueue_create 212a247c996SSascha Wildnerwith the values of its 213a247c996SSascha Wildner.Fa name , 214a247c996SSascha Wildner.Fa enqueue 215a247c996SSascha Wildnerand 216a247c996SSascha Wildner.Fa context 217a247c996SSascha Wildnerarguments during system initialisation. 218a247c996SSascha WildnerAfter calling 219a247c996SSascha Wildner.Fn taskqueue_create , 220a247c996SSascha Wildnerthe 221a247c996SSascha Wildner.Fa init 222a247c996SSascha Wildnerargument to the macro is executed as a C statement, 223a247c996SSascha Wildnerallowing any further initialisation to be performed 224a247c996SSascha Wildner(such as registering an interrupt handler etc.) 225a247c996SSascha Wildner.Pp 226*a0d61755SAlex HornungThe system provides two global taskqueues, 227a247c996SSascha Wildner.Va taskqueue_swi , 228*a0d61755SAlex Hornung.Va taskqueue_swi_mp , 229*a0d61755SAlex Hornungwhich are run via a software interrupt mechanism. 230*a0d61755SAlex HornungTo use these queues, call 231a247c996SSascha Wildner.Fn taskqueue_enqueue 232a247c996SSascha Wildnerwith the value of the global variable 233*a0d61755SAlex Hornung.Va taskqueue_swi or 234*a0d61755SAlex Hornung.Va taskqueue_swi_mp . 235a247c996SSascha Wildner.Pp 236*a0d61755SAlex HornungWhile 237*a0d61755SAlex Hornung.Va taskqueue_swi 238*a0d61755SAlex Hornungacquires the mplock for its tasks, 239*a0d61755SAlex Hornung.Va taskqueue_swi_mp 240*a0d61755SAlex Hornungis intended for mpsafe tasks and no mplock will be acquired for them. 241*a0d61755SAlex HornungThese queues can be used, 242a247c996SSascha Wildnerfor instance, for implementing interrupt handlers which must perform a 243a247c996SSascha Wildnersignificant amount of processing in the handler. 244a247c996SSascha WildnerThe hardware interrupt handler would perform minimal processing of the 245a247c996SSascha Wildnerinterrupt and then enqueue a task to finish the work. 246a247c996SSascha WildnerThis reduces to a minimum 247a247c996SSascha Wildnerthe amount of time spent with interrupts disabled. 248a247c996SSascha Wildner.\".Sh SEE ALSO 249a247c996SSascha Wildner.\".Xr ithread 9 , 250a247c996SSascha Wildner.\".Xr kthread 9 , 251a247c996SSascha Wildner.\".Xr swi 9 252a247c996SSascha Wildner.Sh HISTORY 253a247c996SSascha WildnerThis interface first appeared in 254a247c996SSascha Wildner.Fx 5.0 . 255a247c996SSascha WildnerThere is a similar facility called tqueue in the Linux kernel. 256a247c996SSascha Wildner.Sh AUTHORS 257a247c996SSascha WildnerThis manual page was written by 258a247c996SSascha Wildner.An Doug Rabson . 259