xref: /freebsd/share/man/man9/taskqueue.9 (revision 7660b554bc59a07be0431c17e0e33815818baa69)
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