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