1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2014 Jeffrey Roberson <jeff@freebsd.org>
5 * Copyright (c) 2016 Matthew Macy <mmacy@mattmacy.io>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
30#ifndef _SYS_GTASKQUEUE_H_
31#define _SYS_GTASKQUEUE_H_
32
33#ifndef _KERNEL
34#error "no user-serviceable parts inside"
35#endif
36
37#include <sys/_task.h>
38#include <sys/bus.h>
39#include <sys/taskqueue.h>
40#include <sys/types.h>
41
42struct gtaskqueue;
43
44/*
45 * Taskqueue groups.  Manages dynamic thread groups and irq binding for
46 * device and other tasks.
47 */
48
49struct grouptask {
50	struct gtask		gt_task;
51	void			*gt_taskqueue;
52	LIST_ENTRY(grouptask)	gt_list;
53	void			*gt_uniq;
54#define	GROUPTASK_NAMELEN	32
55	char			gt_name[GROUPTASK_NAMELEN];
56	device_t		gt_dev;
57	struct resource		*gt_irq;
58	int			gt_cpu;
59};
60
61void	gtaskqueue_block(struct gtaskqueue *queue);
62void	gtaskqueue_unblock(struct gtaskqueue *queue);
63
64int	gtaskqueue_cancel(struct gtaskqueue *queue, struct gtask *gtask);
65void	gtaskqueue_drain(struct gtaskqueue *queue, struct gtask *task);
66void	gtaskqueue_drain_all(struct gtaskqueue *queue);
67
68void	grouptask_block(struct grouptask *grouptask);
69void	grouptask_unblock(struct grouptask *grouptask);
70int	grouptaskqueue_enqueue(struct gtaskqueue *queue, struct gtask *task);
71
72void	taskqgroup_attach(struct taskqgroup *qgroup, struct grouptask *grptask,
73	    void *uniq, device_t dev, struct resource *irq, const char *name);
74int	taskqgroup_attach_cpu(struct taskqgroup *qgroup,
75	    struct grouptask *grptask, void *uniq, int cpu, device_t dev,
76	    struct resource *irq, const char *name);
77void	taskqgroup_detach(struct taskqgroup *qgroup, struct grouptask *gtask);
78struct taskqgroup *taskqgroup_create(const char *name, int cnt, int stride);
79void	taskqgroup_destroy(struct taskqgroup *qgroup);
80void	taskqgroup_bind(struct taskqgroup *qgroup);
81void	taskqgroup_drain_all(struct taskqgroup *qgroup);
82
83#define	GTASK_INIT(gtask, flags, priority, func, context) do {	\
84	(gtask)->ta_flags = flags;				\
85	(gtask)->ta_priority = (priority);			\
86	(gtask)->ta_func = (func);				\
87	(gtask)->ta_context = (context);			\
88} while (0)
89
90#define	GROUPTASK_INIT(gtask, priority, func, context)	\
91	GTASK_INIT(&(gtask)->gt_task, 0, priority, func, context)
92
93#define	GROUPTASK_ENQUEUE(gtask)			\
94	grouptaskqueue_enqueue((gtask)->gt_taskqueue, &(gtask)->gt_task)
95
96#define TASKQGROUP_DECLARE(name)			\
97extern struct taskqgroup *qgroup_##name
98
99#define TASKQGROUP_DEFINE(name, cnt, stride)				\
100									\
101struct taskqgroup *qgroup_##name;					\
102									\
103static void								\
104taskqgroup_define_##name(void *arg)					\
105{									\
106	qgroup_##name = taskqgroup_create(#name, (cnt), (stride));	\
107}									\
108SYSINIT(taskqgroup_##name, SI_SUB_TASKQ, SI_ORDER_FIRST,		\
109    taskqgroup_define_##name, NULL);					\
110									\
111static void								\
112taskqgroup_bind_##name(void *arg)					\
113{									\
114	taskqgroup_bind(qgroup_##name);					\
115}									\
116SYSINIT(taskqgroup_bind_##name, SI_SUB_SMP, SI_ORDER_ANY,		\
117    taskqgroup_bind_##name, NULL)
118
119TASKQGROUP_DECLARE(softirq);
120
121#endif /* !_SYS_GTASKQUEUE_H_ */
122