1*a247c996SSascha Wildner.\" 2*a247c996SSascha Wildner.\" Copyright (c) 2000 Doug Rabson 3*a247c996SSascha Wildner.\" 4*a247c996SSascha Wildner.\" All rights reserved. 5*a247c996SSascha Wildner.\" 6*a247c996SSascha Wildner.\" This program is free software. 7*a247c996SSascha Wildner.\" 8*a247c996SSascha Wildner.\" Redistribution and use in source and binary forms, with or without 9*a247c996SSascha Wildner.\" modification, are permitted provided that the following conditions 10*a247c996SSascha Wildner.\" are met: 11*a247c996SSascha Wildner.\" 1. Redistributions of source code must retain the above copyright 12*a247c996SSascha Wildner.\" notice, this list of conditions and the following disclaimer. 13*a247c996SSascha Wildner.\" 2. Redistributions in binary form must reproduce the above copyright 14*a247c996SSascha Wildner.\" notice, this list of conditions and the following disclaimer in the 15*a247c996SSascha Wildner.\" documentation and/or other materials provided with the distribution. 16*a247c996SSascha Wildner.\" 17*a247c996SSascha Wildner.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR 18*a247c996SSascha Wildner.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19*a247c996SSascha Wildner.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20*a247c996SSascha Wildner.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT, 21*a247c996SSascha Wildner.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22*a247c996SSascha Wildner.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23*a247c996SSascha Wildner.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24*a247c996SSascha Wildner.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25*a247c996SSascha Wildner.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26*a247c996SSascha Wildner.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27*a247c996SSascha Wildner.\" 28*a247c996SSascha Wildner.\" $FreeBSD: src/share/man/man9/taskqueue.9,v 1.21 2007/07/09 06:24:10 jmg Exp $ 29*a247c996SSascha Wildner.\" $DragonFly: src/share/man/man9/taskqueue.9,v 1.1 2007/08/10 18:53:19 swildner Exp $ 30*a247c996SSascha Wildner.\" 31*a247c996SSascha Wildner.Dd August 10, 2007 32*a247c996SSascha Wildner.Dt TASKQUEUE 9 33*a247c996SSascha Wildner.Os 34*a247c996SSascha Wildner.Sh NAME 35*a247c996SSascha Wildner.Nm taskqueue_create , 36*a247c996SSascha Wildner.Nm taskqueue_free , 37*a247c996SSascha Wildner.Nm taskqueue_find , 38*a247c996SSascha Wildner.Nm taskqueue_enqueue , 39*a247c996SSascha Wildner.Nm taskqueue_run , 40*a247c996SSascha Wildner.Nm TASK_INIT , 41*a247c996SSascha Wildner.Nm TASKQUEUE_DECLARE , 42*a247c996SSascha Wildner.Nm TASKQUEUE_DEFINE 43*a247c996SSascha Wildner.Nd asynchronous task execution 44*a247c996SSascha Wildner.Sh SYNOPSIS 45*a247c996SSascha Wildner.In sys/param.h 46*a247c996SSascha Wildner.In sys/kernel.h 47*a247c996SSascha Wildner.In sys/malloc.h 48*a247c996SSascha Wildner.In sys/queue.h 49*a247c996SSascha Wildner.In sys/taskqueue.h 50*a247c996SSascha Wildner.Bd -literal 51*a247c996SSascha Wildnertypedef void (*task_fn_t)(void *context, int pending); 52*a247c996SSascha Wildner 53*a247c996SSascha Wildnertypedef void (*taskqueue_enqueue_fn)(void *context); 54*a247c996SSascha Wildner 55*a247c996SSascha Wildnerstruct task { 56*a247c996SSascha Wildner STAILQ_ENTRY(task) ta_link; /* link for queue */ 57*a247c996SSascha Wildner int ta_pending; /* count times queued */ 58*a247c996SSascha Wildner int ta_priority; /* priority of task in queue */ 59*a247c996SSascha Wildner task_fn_t ta_func; /* task handler */ 60*a247c996SSascha Wildner void *ta_context; /* argument for handler */ 61*a247c996SSascha Wildner}; 62*a247c996SSascha Wildner.Ed 63*a247c996SSascha Wildner.Ft struct taskqueue * 64*a247c996SSascha Wildner.Fn taskqueue_create "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context" 65*a247c996SSascha Wildner.Ft void 66*a247c996SSascha Wildner.Fn taskqueue_free "struct taskqueue *queue" 67*a247c996SSascha Wildner.Ft struct taskqueue * 68*a247c996SSascha Wildner.Fn taskqueue_find "const char *name" 69*a247c996SSascha Wildner.Ft int 70*a247c996SSascha Wildner.Fn taskqueue_enqueue "struct taskqueue *queue" "struct task *task" 71*a247c996SSascha Wildner.Ft void 72*a247c996SSascha Wildner.Fn taskqueue_run "struct taskqueue *queue" 73*a247c996SSascha Wildner.Fn TASK_INIT "struct task *task" "int priority" "task_fn_t *func" "void *context" 74*a247c996SSascha Wildner.Fn TASKQUEUE_DECLARE "name" 75*a247c996SSascha Wildner.Fn TASKQUEUE_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init" 76*a247c996SSascha Wildner.Sh DESCRIPTION 77*a247c996SSascha WildnerThese functions provide a simple interface for asynchronous execution 78*a247c996SSascha Wildnerof code. 79*a247c996SSascha Wildner.Pp 80*a247c996SSascha WildnerThe function 81*a247c996SSascha Wildner.Fn taskqueue_create 82*a247c996SSascha Wildneris used to create new queues. 83*a247c996SSascha WildnerThe arguments to 84*a247c996SSascha Wildner.Fn taskqueue_create 85*a247c996SSascha Wildnerinclude a name that should be unique, 86*a247c996SSascha Wildnera set of 87*a247c996SSascha Wildner.Xr malloc 9 88*a247c996SSascha Wildnerflags that specify whether the call to 89*a247c996SSascha Wildner.Fn malloc 90*a247c996SSascha Wildneris allowed to sleep, 91*a247c996SSascha Wildnerand a function which is called from 92*a247c996SSascha Wildner.Fn taskqueue_enqueue 93*a247c996SSascha Wildnerwhen a task is added to the queue 94*a247c996SSascha Wildner.\" XXX The rest of the sentence gets lots in relation to the first part. 95*a247c996SSascha Wildnerto allow the queue to arrange to be run later 96*a247c996SSascha Wildner(for instance by scheduling a software interrupt or waking a kernel 97*a247c996SSascha Wildnerthread). 98*a247c996SSascha Wildner.Pp 99*a247c996SSascha WildnerThe function 100*a247c996SSascha Wildner.Fn taskqueue_free 101*a247c996SSascha Wildnershould be used to remove the queue from the global list of queues 102*a247c996SSascha Wildnerand free the memory used by the queue. 103*a247c996SSascha WildnerAny tasks that are on the queue will be executed at this time. 104*a247c996SSascha Wildner.Pp 105*a247c996SSascha WildnerThe system maintains a list of all queues which can be searched using 106*a247c996SSascha Wildner.Fn taskqueue_find . 107*a247c996SSascha WildnerThe first queue whose name matches is returned, otherwise 108*a247c996SSascha Wildner.Dv NULL . 109*a247c996SSascha Wildner.Pp 110*a247c996SSascha WildnerTo add a task to the list of tasks queued on a taskqueue, call 111*a247c996SSascha Wildner.Fn taskqueue_enqueue 112*a247c996SSascha Wildnerwith pointers to the queue and task. 113*a247c996SSascha WildnerIf the task's 114*a247c996SSascha Wildner.Fa ta_pending 115*a247c996SSascha Wildnerfield is non-zero, 116*a247c996SSascha Wildnerthen it is simply incremented to reflect the number of times the task 117*a247c996SSascha Wildnerwas enqueued. 118*a247c996SSascha WildnerOtherwise, 119*a247c996SSascha Wildnerthe task is added to the list before the first task which has a lower 120*a247c996SSascha Wildner.Fa ta_priority 121*a247c996SSascha Wildnervalue or at the end of the list if no tasks have a lower priority. 122*a247c996SSascha WildnerEnqueueing a task does not perform any memory allocation which makes 123*a247c996SSascha Wildnerit suitable for calling from an interrupt handler. 124*a247c996SSascha WildnerThis function will return 125*a247c996SSascha Wildner.Er EPIPE 126*a247c996SSascha Wildnerif the queue is being freed. 127*a247c996SSascha Wildner.Pp 128*a247c996SSascha WildnerTo execute all the tasks on a queue, 129*a247c996SSascha Wildnercall 130*a247c996SSascha Wildner.Fn taskqueue_run . 131*a247c996SSascha WildnerWhen a task is executed, 132*a247c996SSascha Wildnerfirst it is removed from the queue, 133*a247c996SSascha Wildnerthe value of 134*a247c996SSascha Wildner.Fa ta_pending 135*a247c996SSascha Wildneris recorded and then the field is zeroed. 136*a247c996SSascha WildnerThe function 137*a247c996SSascha Wildner.Fa ta_func 138*a247c996SSascha Wildnerfrom the task structure is called with the value of the field 139*a247c996SSascha Wildner.Fa ta_context 140*a247c996SSascha Wildneras its first argument 141*a247c996SSascha Wildnerand the value of 142*a247c996SSascha Wildner.Fa ta_pending 143*a247c996SSascha Wildneras its second argument. 144*a247c996SSascha Wildner.Pp 145*a247c996SSascha WildnerA convenience macro, 146*a247c996SSascha Wildner.Fn TASK_INIT 147*a247c996SSascha Wildneris provided to initialise a 148*a247c996SSascha Wildner.Vt task 149*a247c996SSascha Wildnerstructure. 150*a247c996SSascha WildnerThe values of 151*a247c996SSascha Wildner.Fa priority , 152*a247c996SSascha Wildner.Fa func , 153*a247c996SSascha Wildnerand 154*a247c996SSascha Wildner.Fa context 155*a247c996SSascha Wildnerare simply copied into the task structure fields and the 156*a247c996SSascha Wildner.Fa ta_pending 157*a247c996SSascha Wildnerfield is cleared. 158*a247c996SSascha Wildner.Pp 159*a247c996SSascha WildnerTwo macros, 160*a247c996SSascha Wildner.Fn TASKQUEUE_DECLARE 161*a247c996SSascha Wildnerand 162*a247c996SSascha Wildner.Fn TASKQUEUE_DEFINE 163*a247c996SSascha Wildnerare used to declare a reference to a global queue, 164*a247c996SSascha Wildnerand to define the implementation of the queue. 165*a247c996SSascha WildnerThe 166*a247c996SSascha Wildner.Fn TASKQUEUE_DEFINE 167*a247c996SSascha Wildnermacro arranges to call 168*a247c996SSascha Wildner.Fn taskqueue_create 169*a247c996SSascha Wildnerwith the values of its 170*a247c996SSascha Wildner.Fa name , 171*a247c996SSascha Wildner.Fa enqueue 172*a247c996SSascha Wildnerand 173*a247c996SSascha Wildner.Fa context 174*a247c996SSascha Wildnerarguments during system initialisation. 175*a247c996SSascha WildnerAfter calling 176*a247c996SSascha Wildner.Fn taskqueue_create , 177*a247c996SSascha Wildnerthe 178*a247c996SSascha Wildner.Fa init 179*a247c996SSascha Wildnerargument to the macro is executed as a C statement, 180*a247c996SSascha Wildnerallowing any further initialisation to be performed 181*a247c996SSascha Wildner(such as registering an interrupt handler etc.) 182*a247c996SSascha Wildner.Pp 183*a247c996SSascha WildnerThe system provides a global taskqueue, 184*a247c996SSascha Wildner.Va taskqueue_swi , 185*a247c996SSascha Wildnerwhich is run via a software interrupt mechanism. 186*a247c996SSascha WildnerTo use this queue, call 187*a247c996SSascha Wildner.Fn taskqueue_enqueue 188*a247c996SSascha Wildnerwith the value of the global variable 189*a247c996SSascha Wildner.Va taskqueue_swi . 190*a247c996SSascha Wildner.Pp 191*a247c996SSascha WildnerThis queue can be used, 192*a247c996SSascha Wildnerfor instance, for implementing interrupt handlers which must perform a 193*a247c996SSascha Wildnersignificant amount of processing in the handler. 194*a247c996SSascha WildnerThe hardware interrupt handler would perform minimal processing of the 195*a247c996SSascha Wildnerinterrupt and then enqueue a task to finish the work. 196*a247c996SSascha WildnerThis reduces to a minimum 197*a247c996SSascha Wildnerthe amount of time spent with interrupts disabled. 198*a247c996SSascha Wildner.\".Sh SEE ALSO 199*a247c996SSascha Wildner.\".Xr ithread 9 , 200*a247c996SSascha Wildner.\".Xr kthread 9 , 201*a247c996SSascha Wildner.\".Xr swi 9 202*a247c996SSascha Wildner.Sh HISTORY 203*a247c996SSascha WildnerThis interface first appeared in 204*a247c996SSascha Wildner.Fx 5.0 . 205*a247c996SSascha WildnerThere is a similar facility called tqueue in the Linux kernel. 206*a247c996SSascha Wildner.Sh AUTHORS 207*a247c996SSascha WildnerThis manual page was written by 208*a247c996SSascha Wildner.An Doug Rabson . 209