182323455SDoug Rabson.\" -*- nroff -*- 282323455SDoug Rabson.\" 382323455SDoug Rabson.\" Copyright (c) 2000 Doug Rabson 482323455SDoug Rabson.\" 582323455SDoug Rabson.\" All rights reserved. 682323455SDoug Rabson.\" 782323455SDoug Rabson.\" This program is free software. 882323455SDoug Rabson.\" 982323455SDoug Rabson.\" Redistribution and use in source and binary forms, with or without 1082323455SDoug Rabson.\" modification, are permitted provided that the following conditions 1182323455SDoug Rabson.\" are met: 1282323455SDoug Rabson.\" 1. Redistributions of source code must retain the above copyright 1382323455SDoug Rabson.\" notice, this list of conditions and the following disclaimer. 1482323455SDoug Rabson.\" 2. Redistributions in binary form must reproduce the above copyright 1582323455SDoug Rabson.\" notice, this list of conditions and the following disclaimer in the 1682323455SDoug Rabson.\" documentation and/or other materials provided with the distribution. 1782323455SDoug Rabson.\" 1882323455SDoug Rabson.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR 1982323455SDoug Rabson.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 2082323455SDoug Rabson.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2182323455SDoug Rabson.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT, 2282323455SDoug Rabson.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2382323455SDoug Rabson.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2482323455SDoug Rabson.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2582323455SDoug Rabson.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2682323455SDoug Rabson.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2782323455SDoug Rabson.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2882323455SDoug Rabson.\" 2982323455SDoug Rabson.\" $FreeBSD$ 3082323455SDoug Rabson.\" 31e477e4feSPawel Jakub Dawidek.Dd August 18, 2009 3282323455SDoug Rabson.Dt TASKQUEUE 9 3382323455SDoug Rabson.Os 3482323455SDoug Rabson.Sh NAME 3582323455SDoug Rabson.Nm taskqueue 3682323455SDoug Rabson.Nd asynchronous task execution 3782323455SDoug Rabson.Sh SYNOPSIS 3832eef9aeSRuslan Ermilov.In sys/param.h 39f16b3c0dSChad David.In sys/kernel.h 40f16b3c0dSChad David.In sys/malloc.h 4132eef9aeSRuslan Ermilov.In sys/queue.h 4232eef9aeSRuslan Ermilov.In sys/taskqueue.h 4382323455SDoug Rabson.Bd -literal 44f674e945SBruce M Simpsontypedef void (*task_fn_t)(void *context, int pending); 4582323455SDoug Rabson 4682323455SDoug Rabsontypedef void (*taskqueue_enqueue_fn)(void *context); 4782323455SDoug Rabson 4882323455SDoug Rabsonstruct task { 4982323455SDoug Rabson STAILQ_ENTRY(task) ta_link; /* link for queue */ 50cf82599dSSam Leffler u_short ta_pending; /* count times queued */ 51cf82599dSSam Leffler u_short ta_priority; /* priority of task in queue */ 52f674e945SBruce M Simpson task_fn_t ta_func; /* task handler */ 5382323455SDoug Rabson void *ta_context; /* argument for handler */ 5482323455SDoug Rabson}; 5582323455SDoug Rabson.Ed 5682323455SDoug Rabson.Ft struct taskqueue * 578f668ffaSOleksandr Tymoshenko.Fn taskqueue_create "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context" 582eb30874SOleksandr Tymoshenko.Ft struct taskqueue * 592eb30874SOleksandr Tymoshenko.Fn taskqueue_create_fast "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context" 6082323455SDoug Rabson.Ft void 6182323455SDoug Rabson.Fn taskqueue_free "struct taskqueue *queue" 6282323455SDoug Rabson.Ft int 6382323455SDoug Rabson.Fn taskqueue_enqueue "struct taskqueue *queue" "struct task *task" 6424b4e9d1SScott Long.Ft int 6524b4e9d1SScott Long.Fn taskqueue_enqueue_fast "struct taskqueue *queue" "struct task *task" 6682323455SDoug Rabson.Ft void 67fff7ff71SGleb Smirnoff.Fn taskqueue_drain "struct taskqueue *queue" "struct task *task" 68159ef108SPawel Jakub Dawidek.Ft int 69159ef108SPawel Jakub Dawidek.Fn taskqueue_member "struct taskqueue *queue" "struct thread *td" 70a92f0ee8SMatthew D Fleming.Ft void 71*bf73d4d2SMatthew D Fleming.Fn taskqueue_run "struct taskqueue *queue" 72f16b3c0dSChad David.Fn TASK_INIT "struct task *task" "int priority" "task_fn_t *func" "void *context" 7382323455SDoug Rabson.Fn TASKQUEUE_DECLARE "name" 74f16b3c0dSChad David.Fn TASKQUEUE_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init" 752eb30874SOleksandr Tymoshenko.Fn TASKQUEUE_FAST_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init" 76227559d1SJohn-Mark Gurney.Fn TASKQUEUE_DEFINE_THREAD "name" 772eb30874SOleksandr Tymoshenko.Fn TASKQUEUE_FAST_DEFINE_THREAD "name" 7882323455SDoug Rabson.Sh DESCRIPTION 7982323455SDoug RabsonThese functions provide a simple interface for asynchronous execution 8082323455SDoug Rabsonof code. 8182323455SDoug Rabson.Pp 8282323455SDoug RabsonThe function 8382323455SDoug Rabson.Fn taskqueue_create 8482323455SDoug Rabsonis used to create new queues. 8582323455SDoug RabsonThe arguments to 8682323455SDoug Rabson.Fn taskqueue_create 87cf82599dSSam Lefflerinclude a name that should be unique, 8882323455SDoug Rabsona set of 8982323455SDoug Rabson.Xr malloc 9 90cf82599dSSam Lefflerflags that specify whether the call to 9182323455SDoug Rabson.Fn malloc 92cf82599dSSam Leffleris allowed to sleep, 93cf82599dSSam Lefflera function that is called from 9482323455SDoug Rabson.Fn taskqueue_enqueue 95cf82599dSSam Lefflerwhen a task is added to the queue, 96cf82599dSSam Lefflerand a pointer to the memory location where the identity of the 97cf82599dSSam Lefflerthread that services the queue is recorded. 9882323455SDoug Rabson.\" XXX The rest of the sentence gets lots in relation to the first part. 99cf82599dSSam LefflerThe function called from 100cf82599dSSam Leffler.Fn taskqueue_enqueue 101cf82599dSSam Lefflermust arrange for the queue to be processed 10282323455SDoug Rabson(for instance by scheduling a software interrupt or waking a kernel 10382323455SDoug Rabsonthread). 104cf82599dSSam LefflerThe memory location where the thread identity is recorded is used 105cf82599dSSam Lefflerto signal the service thread(s) to terminate--when this value is set to 106cf82599dSSam Lefflerzero and the thread is signaled it will terminate. 1072eb30874SOleksandr TymoshenkoIf the queue is intended for use in fast interrupt handlers 1082eb30874SOleksandr Tymoshenko.Fn taskqueue_create_fast 1092eb30874SOleksandr Tymoshenkoshould be used in place of 1102eb30874SOleksandr Tymoshenko.Fn taskqueue_create . 11182323455SDoug Rabson.Pp 11282323455SDoug RabsonThe function 11382323455SDoug Rabson.Fn taskqueue_free 114e477e4feSPawel Jakub Dawidekshould be used to free the memory used by the queue. 115cf82599dSSam LefflerAny tasks that are on the queue will be executed at this time after 116cf82599dSSam Lefflerwhich the thread servicing the queue will be signaled that it should exit. 11782323455SDoug Rabson.Pp 11882323455SDoug RabsonTo add a task to the list of tasks queued on a taskqueue, call 11982323455SDoug Rabson.Fn taskqueue_enqueue 12082323455SDoug Rabsonwith pointers to the queue and task. 12182323455SDoug RabsonIf the task's 12282323455SDoug Rabson.Va ta_pending 12382323455SDoug Rabsonfield is non-zero, 12482323455SDoug Rabsonthen it is simply incremented to reflect the number of times the task 12582323455SDoug Rabsonwas enqueued. 12682323455SDoug RabsonOtherwise, 12782323455SDoug Rabsonthe task is added to the list before the first task which has a lower 12882323455SDoug Rabson.Va ta_priority 12982323455SDoug Rabsonvalue or at the end of the list if no tasks have a lower priority. 13082323455SDoug RabsonEnqueueing a task does not perform any memory allocation which makes 13182323455SDoug Rabsonit suitable for calling from an interrupt handler. 13282323455SDoug RabsonThis function will return 133b92a189eSRuslan Ermilov.Er EPIPE 13482323455SDoug Rabsonif the queue is being freed. 13582323455SDoug Rabson.Pp 13624b4e9d1SScott LongThe function 13724b4e9d1SScott Long.Fn taskqueue_enqueue_fast 13824b4e9d1SScott Longshould be used in place of 13924b4e9d1SScott Long.Fn taskqueue_enqueue 14024b4e9d1SScott Longwhen the enqueuing must happen from a fast interrupt handler. 14124b4e9d1SScott LongThis method uses spin locks to avoid the possibility of sleeping in the fast 14224b4e9d1SScott Longinterrupt context. 14324b4e9d1SScott Long.Pp 14482323455SDoug RabsonWhen a task is executed, 14582323455SDoug Rabsonfirst it is removed from the queue, 14682323455SDoug Rabsonthe value of 14782323455SDoug Rabson.Va ta_pending 14882323455SDoug Rabsonis recorded and then the field is zeroed. 14982323455SDoug RabsonThe function 15082323455SDoug Rabson.Va ta_func 15182323455SDoug Rabsonfrom the task structure is called with the value of the field 15282323455SDoug Rabson.Va ta_context 15382323455SDoug Rabsonas its first argument 15482323455SDoug Rabsonand the value of 15582323455SDoug Rabson.Va ta_pending 15682323455SDoug Rabsonas its second argument. 157f616cf33SJohn-Mark GurneyAfter the function 158f616cf33SJohn-Mark Gurney.Va ta_func 159f616cf33SJohn-Mark Gurneyreturns, 160f616cf33SJohn-Mark Gurney.Xr wakeup 9 161f616cf33SJohn-Mark Gurneyis called on the task pointer passed to 162f616cf33SJohn-Mark Gurney.Fn taskqueue_enqueue . 16382323455SDoug Rabson.Pp 164fff7ff71SGleb SmirnoffThe 165fff7ff71SGleb Smirnoff.Fn taskqueue_drain 166fff7ff71SGleb Smirnofffunction is used to wait for the task to finish. 167fff7ff71SGleb SmirnoffThere is no guarantee that the task will not be 168fff7ff71SGleb Smirnoffenqueued after call to 169fff7ff71SGleb Smirnoff.Fn taskqueue_drain . 170fff7ff71SGleb Smirnoff.Pp 171159ef108SPawel Jakub DawidekThe 172159ef108SPawel Jakub Dawidek.Fn taskqueue_member 173159ef108SPawel Jakub Dawidekfunction returns 174159ef108SPawel Jakub Dawidek.No 1 1759c1a8ce4SPawel Jakub Dawidekif the given thread 176159ef108SPawel Jakub Dawidek.Fa td 1779ba47352SJoel Dahlis part of the given taskqueue 178159ef108SPawel Jakub Dawidek.Fa queue 179159ef108SPawel Jakub Dawidekand 180159ef108SPawel Jakub Dawidek.No 0 181159ef108SPawel Jakub Dawidekotherwise. 182159ef108SPawel Jakub Dawidek.Pp 183a92f0ee8SMatthew D FlemingThe 184a92f0ee8SMatthew D Fleming.Fn taskqueue_run 185a92f0ee8SMatthew D Flemingfunction will run all pending tasks in the specified 186a92f0ee8SMatthew D Fleming.Fa queue . 187a92f0ee8SMatthew D FlemingNormally this function is only used internally. 188a92f0ee8SMatthew D Fleming.Pp 18982323455SDoug RabsonA convenience macro, 19082323455SDoug Rabson.Fn TASK_INIT "task" "priority" "func" "context" 19182323455SDoug Rabsonis provided to initialise a 19282323455SDoug Rabson.Va task 19382323455SDoug Rabsonstructure. 19482323455SDoug RabsonThe values of 19582323455SDoug Rabson.Va priority , 19682323455SDoug Rabson.Va func , 19782323455SDoug Rabsonand 19882323455SDoug Rabson.Va context 19982323455SDoug Rabsonare simply copied into the task structure fields and the 20082323455SDoug Rabson.Va ta_pending 20182323455SDoug Rabsonfield is cleared. 20282323455SDoug Rabson.Pp 2032eb30874SOleksandr TymoshenkoFive macros 204227559d1SJohn-Mark Gurney.Fn TASKQUEUE_DECLARE "name" , 205227559d1SJohn-Mark Gurney.Fn TASKQUEUE_DEFINE "name" "enqueue" "context" "init" , 2062eb30874SOleksandr Tymoshenko.Fn TASKQUEUE_FAST_DEFINE "name" "enqueue" "context" "init" , 20782323455SDoug Rabsonand 208227559d1SJohn-Mark Gurney.Fn TASKQUEUE_DEFINE_THREAD "name" 2092eb30874SOleksandr Tymoshenko.Fn TASKQUEUE_FAST_DEFINE_THREAD "name" 210227559d1SJohn-Mark Gurneyare used to declare a reference to a global queue, to define the 211c0854fb7SRuslan Ermilovimplementation of the queue, and declare a queue that uses its own thread. 21282323455SDoug RabsonThe 21382323455SDoug Rabson.Fn TASKQUEUE_DEFINE 21482323455SDoug Rabsonmacro arranges to call 21582323455SDoug Rabson.Fn taskqueue_create 21682323455SDoug Rabsonwith the values of its 21782323455SDoug Rabson.Va name , 21882323455SDoug Rabson.Va enqueue 21982323455SDoug Rabsonand 22082323455SDoug Rabson.Va context 22182323455SDoug Rabsonarguments during system initialisation. 22282323455SDoug RabsonAfter calling 22382323455SDoug Rabson.Fn taskqueue_create , 22482323455SDoug Rabsonthe 22582323455SDoug Rabson.Va init 22682323455SDoug Rabsonargument to the macro is executed as a C statement, 22782323455SDoug Rabsonallowing any further initialisation to be performed 22882323455SDoug Rabson(such as registering an interrupt handler etc.) 22982323455SDoug Rabson.Pp 230227559d1SJohn-Mark GurneyThe 231227559d1SJohn-Mark Gurney.Fn TASKQUEUE_DEFINE_THREAD 232c0854fb7SRuslan Ermilovmacro defines a new taskqueue with its own kernel thread to serve tasks. 233c0854fb7SRuslan ErmilovThe variable 234227559d1SJohn-Mark Gurney.Vt struct taskqueue *taskqueue_name 235227559d1SJohn-Mark Gurneyis used to enqueue tasks onto the queue. 2362eb30874SOleksandr Tymoshenko.Pp 2372eb30874SOleksandr Tymoshenko.Fn TASKQUEUE_FAST_DEFINE 2382eb30874SOleksandr Tymoshenkoand 2392eb30874SOleksandr Tymoshenko.Fn TASKQUEUE_FAST_DEFINE_THREAD 2402eb30874SOleksandr Tymoshenkoact just like 2412eb30874SOleksandr Tymoshenko.Fn TASKQUEUE_DEFINE 2422eb30874SOleksandr Tymoshenkoand 2432eb30874SOleksandr Tymoshenko.Fn TASKQUEUE_DEFINE_THREAD 2442eb30874SOleksandr Tymoshenkorespectively but taskqueue is created with 2452eb30874SOleksandr Tymoshenko.Fn taskqueue_create_fast . 2464c49b002SJoseph Koshy.Ss Predefined Task Queues 2474c49b002SJoseph KoshyThe system provides four global taskqueues, 2484c49b002SJoseph Koshy.Va taskqueue_fast , 24982323455SDoug Rabson.Va taskqueue_swi , 250cb32189eSKenneth D. Merry.Va taskqueue_swi_giant , 251cb32189eSKenneth D. Merryand 252cb32189eSKenneth D. Merry.Va taskqueue_thread . 2534c49b002SJoseph KoshyThe 2544c49b002SJoseph Koshy.Va taskqueue_fast 2554c49b002SJoseph Koshyqueue is for swi handlers dispatched from fast interrupt handlers, 2564c49b002SJoseph Koshywhere sleep mutexes cannot be used. 257cb32189eSKenneth D. MerryThe swi taskqueues are run via a software interrupt mechanism. 2584c49b002SJoseph KoshyThe 2594c49b002SJoseph Koshy.Va taskqueue_swi 2604c49b002SJoseph Koshyqueue runs without the protection of the 2614c49b002SJoseph Koshy.Va Giant 2624c49b002SJoseph Koshykernel lock, and the 2634c49b002SJoseph Koshy.Va taskqueue_swi_giant 2644c49b002SJoseph Koshyqueue runs with the protection of the 2654c49b002SJoseph Koshy.Va Giant 266cb32189eSKenneth D. Merrykernel lock. 2674c49b002SJoseph KoshyThe thread taskqueue 2684c49b002SJoseph Koshy.Va taskqueue_thread 2694c49b002SJoseph Koshyruns in a kernel thread context, and tasks run from this thread do 2704c49b002SJoseph Koshynot run under the 2714c49b002SJoseph Koshy.Va Giant 2724c49b002SJoseph Koshykernel lock. 2734c49b002SJoseph KoshyIf the caller wants to run under 2744c49b002SJoseph Koshy.Va Giant , 2754c49b002SJoseph Koshyhe should explicitly acquire and release 2764c49b002SJoseph Koshy.Va Giant 2774c49b002SJoseph Koshyin his taskqueue handler routine. 278bf7f20c2SRuslan Ermilov.Pp 279cb32189eSKenneth D. MerryTo use these queues, 28082323455SDoug Rabsoncall 28182323455SDoug Rabson.Fn taskqueue_enqueue 282cb32189eSKenneth D. Merrywith the value of the global taskqueue variable for the queue you wish to 283c0854fb7SRuslan Ermilovuse 284c0854fb7SRuslan Ermilov.Va ( taskqueue_swi , 285cb32189eSKenneth D. Merry.Va taskqueue_swi_giant , 286cb32189eSKenneth D. Merryor 287c0854fb7SRuslan Ermilov.Va taskqueue_thread ) . 2884c49b002SJoseph KoshyUse 2894c49b002SJoseph Koshy.Fn taskqueue_enqueue_fast 2904c49b002SJoseph Koshyfor the global taskqueue variable 2914c49b002SJoseph Koshy.Va taskqueue_fast . 29282323455SDoug Rabson.Pp 293e0254f10SKenneth D. MerryThe software interrupt queues can be used, 29482323455SDoug Rabsonfor instance, for implementing interrupt handlers which must perform a 29582323455SDoug Rabsonsignificant amount of processing in the handler. 29682323455SDoug RabsonThe hardware interrupt handler would perform minimal processing of the 29782323455SDoug Rabsoninterrupt and then enqueue a task to finish the work. 29882323455SDoug RabsonThis reduces to a minimum 29982323455SDoug Rabsonthe amount of time spent with interrupts disabled. 300cb32189eSKenneth D. Merry.Pp 301cb32189eSKenneth D. MerryThe thread queue can be used, for instance, by interrupt level routines 302cb32189eSKenneth D. Merrythat need to call kernel functions that do things that can only be done 303cb32189eSKenneth D. Merryfrom a thread context. 304cb32189eSKenneth D. Merry(e.g., call malloc with the M_WAITOK flag.) 305cf82599dSSam Leffler.Pp 306cf82599dSSam LefflerNote that tasks queued on shared taskqueues such as 307cf82599dSSam Leffler.Va taskqueue_swi 308cf82599dSSam Lefflermay be delayed an indeterminate amount of time before execution. 309cf82599dSSam LefflerIf queueing delays cannot be tolerated then a private taskqueue should 310cf82599dSSam Lefflerbe created with a dedicated processing thread. 3113bbf58f9SJoseph Koshy.Sh SEE ALSO 3123bbf58f9SJoseph Koshy.Xr ithread 9 , 3133bbf58f9SJoseph Koshy.Xr kthread 9 , 3143bbf58f9SJoseph Koshy.Xr swi 9 31582323455SDoug Rabson.Sh HISTORY 31682323455SDoug RabsonThis interface first appeared in 31782323455SDoug Rabson.Fx 5.0 . 31882323455SDoug RabsonThere is a similar facility called tqueue in the Linux kernel. 31982323455SDoug Rabson.Sh AUTHORS 320571dba6eSHiten PandyaThis manual page was written by 32182323455SDoug Rabson.An Doug Rabson . 322