xref: /freebsd/share/man/man9/taskqueue.9 (revision 4c49b002e03742fafcdad02d84a6f8bcf4f58bdc)
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
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 */
5082323455SDoug Rabson	int			ta_pending;	/* count times queued */
5182323455SDoug Rabson	int			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 *
5782323455SDoug Rabson.Fn taskqueue_create "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context"
5882323455SDoug Rabson.Ft void
5982323455SDoug Rabson.Fn taskqueue_free "struct taskqueue *queue"
6082323455SDoug Rabson.Ft struct taskqueue *
6182323455SDoug Rabson.Fn taskqueue_find "const char *name"
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
6782323455SDoug Rabson.Fn taskqueue_run "struct taskqueue *queue"
684c49b002SJoseph Koshy.Ft void
694c49b002SJoseph Koshy.Fn taskqueue_run_fast "struct taskqueue *queue"
70f16b3c0dSChad David.Fn TASK_INIT "struct task *task" "int priority" "task_fn_t *func" "void *context"
7182323455SDoug Rabson.Fn TASKQUEUE_DECLARE "name"
72f16b3c0dSChad David.Fn TASKQUEUE_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init"
73227559d1SJohn-Mark Gurney.Fn TASKQUEUE_DEFINE_THREAD "name"
7482323455SDoug Rabson.Sh DESCRIPTION
7582323455SDoug RabsonThese functions provide a simple interface for asynchronous execution
7682323455SDoug Rabsonof code.
7782323455SDoug Rabson.Pp
7882323455SDoug RabsonThe function
7982323455SDoug Rabson.Fn taskqueue_create
8082323455SDoug Rabsonis used to create new queues.
8182323455SDoug RabsonThe arguments to
8282323455SDoug Rabson.Fn taskqueue_create
8382323455SDoug Rabsoninclude a name which should be unique,
8482323455SDoug Rabsona set of
8582323455SDoug Rabson.Xr malloc 9
8682323455SDoug Rabsonflags which specify whether the call to
8782323455SDoug Rabson.Fn malloc
8882323455SDoug Rabsonis allowed to sleep
8982323455SDoug Rabsonand a function which is called from
9082323455SDoug Rabson.Fn taskqueue_enqueue
9182323455SDoug Rabsonwhen a task is added to the queue
9282323455SDoug Rabson.\" XXX	The rest of the sentence gets lots in relation to the first part.
9382323455SDoug Rabsonto allow the queue to arrange to be run later
9482323455SDoug Rabson(for instance by scheduling a software interrupt or waking a kernel
9582323455SDoug Rabsonthread).
9682323455SDoug Rabson.Pp
9782323455SDoug RabsonThe function
9882323455SDoug Rabson.Fn taskqueue_free
9982323455SDoug Rabsonshould be used to remove the queue from the global list of queues
10082323455SDoug Rabsonand free the memory used by the queue.
10182323455SDoug RabsonAny tasks which are on the queue will be executed at this time.
10282323455SDoug Rabson.Pp
10382323455SDoug RabsonThe system maintains a list of all queues which can be searched using
10482323455SDoug Rabson.Fn taskqueue_find .
10582323455SDoug RabsonThe first queue whose name matches is returned, otherwise
10682323455SDoug Rabson.Dv NULL .
10782323455SDoug Rabson.Pp
10882323455SDoug RabsonTo add a task to the list of tasks queued on a taskqueue, call
10982323455SDoug Rabson.Fn taskqueue_enqueue
11082323455SDoug Rabsonwith pointers to the queue and task.
11182323455SDoug RabsonIf the task's
11282323455SDoug Rabson.Va ta_pending
11382323455SDoug Rabsonfield is non-zero,
11482323455SDoug Rabsonthen it is simply incremented to reflect the number of times the task
11582323455SDoug Rabsonwas enqueued.
11682323455SDoug RabsonOtherwise,
11782323455SDoug Rabsonthe task is added to the list before the first task which has a lower
11882323455SDoug Rabson.Va ta_priority
11982323455SDoug Rabsonvalue or at the end of the list if no tasks have a lower priority.
12082323455SDoug RabsonEnqueueing a task does not perform any memory allocation which makes
12182323455SDoug Rabsonit suitable for calling from an interrupt handler.
12282323455SDoug RabsonThis function will return
123b92a189eSRuslan Ermilov.Er EPIPE
12482323455SDoug Rabsonif the queue is being freed.
12582323455SDoug Rabson.Pp
12624b4e9d1SScott LongThe function
12724b4e9d1SScott Long.Fn taskqueue_enqueue_fast
12824b4e9d1SScott Longshould be used in place of
12924b4e9d1SScott Long.Fn taskqueue_enqueue
13024b4e9d1SScott Longwhen the enqueuing must happen from a fast interrupt handler.
13124b4e9d1SScott LongThis method uses spin locks to avoid the possibility of sleeping in the fast
13224b4e9d1SScott Longinterrupt context.
13324b4e9d1SScott Long.Pp
13482323455SDoug RabsonTo execute all the tasks on a queue,
13582323455SDoug Rabsoncall
1364c49b002SJoseph Koshy.Fn taskqueue_run
1374c49b002SJoseph Koshyor
1384c49b002SJoseph Koshy.Fn taskqueue_run_fast
1394c49b002SJoseph Koshydepending on the flavour of the queue.
14082323455SDoug RabsonWhen a task is executed,
14182323455SDoug Rabsonfirst it is removed from the queue,
14282323455SDoug Rabsonthe value of
14382323455SDoug Rabson.Va ta_pending
14482323455SDoug Rabsonis recorded and then the field is zeroed.
14582323455SDoug RabsonThe function
14682323455SDoug Rabson.Va ta_func
14782323455SDoug Rabsonfrom the task structure is called with the value of the field
14882323455SDoug Rabson.Va ta_context
14982323455SDoug Rabsonas its first argument
15082323455SDoug Rabsonand the value of
15182323455SDoug Rabson.Va ta_pending
15282323455SDoug Rabsonas its second argument.
15382323455SDoug Rabson.Pp
15482323455SDoug RabsonA convenience macro,
15582323455SDoug Rabson.Fn TASK_INIT "task" "priority" "func" "context"
15682323455SDoug Rabsonis provided to initialise a
15782323455SDoug Rabson.Va task
15882323455SDoug Rabsonstructure.
15982323455SDoug RabsonThe values of
16082323455SDoug Rabson.Va priority ,
16182323455SDoug Rabson.Va func ,
16282323455SDoug Rabsonand
16382323455SDoug Rabson.Va context
16482323455SDoug Rabsonare simply copied into the task structure fields and the
16582323455SDoug Rabson.Va ta_pending
16682323455SDoug Rabsonfield is cleared.
16782323455SDoug Rabson.Pp
168227559d1SJohn-Mark GurneyThree macros
169227559d1SJohn-Mark Gurney.Fn TASKQUEUE_DECLARE "name" ,
170227559d1SJohn-Mark Gurney.Fn TASKQUEUE_DEFINE "name" "enqueue" "context" "init" ,
17182323455SDoug Rabsonand
172227559d1SJohn-Mark Gurney.Fn TASKQUEUE_DEFINE_THREAD "name"
173227559d1SJohn-Mark Gurneyare used to declare a reference to a global queue, to define the
174c0854fb7SRuslan Ermilovimplementation of the queue, and declare a queue that uses its own thread.
17582323455SDoug RabsonThe
17682323455SDoug Rabson.Fn TASKQUEUE_DEFINE
17782323455SDoug Rabsonmacro arranges to call
17882323455SDoug Rabson.Fn taskqueue_create
17982323455SDoug Rabsonwith the values of its
18082323455SDoug Rabson.Va name ,
18182323455SDoug Rabson.Va enqueue
18282323455SDoug Rabsonand
18382323455SDoug Rabson.Va context
18482323455SDoug Rabsonarguments during system initialisation.
18582323455SDoug RabsonAfter calling
18682323455SDoug Rabson.Fn taskqueue_create ,
18782323455SDoug Rabsonthe
18882323455SDoug Rabson.Va init
18982323455SDoug Rabsonargument to the macro is executed as a C statement,
19082323455SDoug Rabsonallowing any further initialisation to be performed
19182323455SDoug Rabson(such as registering an interrupt handler etc.)
19282323455SDoug Rabson.Pp
193227559d1SJohn-Mark GurneyThe
194227559d1SJohn-Mark Gurney.Fn TASKQUEUE_DEFINE_THREAD
195c0854fb7SRuslan Ermilovmacro defines a new taskqueue with its own kernel thread to serve tasks.
196c0854fb7SRuslan ErmilovThe variable
197227559d1SJohn-Mark Gurney.Vt struct proc *taskqueue_name_proc
198227559d1SJohn-Mark Gurneyis defined which contains the kernel thread serving the tasks.
199227559d1SJohn-Mark GurneyThe variable
200227559d1SJohn-Mark Gurney.Vt struct taskqueue *taskqueue_name
201227559d1SJohn-Mark Gurneyis used to enqueue tasks onto the queue.
2024c49b002SJoseph Koshy.Ss Predefined Task Queues
2034c49b002SJoseph KoshyThe system provides four global taskqueues,
2044c49b002SJoseph Koshy.Va taskqueue_fast ,
20582323455SDoug Rabson.Va taskqueue_swi ,
206cb32189eSKenneth D. Merry.Va taskqueue_swi_giant ,
207cb32189eSKenneth D. Merryand
208cb32189eSKenneth D. Merry.Va taskqueue_thread .
2094c49b002SJoseph KoshyThe
2104c49b002SJoseph Koshy.Va taskqueue_fast
2114c49b002SJoseph Koshyqueue is for swi handlers dispatched from fast interrupt handlers,
2124c49b002SJoseph Koshywhere sleep mutexes cannot be used.
213cb32189eSKenneth D. MerryThe swi taskqueues are run via a software interrupt mechanism.
2144c49b002SJoseph KoshyThe
2154c49b002SJoseph Koshy.Va taskqueue_swi
2164c49b002SJoseph Koshyqueue runs without the protection of the
2174c49b002SJoseph Koshy.Va Giant
2184c49b002SJoseph Koshykernel lock, and the
2194c49b002SJoseph Koshy.Va taskqueue_swi_giant
2204c49b002SJoseph Koshyqueue runs with the protection of the
2214c49b002SJoseph Koshy.Va Giant
222cb32189eSKenneth D. Merrykernel lock.
2234c49b002SJoseph KoshyThe thread taskqueue
2244c49b002SJoseph Koshy.Va taskqueue_thread
2254c49b002SJoseph Koshyruns in a kernel thread context, and tasks run from this thread do
2264c49b002SJoseph Koshynot run under the
2274c49b002SJoseph Koshy.Va Giant
2284c49b002SJoseph Koshykernel lock.
2294c49b002SJoseph KoshyIf the caller wants to run under
2304c49b002SJoseph Koshy.Va Giant ,
2314c49b002SJoseph Koshyhe should explicitly acquire and release
2324c49b002SJoseph Koshy.Va Giant
2334c49b002SJoseph Koshyin his taskqueue handler routine.
234bf7f20c2SRuslan Ermilov.Pp
235cb32189eSKenneth D. MerryTo use these queues,
23682323455SDoug Rabsoncall
23782323455SDoug Rabson.Fn taskqueue_enqueue
238cb32189eSKenneth D. Merrywith the value of the global taskqueue variable for the queue you wish to
239c0854fb7SRuslan Ermilovuse
240c0854fb7SRuslan Ermilov.Va ( taskqueue_swi ,
241cb32189eSKenneth D. Merry.Va taskqueue_swi_giant ,
242cb32189eSKenneth D. Merryor
243c0854fb7SRuslan Ermilov.Va taskqueue_thread ) .
2444c49b002SJoseph KoshyUse
2454c49b002SJoseph Koshy.Fn taskqueue_enqueue_fast
2464c49b002SJoseph Koshyfor the global taskqueue variable
2474c49b002SJoseph Koshy.Va taskqueue_fast .
24882323455SDoug Rabson.Pp
249e0254f10SKenneth D. MerryThe software interrupt queues can be used,
25082323455SDoug Rabsonfor instance, for implementing interrupt handlers which must perform a
25182323455SDoug Rabsonsignificant amount of processing in the handler.
25282323455SDoug RabsonThe hardware interrupt handler would perform minimal processing of the
25382323455SDoug Rabsoninterrupt and then enqueue a task to finish the work.
25482323455SDoug RabsonThis reduces to a minimum
25582323455SDoug Rabsonthe amount of time spent with interrupts disabled.
256cb32189eSKenneth D. Merry.Pp
257cb32189eSKenneth D. MerryThe thread queue can be used, for instance, by interrupt level routines
258cb32189eSKenneth D. Merrythat need to call kernel functions that do things that can only be done
259cb32189eSKenneth D. Merryfrom a thread context.
260cb32189eSKenneth D. Merry(e.g., call malloc with the M_WAITOK flag.)
2613bbf58f9SJoseph Koshy.Sh SEE ALSO
2623bbf58f9SJoseph Koshy.Xr ithread 9 ,
2633bbf58f9SJoseph Koshy.Xr kthread 9 ,
2643bbf58f9SJoseph Koshy.Xr swi 9
26582323455SDoug Rabson.Sh HISTORY
26682323455SDoug RabsonThis interface first appeared in
26782323455SDoug Rabson.Fx 5.0 .
26882323455SDoug RabsonThere is a similar facility called tqueue in the Linux kernel.
26982323455SDoug Rabson.Sh AUTHORS
27082323455SDoug RabsonThis man page was written by
27182323455SDoug Rabson.An Doug Rabson .
2724c49b002SJoseph Koshy.Sh BUGS
2734c49b002SJoseph KoshyThere is no
2744c49b002SJoseph Koshy.Fn taskqueue_create_fast .
275