xref: /freebsd/share/man/man9/taskqueue.9 (revision e477e4fe8eefd7a033e1ce392555e2bb905fc803)
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
6782323455SDoug Rabson.Fn taskqueue_run "struct taskqueue *queue"
684c49b002SJoseph Koshy.Ft void
694c49b002SJoseph Koshy.Fn taskqueue_run_fast "struct taskqueue *queue"
70fff7ff71SGleb Smirnoff.Ft void
71fff7ff71SGleb Smirnoff.Fn taskqueue_drain "struct taskqueue *queue" "struct task *task"
72159ef108SPawel Jakub Dawidek.Ft int
73159ef108SPawel Jakub Dawidek.Fn taskqueue_member "struct taskqueue *queue" "struct thread *td"
74f16b3c0dSChad David.Fn TASK_INIT "struct task *task" "int priority" "task_fn_t *func" "void *context"
7582323455SDoug Rabson.Fn TASKQUEUE_DECLARE "name"
76f16b3c0dSChad David.Fn TASKQUEUE_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init"
772eb30874SOleksandr Tymoshenko.Fn TASKQUEUE_FAST_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init"
78227559d1SJohn-Mark Gurney.Fn TASKQUEUE_DEFINE_THREAD "name"
792eb30874SOleksandr Tymoshenko.Fn TASKQUEUE_FAST_DEFINE_THREAD "name"
8082323455SDoug Rabson.Sh DESCRIPTION
8182323455SDoug RabsonThese functions provide a simple interface for asynchronous execution
8282323455SDoug Rabsonof code.
8382323455SDoug Rabson.Pp
8482323455SDoug RabsonThe function
8582323455SDoug Rabson.Fn taskqueue_create
8682323455SDoug Rabsonis used to create new queues.
8782323455SDoug RabsonThe arguments to
8882323455SDoug Rabson.Fn taskqueue_create
89cf82599dSSam Lefflerinclude a name that should be unique,
9082323455SDoug Rabsona set of
9182323455SDoug Rabson.Xr malloc 9
92cf82599dSSam Lefflerflags that specify whether the call to
9382323455SDoug Rabson.Fn malloc
94cf82599dSSam Leffleris allowed to sleep,
95cf82599dSSam Lefflera function that is called from
9682323455SDoug Rabson.Fn taskqueue_enqueue
97cf82599dSSam Lefflerwhen a task is added to the queue,
98cf82599dSSam Lefflerand a pointer to the memory location where the identity of the
99cf82599dSSam Lefflerthread that services the queue is recorded.
10082323455SDoug Rabson.\" XXX	The rest of the sentence gets lots in relation to the first part.
101cf82599dSSam LefflerThe function called from
102cf82599dSSam Leffler.Fn taskqueue_enqueue
103cf82599dSSam Lefflermust arrange for the queue to be processed
10482323455SDoug Rabson(for instance by scheduling a software interrupt or waking a kernel
10582323455SDoug Rabsonthread).
106cf82599dSSam LefflerThe memory location where the thread identity is recorded is used
107cf82599dSSam Lefflerto signal the service thread(s) to terminate--when this value is set to
108cf82599dSSam Lefflerzero and the thread is signaled it will terminate.
1092eb30874SOleksandr TymoshenkoIf the queue is intended for use in fast interrupt handlers
1102eb30874SOleksandr Tymoshenko.Fn taskqueue_create_fast
1112eb30874SOleksandr Tymoshenkoshould be used in place of
1122eb30874SOleksandr Tymoshenko.Fn taskqueue_create .
11382323455SDoug Rabson.Pp
11482323455SDoug RabsonThe function
11582323455SDoug Rabson.Fn taskqueue_free
116e477e4feSPawel Jakub Dawidekshould be used to free the memory used by the queue.
117cf82599dSSam LefflerAny tasks that are on the queue will be executed at this time after
118cf82599dSSam Lefflerwhich the thread servicing the queue will be signaled that it should exit.
11982323455SDoug Rabson.Pp
12082323455SDoug RabsonTo add a task to the list of tasks queued on a taskqueue, call
12182323455SDoug Rabson.Fn taskqueue_enqueue
12282323455SDoug Rabsonwith pointers to the queue and task.
12382323455SDoug RabsonIf the task's
12482323455SDoug Rabson.Va ta_pending
12582323455SDoug Rabsonfield is non-zero,
12682323455SDoug Rabsonthen it is simply incremented to reflect the number of times the task
12782323455SDoug Rabsonwas enqueued.
12882323455SDoug RabsonOtherwise,
12982323455SDoug Rabsonthe task is added to the list before the first task which has a lower
13082323455SDoug Rabson.Va ta_priority
13182323455SDoug Rabsonvalue or at the end of the list if no tasks have a lower priority.
13282323455SDoug RabsonEnqueueing a task does not perform any memory allocation which makes
13382323455SDoug Rabsonit suitable for calling from an interrupt handler.
13482323455SDoug RabsonThis function will return
135b92a189eSRuslan Ermilov.Er EPIPE
13682323455SDoug Rabsonif the queue is being freed.
13782323455SDoug Rabson.Pp
13824b4e9d1SScott LongThe function
13924b4e9d1SScott Long.Fn taskqueue_enqueue_fast
14024b4e9d1SScott Longshould be used in place of
14124b4e9d1SScott Long.Fn taskqueue_enqueue
14224b4e9d1SScott Longwhen the enqueuing must happen from a fast interrupt handler.
14324b4e9d1SScott LongThis method uses spin locks to avoid the possibility of sleeping in the fast
14424b4e9d1SScott Longinterrupt context.
14524b4e9d1SScott Long.Pp
14682323455SDoug RabsonTo execute all the tasks on a queue,
14782323455SDoug Rabsoncall
1484c49b002SJoseph Koshy.Fn taskqueue_run
1494c49b002SJoseph Koshyor
1504c49b002SJoseph Koshy.Fn taskqueue_run_fast
1514c49b002SJoseph Koshydepending on the flavour of the queue.
15282323455SDoug RabsonWhen a task is executed,
15382323455SDoug Rabsonfirst it is removed from the queue,
15482323455SDoug Rabsonthe value of
15582323455SDoug Rabson.Va ta_pending
15682323455SDoug Rabsonis recorded and then the field is zeroed.
15782323455SDoug RabsonThe function
15882323455SDoug Rabson.Va ta_func
15982323455SDoug Rabsonfrom the task structure is called with the value of the field
16082323455SDoug Rabson.Va ta_context
16182323455SDoug Rabsonas its first argument
16282323455SDoug Rabsonand the value of
16382323455SDoug Rabson.Va ta_pending
16482323455SDoug Rabsonas its second argument.
165f616cf33SJohn-Mark GurneyAfter the function
166f616cf33SJohn-Mark Gurney.Va ta_func
167f616cf33SJohn-Mark Gurneyreturns,
168f616cf33SJohn-Mark Gurney.Xr wakeup 9
169f616cf33SJohn-Mark Gurneyis called on the task pointer passed to
170f616cf33SJohn-Mark Gurney.Fn taskqueue_enqueue .
17182323455SDoug Rabson.Pp
172fff7ff71SGleb SmirnoffThe
173fff7ff71SGleb Smirnoff.Fn taskqueue_drain
174fff7ff71SGleb Smirnofffunction is used to wait for the task to finish.
175fff7ff71SGleb SmirnoffThere is no guarantee that the task will not be
176fff7ff71SGleb Smirnoffenqueued after call to
177fff7ff71SGleb Smirnoff.Fn taskqueue_drain .
178fff7ff71SGleb Smirnoff.Pp
179159ef108SPawel Jakub DawidekThe
180159ef108SPawel Jakub Dawidek.Fn taskqueue_member
181159ef108SPawel Jakub Dawidekfunction returns
182159ef108SPawel Jakub Dawidek.No 1
1839c1a8ce4SPawel Jakub Dawidekif the given thread
184159ef108SPawel Jakub Dawidek.Fa td
185159ef108SPawel Jakub Dawidekis part of the given taskqeueue
186159ef108SPawel Jakub Dawidek.Fa queue
187159ef108SPawel Jakub Dawidekand
188159ef108SPawel Jakub Dawidek.No 0
189159ef108SPawel Jakub Dawidekotherwise.
190159ef108SPawel Jakub Dawidek.Pp
19182323455SDoug RabsonA convenience macro,
19282323455SDoug Rabson.Fn TASK_INIT "task" "priority" "func" "context"
19382323455SDoug Rabsonis provided to initialise a
19482323455SDoug Rabson.Va task
19582323455SDoug Rabsonstructure.
19682323455SDoug RabsonThe values of
19782323455SDoug Rabson.Va priority ,
19882323455SDoug Rabson.Va func ,
19982323455SDoug Rabsonand
20082323455SDoug Rabson.Va context
20182323455SDoug Rabsonare simply copied into the task structure fields and the
20282323455SDoug Rabson.Va ta_pending
20382323455SDoug Rabsonfield is cleared.
20482323455SDoug Rabson.Pp
2052eb30874SOleksandr TymoshenkoFive macros
206227559d1SJohn-Mark Gurney.Fn TASKQUEUE_DECLARE "name" ,
207227559d1SJohn-Mark Gurney.Fn TASKQUEUE_DEFINE "name" "enqueue" "context" "init" ,
2082eb30874SOleksandr Tymoshenko.Fn TASKQUEUE_FAST_DEFINE "name" "enqueue" "context" "init" ,
20982323455SDoug Rabsonand
210227559d1SJohn-Mark Gurney.Fn TASKQUEUE_DEFINE_THREAD "name"
2112eb30874SOleksandr Tymoshenko.Fn TASKQUEUE_FAST_DEFINE_THREAD "name"
212227559d1SJohn-Mark Gurneyare used to declare a reference to a global queue, to define the
213c0854fb7SRuslan Ermilovimplementation of the queue, and declare a queue that uses its own thread.
21482323455SDoug RabsonThe
21582323455SDoug Rabson.Fn TASKQUEUE_DEFINE
21682323455SDoug Rabsonmacro arranges to call
21782323455SDoug Rabson.Fn taskqueue_create
21882323455SDoug Rabsonwith the values of its
21982323455SDoug Rabson.Va name ,
22082323455SDoug Rabson.Va enqueue
22182323455SDoug Rabsonand
22282323455SDoug Rabson.Va context
22382323455SDoug Rabsonarguments during system initialisation.
22482323455SDoug RabsonAfter calling
22582323455SDoug Rabson.Fn taskqueue_create ,
22682323455SDoug Rabsonthe
22782323455SDoug Rabson.Va init
22882323455SDoug Rabsonargument to the macro is executed as a C statement,
22982323455SDoug Rabsonallowing any further initialisation to be performed
23082323455SDoug Rabson(such as registering an interrupt handler etc.)
23182323455SDoug Rabson.Pp
232227559d1SJohn-Mark GurneyThe
233227559d1SJohn-Mark Gurney.Fn TASKQUEUE_DEFINE_THREAD
234c0854fb7SRuslan Ermilovmacro defines a new taskqueue with its own kernel thread to serve tasks.
235c0854fb7SRuslan ErmilovThe variable
236227559d1SJohn-Mark Gurney.Vt struct taskqueue *taskqueue_name
237227559d1SJohn-Mark Gurneyis used to enqueue tasks onto the queue.
2382eb30874SOleksandr Tymoshenko.Pp
2392eb30874SOleksandr Tymoshenko.Fn TASKQUEUE_FAST_DEFINE
2402eb30874SOleksandr Tymoshenkoand
2412eb30874SOleksandr Tymoshenko.Fn TASKQUEUE_FAST_DEFINE_THREAD
2422eb30874SOleksandr Tymoshenkoact just like
2432eb30874SOleksandr Tymoshenko.Fn TASKQUEUE_DEFINE
2442eb30874SOleksandr Tymoshenkoand
2452eb30874SOleksandr Tymoshenko.Fn TASKQUEUE_DEFINE_THREAD
2462eb30874SOleksandr Tymoshenkorespectively but taskqueue is created with
2472eb30874SOleksandr Tymoshenko.Fn taskqueue_create_fast .
2484c49b002SJoseph Koshy.Ss Predefined Task Queues
2494c49b002SJoseph KoshyThe system provides four global taskqueues,
2504c49b002SJoseph Koshy.Va taskqueue_fast ,
25182323455SDoug Rabson.Va taskqueue_swi ,
252cb32189eSKenneth D. Merry.Va taskqueue_swi_giant ,
253cb32189eSKenneth D. Merryand
254cb32189eSKenneth D. Merry.Va taskqueue_thread .
2554c49b002SJoseph KoshyThe
2564c49b002SJoseph Koshy.Va taskqueue_fast
2574c49b002SJoseph Koshyqueue is for swi handlers dispatched from fast interrupt handlers,
2584c49b002SJoseph Koshywhere sleep mutexes cannot be used.
259cb32189eSKenneth D. MerryThe swi taskqueues are run via a software interrupt mechanism.
2604c49b002SJoseph KoshyThe
2614c49b002SJoseph Koshy.Va taskqueue_swi
2624c49b002SJoseph Koshyqueue runs without the protection of the
2634c49b002SJoseph Koshy.Va Giant
2644c49b002SJoseph Koshykernel lock, and the
2654c49b002SJoseph Koshy.Va taskqueue_swi_giant
2664c49b002SJoseph Koshyqueue runs with the protection of the
2674c49b002SJoseph Koshy.Va Giant
268cb32189eSKenneth D. Merrykernel lock.
2694c49b002SJoseph KoshyThe thread taskqueue
2704c49b002SJoseph Koshy.Va taskqueue_thread
2714c49b002SJoseph Koshyruns in a kernel thread context, and tasks run from this thread do
2724c49b002SJoseph Koshynot run under the
2734c49b002SJoseph Koshy.Va Giant
2744c49b002SJoseph Koshykernel lock.
2754c49b002SJoseph KoshyIf the caller wants to run under
2764c49b002SJoseph Koshy.Va Giant ,
2774c49b002SJoseph Koshyhe should explicitly acquire and release
2784c49b002SJoseph Koshy.Va Giant
2794c49b002SJoseph Koshyin his taskqueue handler routine.
280bf7f20c2SRuslan Ermilov.Pp
281cb32189eSKenneth D. MerryTo use these queues,
28282323455SDoug Rabsoncall
28382323455SDoug Rabson.Fn taskqueue_enqueue
284cb32189eSKenneth D. Merrywith the value of the global taskqueue variable for the queue you wish to
285c0854fb7SRuslan Ermilovuse
286c0854fb7SRuslan Ermilov.Va ( taskqueue_swi ,
287cb32189eSKenneth D. Merry.Va taskqueue_swi_giant ,
288cb32189eSKenneth D. Merryor
289c0854fb7SRuslan Ermilov.Va taskqueue_thread ) .
2904c49b002SJoseph KoshyUse
2914c49b002SJoseph Koshy.Fn taskqueue_enqueue_fast
2924c49b002SJoseph Koshyfor the global taskqueue variable
2934c49b002SJoseph Koshy.Va taskqueue_fast .
29482323455SDoug Rabson.Pp
295e0254f10SKenneth D. MerryThe software interrupt queues can be used,
29682323455SDoug Rabsonfor instance, for implementing interrupt handlers which must perform a
29782323455SDoug Rabsonsignificant amount of processing in the handler.
29882323455SDoug RabsonThe hardware interrupt handler would perform minimal processing of the
29982323455SDoug Rabsoninterrupt and then enqueue a task to finish the work.
30082323455SDoug RabsonThis reduces to a minimum
30182323455SDoug Rabsonthe amount of time spent with interrupts disabled.
302cb32189eSKenneth D. Merry.Pp
303cb32189eSKenneth D. MerryThe thread queue can be used, for instance, by interrupt level routines
304cb32189eSKenneth D. Merrythat need to call kernel functions that do things that can only be done
305cb32189eSKenneth D. Merryfrom a thread context.
306cb32189eSKenneth D. Merry(e.g., call malloc with the M_WAITOK flag.)
307cf82599dSSam Leffler.Pp
308cf82599dSSam LefflerNote that tasks queued on shared taskqueues such as
309cf82599dSSam Leffler.Va taskqueue_swi
310cf82599dSSam Lefflermay be delayed an indeterminate amount of time before execution.
311cf82599dSSam LefflerIf queueing delays cannot be tolerated then a private taskqueue should
312cf82599dSSam Lefflerbe created with a dedicated processing thread.
3133bbf58f9SJoseph Koshy.Sh SEE ALSO
3143bbf58f9SJoseph Koshy.Xr ithread 9 ,
3153bbf58f9SJoseph Koshy.Xr kthread 9 ,
3163bbf58f9SJoseph Koshy.Xr swi 9
31782323455SDoug Rabson.Sh HISTORY
31882323455SDoug RabsonThis interface first appeared in
31982323455SDoug Rabson.Fx 5.0 .
32082323455SDoug RabsonThere is a similar facility called tqueue in the Linux kernel.
32182323455SDoug Rabson.Sh AUTHORS
322571dba6eSHiten PandyaThis manual page was written by
32382323455SDoug Rabson.An Doug Rabson .
324