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.\" 3182323455SDoug Rabson.Dd May 12, 2000 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 4482323455SDoug Rabsontypedef void (*task_fn)(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 */ 5082323455SDoug Rabson int ta_pending; /* count times queued */ 5182323455SDoug Rabson int ta_priority; /* priority of task in queue */ 5282323455SDoug Rabson task_fn ta_func; /* task handler */ 5382323455SDoug Rabson void *ta_context; /* argument for handler */ 5482323455SDoug Rabson}; 5582323455SDoug Rabson 5682323455SDoug Rabson.Ed 5782323455SDoug Rabson.Ft struct taskqueue * 5882323455SDoug Rabson.Fn taskqueue_create "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context" 5982323455SDoug Rabson.Ft void 6082323455SDoug Rabson.Fn taskqueue_free "struct taskqueue *queue" 6182323455SDoug Rabson.Ft struct taskqueue * 6282323455SDoug Rabson.Fn taskqueue_find "const char *name" 6382323455SDoug Rabson.Ft int 6482323455SDoug Rabson.Fn taskqueue_enqueue "struct taskqueue *queue" "struct task *task" 6524b4e9d1SScott Long.Ft int 6624b4e9d1SScott Long.Fn taskqueue_enqueue_fast "struct taskqueue *queue" "struct task *task" 6782323455SDoug Rabson.Ft void 6882323455SDoug Rabson.Fn taskqueue_run "struct taskqueue *queue" 69f16b3c0dSChad David.Fn TASK_INIT "struct task *task" "int priority" "task_fn_t *func" "void *context" 7082323455SDoug Rabson.Fn TASKQUEUE_DECLARE "name" 71f16b3c0dSChad David.Fn TASKQUEUE_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init" 7282323455SDoug Rabson.Sh DESCRIPTION 7382323455SDoug RabsonThese functions provide a simple interface for asynchronous execution 7482323455SDoug Rabsonof code. 7582323455SDoug Rabson.Pp 7682323455SDoug RabsonThe function 7782323455SDoug Rabson.Fn taskqueue_create 7882323455SDoug Rabsonis used to create new queues. 7982323455SDoug RabsonThe arguments to 8082323455SDoug Rabson.Fn taskqueue_create 8182323455SDoug Rabsoninclude a name which should be unique, 8282323455SDoug Rabsona set of 8382323455SDoug Rabson.Xr malloc 9 8482323455SDoug Rabsonflags which specify whether the call to 8582323455SDoug Rabson.Fn malloc 8682323455SDoug Rabsonis allowed to sleep 8782323455SDoug Rabsonand a function which is called from 8882323455SDoug Rabson.Fn taskqueue_enqueue 8982323455SDoug Rabsonwhen a task is added to the queue 9082323455SDoug Rabson.\" XXX The rest of the sentence gets lots in relation to the first part. 9182323455SDoug Rabsonto allow the queue to arrange to be run later 9282323455SDoug Rabson(for instance by scheduling a software interrupt or waking a kernel 9382323455SDoug Rabsonthread). 9482323455SDoug Rabson.Pp 9582323455SDoug RabsonThe function 9682323455SDoug Rabson.Fn taskqueue_free 9782323455SDoug Rabsonshould be used to remove the queue from the global list of queues 9882323455SDoug Rabsonand free the memory used by the queue. 9982323455SDoug RabsonAny tasks which are on the queue will be executed at this time. 10082323455SDoug Rabson.Pp 10182323455SDoug RabsonThe system maintains a list of all queues which can be searched using 10282323455SDoug Rabson.Fn taskqueue_find . 10382323455SDoug RabsonThe first queue whose name matches is returned, otherwise 10482323455SDoug Rabson.Dv NULL . 10582323455SDoug Rabson.Pp 10682323455SDoug RabsonTo add a task to the list of tasks queued on a taskqueue, call 10782323455SDoug Rabson.Fn taskqueue_enqueue 10882323455SDoug Rabsonwith pointers to the queue and task. 10982323455SDoug RabsonIf the task's 11082323455SDoug Rabson.Va ta_pending 11182323455SDoug Rabsonfield is non-zero, 11282323455SDoug Rabsonthen it is simply incremented to reflect the number of times the task 11382323455SDoug Rabsonwas enqueued. 11482323455SDoug RabsonOtherwise, 11582323455SDoug Rabsonthe task is added to the list before the first task which has a lower 11682323455SDoug Rabson.Va ta_priority 11782323455SDoug Rabsonvalue or at the end of the list if no tasks have a lower priority. 11882323455SDoug RabsonEnqueueing a task does not perform any memory allocation which makes 11982323455SDoug Rabsonit suitable for calling from an interrupt handler. 12082323455SDoug RabsonThis function will return 121b92a189eSRuslan Ermilov.Er EPIPE 12282323455SDoug Rabsonif the queue is being freed. 12382323455SDoug Rabson.Pp 12424b4e9d1SScott LongThe function 12524b4e9d1SScott Long.Fn taskqueue_enqueue_fast 12624b4e9d1SScott Longshould be used in place of 12724b4e9d1SScott Long.Fn taskqueue_enqueue 12824b4e9d1SScott Longwhen the enqueuing must happen from a fast interrupt handler. 12924b4e9d1SScott LongThis method uses spin locks to avoid the possibility of sleeping in the fast 13024b4e9d1SScott Longinterrupt context. 13124b4e9d1SScott Long.Pp 13282323455SDoug RabsonTo execute all the tasks on a queue, 13382323455SDoug Rabsoncall 13482323455SDoug Rabson.Fn taskqueue_run . 13582323455SDoug RabsonWhen a task is executed, 13682323455SDoug Rabsonfirst it is removed from the queue, 13782323455SDoug Rabsonthe value of 13882323455SDoug Rabson.Va ta_pending 13982323455SDoug Rabsonis recorded and then the field is zeroed. 14082323455SDoug RabsonThe function 14182323455SDoug Rabson.Va ta_func 14282323455SDoug Rabsonfrom the task structure is called with the value of the field 14382323455SDoug Rabson.Va ta_context 14482323455SDoug Rabsonas its first argument 14582323455SDoug Rabsonand the value of 14682323455SDoug Rabson.Va ta_pending 14782323455SDoug Rabsonas its second argument. 14882323455SDoug Rabson.Pp 14982323455SDoug RabsonA convenience macro, 15082323455SDoug Rabson.Fn TASK_INIT "task" "priority" "func" "context" 15182323455SDoug Rabsonis provided to initialise a 15282323455SDoug Rabson.Va task 15382323455SDoug Rabsonstructure. 15482323455SDoug RabsonThe values of 15582323455SDoug Rabson.Va priority , 15682323455SDoug Rabson.Va func , 15782323455SDoug Rabsonand 15882323455SDoug Rabson.Va context 15982323455SDoug Rabsonare simply copied into the task structure fields and the 16082323455SDoug Rabson.Va ta_pending 16182323455SDoug Rabsonfield is cleared. 16282323455SDoug Rabson.Pp 16382323455SDoug RabsonTwo macros 16482323455SDoug Rabson.Fn TASKQUEUE_DECLARE "name" 16582323455SDoug Rabsonand 16682323455SDoug Rabson.Fn TASKQUEUE_DEFINE "name" "enqueue" "context" "init" 16782323455SDoug Rabsonare used to declare a reference to a global queue 16882323455SDoug Rabsonand to define the implementation of the queue. 16982323455SDoug RabsonThe 17082323455SDoug Rabson.Fn TASKQUEUE_DEFINE 17182323455SDoug Rabsonmacro arranges to call 17282323455SDoug Rabson.Fn taskqueue_create 17382323455SDoug Rabsonwith the values of its 17482323455SDoug Rabson.Va name , 17582323455SDoug Rabson.Va enqueue 17682323455SDoug Rabsonand 17782323455SDoug Rabson.Va context 17882323455SDoug Rabsonarguments during system initialisation. 17982323455SDoug RabsonAfter calling 18082323455SDoug Rabson.Fn taskqueue_create , 18182323455SDoug Rabsonthe 18282323455SDoug Rabson.Va init 18382323455SDoug Rabsonargument to the macro is executed as a C statement, 18482323455SDoug Rabsonallowing any further initialisation to be performed 18582323455SDoug Rabson(such as registering an interrupt handler etc.) 18682323455SDoug Rabson.Pp 187cb32189eSKenneth D. MerryThe system provides three global taskqueues, 18882323455SDoug Rabson.Va taskqueue_swi , 189cb32189eSKenneth D. Merry.Va taskqueue_swi_giant , 190cb32189eSKenneth D. Merryand 191cb32189eSKenneth D. Merry.Va taskqueue_thread . 192cb32189eSKenneth D. MerryThe swi taskqueues are run via a software interrupt mechanism. 193cb32189eSKenneth D. MerryThe taskqueue_swi queue runs without the protection of the Giant kernel lock, 194cb32189eSKenneth D. Merryand the taskqueue_swi_giant queue runs with the protection of the Giant 195cb32189eSKenneth D. Merrykernel lock. 196cb32189eSKenneth D. MerryThe thread taskqueue runs in a kernel thread context, and tasks run from 197cb32189eSKenneth D. Merrythis thread do not run under the Giant kernel lock. 198cb32189eSKenneth D. MerryIf the caller wants to run under Giant, he should explicitly acquire and 199cb32189eSKenneth D. Merryrelease Giant in his taskqueue handler routine. 200cb32189eSKenneth D. Merry 201cb32189eSKenneth D. MerryTo use these queues, 20282323455SDoug Rabsoncall 20382323455SDoug Rabson.Fn taskqueue_enqueue 204cb32189eSKenneth D. Merrywith the value of the global taskqueue variable for the queue you wish to 205cb32189eSKenneth D. Merryuse ( 206cb32189eSKenneth D. Merry.Va taskqueue_swi , 207cb32189eSKenneth D. Merry.Va taskqueue_swi_giant , 208cb32189eSKenneth D. Merryor 209cb32189eSKenneth D. Merry.Va taskqueue_thread 210cb32189eSKenneth D. Merry). 21182323455SDoug Rabson.Pp 212e0254f10SKenneth D. MerryThe software interrupt queues can be used, 21382323455SDoug Rabsonfor instance, for implementing interrupt handlers which must perform a 21482323455SDoug Rabsonsignificant amount of processing in the handler. 21582323455SDoug RabsonThe hardware interrupt handler would perform minimal processing of the 21682323455SDoug Rabsoninterrupt and then enqueue a task to finish the work. 21782323455SDoug RabsonThis reduces to a minimum 21882323455SDoug Rabsonthe amount of time spent with interrupts disabled. 219cb32189eSKenneth D. Merry.Pp 220cb32189eSKenneth D. MerryThe thread queue can be used, for instance, by interrupt level routines 221cb32189eSKenneth D. Merrythat need to call kernel functions that do things that can only be done 222cb32189eSKenneth D. Merryfrom a thread context. 223cb32189eSKenneth D. Merry(e.g., call malloc with the M_WAITOK flag.) 22482323455SDoug Rabson.Sh HISTORY 22582323455SDoug RabsonThis interface first appeared in 22682323455SDoug Rabson.Fx 5.0 . 22782323455SDoug RabsonThere is a similar facility called tqueue in the Linux kernel. 22882323455SDoug Rabson.Sh AUTHORS 22982323455SDoug RabsonThis man page was written by 23082323455SDoug Rabson.An Doug Rabson . 231