xref: /freebsd/share/man/man9/taskqueue.9 (revision 6b3455a7665208c366849f0b2b3bc916fb97516e)
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.Ed
56.Ft struct taskqueue *
57.Fn taskqueue_create "const char *name" "int mflags" "taskqueue_enqueue_fn enqueue" "void *context"
58.Ft void
59.Fn taskqueue_free "struct taskqueue *queue"
60.Ft struct taskqueue *
61.Fn taskqueue_find "const char *name"
62.Ft int
63.Fn taskqueue_enqueue "struct taskqueue *queue" "struct task *task"
64.Ft int
65.Fn taskqueue_enqueue_fast "struct taskqueue *queue" "struct task *task"
66.Ft void
67.Fn taskqueue_run "struct taskqueue *queue"
68.Fn TASK_INIT "struct task *task" "int priority" "task_fn_t *func" "void *context"
69.Fn TASKQUEUE_DECLARE "name"
70.Fn TASKQUEUE_DEFINE "name" "taskqueue_enqueue_fn enqueue" "void *context" "init"
71.Sh DESCRIPTION
72These functions provide a simple interface for asynchronous execution
73of code.
74.Pp
75The function
76.Fn taskqueue_create
77is used to create new queues.
78The arguments to
79.Fn taskqueue_create
80include a name which should be unique,
81a set of
82.Xr malloc 9
83flags which specify whether the call to
84.Fn malloc
85is allowed to sleep
86and a function which is called from
87.Fn taskqueue_enqueue
88when a task is added to the queue
89.\" XXX	The rest of the sentence gets lots in relation to the first part.
90to allow the queue to arrange to be run later
91(for instance by scheduling a software interrupt or waking a kernel
92thread).
93.Pp
94The function
95.Fn taskqueue_free
96should be used to remove the queue from the global list of queues
97and free the memory used by the queue.
98Any tasks which are on the queue will be executed at this time.
99.Pp
100The system maintains a list of all queues which can be searched using
101.Fn taskqueue_find .
102The first queue whose name matches is returned, otherwise
103.Dv NULL .
104.Pp
105To add a task to the list of tasks queued on a taskqueue, call
106.Fn taskqueue_enqueue
107with pointers to the queue and task.
108If the task's
109.Va ta_pending
110field is non-zero,
111then it is simply incremented to reflect the number of times the task
112was enqueued.
113Otherwise,
114the task is added to the list before the first task which has a lower
115.Va ta_priority
116value or at the end of the list if no tasks have a lower priority.
117Enqueueing a task does not perform any memory allocation which makes
118it suitable for calling from an interrupt handler.
119This function will return
120.Er EPIPE
121if the queue is being freed.
122.Pp
123The function
124.Fn taskqueue_enqueue_fast
125should be used in place of
126.Fn taskqueue_enqueue
127when the enqueuing must happen from a fast interrupt handler.
128This method uses spin locks to avoid the possibility of sleeping in the fast
129interrupt context.
130.Pp
131To execute all the tasks on a queue,
132call
133.Fn taskqueue_run .
134When a task is executed,
135first it is removed from the queue,
136the value of
137.Va ta_pending
138is recorded and then the field is zeroed.
139The function
140.Va ta_func
141from the task structure is called with the value of the field
142.Va ta_context
143as its first argument
144and the value of
145.Va ta_pending
146as its second argument.
147.Pp
148A convenience macro,
149.Fn TASK_INIT "task" "priority" "func" "context"
150is provided to initialise a
151.Va task
152structure.
153The values of
154.Va priority ,
155.Va func ,
156and
157.Va context
158are simply copied into the task structure fields and the
159.Va ta_pending
160field is cleared.
161.Pp
162Two macros
163.Fn TASKQUEUE_DECLARE "name"
164and
165.Fn TASKQUEUE_DEFINE "name" "enqueue" "context" "init"
166are used to declare a reference to a global queue
167and to define the implementation of the queue.
168The
169.Fn TASKQUEUE_DEFINE
170macro arranges to call
171.Fn taskqueue_create
172with the values of its
173.Va name ,
174.Va enqueue
175and
176.Va context
177arguments during system initialisation.
178After calling
179.Fn taskqueue_create ,
180the
181.Va init
182argument to the macro is executed as a C statement,
183allowing any further initialisation to be performed
184(such as registering an interrupt handler etc.)
185.Pp
186The system provides three global taskqueues,
187.Va taskqueue_swi ,
188.Va taskqueue_swi_giant ,
189and
190.Va taskqueue_thread .
191The swi taskqueues are run via a software interrupt mechanism.
192The taskqueue_swi queue runs without the protection of the Giant kernel lock,
193and the taskqueue_swi_giant queue runs with the protection of the Giant
194kernel lock.
195The thread taskqueue runs in a kernel thread context, and tasks run from
196this thread do not run under the Giant kernel lock.
197If the caller wants to run under Giant, he should explicitly acquire and
198release Giant in his taskqueue handler routine.
199.Pp
200To use these queues,
201call
202.Fn taskqueue_enqueue
203with the value of the global taskqueue variable for the queue you wish to
204use (
205.Va taskqueue_swi ,
206.Va taskqueue_swi_giant ,
207or
208.Va taskqueue_thread
209).
210.Pp
211The software interrupt queues can be used,
212for instance, for implementing interrupt handlers which must perform a
213significant amount of processing in the handler.
214The hardware interrupt handler would perform minimal processing of the
215interrupt and then enqueue a task to finish the work.
216This reduces to a minimum
217the amount of time spent with interrupts disabled.
218.Pp
219The thread queue can be used, for instance, by interrupt level routines
220that need to call kernel functions that do things that can only be done
221from a thread context.
222(e.g., call malloc with the M_WAITOK flag.)
223.Sh HISTORY
224This interface first appeared in
225.Fx 5.0 .
226There is a similar facility called tqueue in the Linux kernel.
227.Sh AUTHORS
228This man page was written by
229.An Doug Rabson .
230