xref: /dragonfly/sys/dev/drm/include/linux/workqueue.h (revision c17dd299)
196b26154SFrançois Tigeot /*
2d8609fe4SFrançois Tigeot  * Copyright (c) 2010 Isilon Systems, Inc.
3d8609fe4SFrançois Tigeot  * Copyright (c) 2010 iX Systems, Inc.
4d8609fe4SFrançois Tigeot  * Copyright (c) 2010 Panasas, Inc.
5516c440cSFrançois Tigeot  * Copyright (c) 2013, 2014 Mellanox Technologies, Ltd.
6e470c808SFrançois Tigeot  * Copyright (c) 2014-2020 François Tigeot <ftigeot@wolfpond.org>
7d8609fe4SFrançois Tigeot  * All rights reserved.
8d8609fe4SFrançois Tigeot  *
9d8609fe4SFrançois Tigeot  * Redistribution and use in source and binary forms, with or without
10d8609fe4SFrançois Tigeot  * modification, are permitted provided that the following conditions
11d8609fe4SFrançois Tigeot  * are met:
12d8609fe4SFrançois Tigeot  * 1. Redistributions of source code must retain the above copyright
13d8609fe4SFrançois Tigeot  *    notice unmodified, this list of conditions, and the following
14d8609fe4SFrançois Tigeot  *    disclaimer.
15d8609fe4SFrançois Tigeot  * 2. Redistributions in binary form must reproduce the above copyright
16d8609fe4SFrançois Tigeot  *    notice, this list of conditions and the following disclaimer in the
17d8609fe4SFrançois Tigeot  *    documentation and/or other materials provided with the distribution.
18d8609fe4SFrançois Tigeot  *
19d8609fe4SFrançois Tigeot  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20d8609fe4SFrançois Tigeot  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21d8609fe4SFrançois Tigeot  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22d8609fe4SFrançois Tigeot  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23d8609fe4SFrançois Tigeot  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24d8609fe4SFrançois Tigeot  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25d8609fe4SFrançois Tigeot  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26d8609fe4SFrançois Tigeot  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27d8609fe4SFrançois Tigeot  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28d8609fe4SFrançois Tigeot  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29d8609fe4SFrançois Tigeot  */
30d8609fe4SFrançois Tigeot #ifndef	_LINUX_WORKQUEUE_H_
31d8609fe4SFrançois Tigeot #define	_LINUX_WORKQUEUE_H_
32d8609fe4SFrançois Tigeot 
33d8609fe4SFrançois Tigeot #include <linux/timer.h>
34d6aa1cc5SFrançois Tigeot #include <linux/bitops.h>
35961a6190SFrançois Tigeot #include <linux/lockdep.h>
36d6aa1cc5SFrançois Tigeot #include <linux/atomic.h>
37d6aa1cc5SFrançois Tigeot #include <linux/cpumask.h>
38d8609fe4SFrançois Tigeot 
39*c17dd299SFrançois Tigeot #define WQ_HIGHPRI	1
40*c17dd299SFrançois Tigeot #define WQ_UNBOUND	2
41d8609fe4SFrançois Tigeot 
42*c17dd299SFrançois Tigeot struct workqueue_worker;
43d8609fe4SFrançois Tigeot 
44d8609fe4SFrançois Tigeot struct work_struct {
45*c17dd299SFrançois Tigeot 	STAILQ_ENTRY(work_struct) ws_entries;
46341b570dSFrançois Tigeot 	void	(*func)(struct work_struct *);
47*c17dd299SFrançois Tigeot 	struct workqueue_worker *worker;
48*c17dd299SFrançois Tigeot 	bool	on_queue;
49*c17dd299SFrançois Tigeot 	bool	running;
50*c17dd299SFrançois Tigeot 	bool	canceled;
51*c17dd299SFrançois Tigeot };
52*c17dd299SFrançois Tigeot 
53*c17dd299SFrançois Tigeot struct workqueue_worker {
54*c17dd299SFrançois Tigeot 	STAILQ_HEAD(ws_list, work_struct) ws_list_head;
55*c17dd299SFrançois Tigeot 	struct thread *worker_thread;
56*c17dd299SFrançois Tigeot 	struct lock worker_lock;
57*c17dd299SFrançois Tigeot };
58*c17dd299SFrançois Tigeot 
59*c17dd299SFrançois Tigeot struct workqueue_struct {
60*c17dd299SFrançois Tigeot 	bool	is_draining;
61*c17dd299SFrançois Tigeot 	int	num_workers;
62*c17dd299SFrançois Tigeot 	struct	workqueue_worker (*workers)[];
63d8609fe4SFrançois Tigeot };
64d8609fe4SFrançois Tigeot 
65d8609fe4SFrançois Tigeot struct delayed_work {
66d8609fe4SFrançois Tigeot 	struct work_struct	work;
67d8609fe4SFrançois Tigeot 	struct callout		timer;
68d8609fe4SFrançois Tigeot };
69d8609fe4SFrançois Tigeot 
70d8609fe4SFrançois Tigeot static inline struct delayed_work *
to_delayed_work(struct work_struct * work)71d8609fe4SFrançois Tigeot to_delayed_work(struct work_struct *work)
72d8609fe4SFrançois Tigeot {
73d8609fe4SFrançois Tigeot 
74d8609fe4SFrançois Tigeot 	return container_of(work, struct delayed_work, work);
75d8609fe4SFrançois Tigeot }
76d8609fe4SFrançois Tigeot 
77341b570dSFrançois Tigeot #define INIT_WORK(work, _func) 		 	\
78d8609fe4SFrançois Tigeot do {						\
79*c17dd299SFrançois Tigeot 	(work)->ws_entries.stqe_next = NULL;	\
80341b570dSFrançois Tigeot 	(work)->func = (_func);			\
81*c17dd299SFrançois Tigeot 	(work)->on_queue = false;		\
82*c17dd299SFrançois Tigeot 	(work)->running = false;		\
83*c17dd299SFrançois Tigeot 	(work)->canceled = false;		\
84d8609fe4SFrançois Tigeot } while (0)
85d8609fe4SFrançois Tigeot 
86341b570dSFrançois Tigeot #define INIT_WORK_ONSTACK(work, _func)	INIT_WORK(work, _func)
876de42543SFrançois Tigeot 
88341b570dSFrançois Tigeot #define INIT_DELAYED_WORK(_work, _func)					\
89d8609fe4SFrançois Tigeot do {									\
90341b570dSFrançois Tigeot 	INIT_WORK(&(_work)->work, _func);				\
91b09aaaa1SFrançois Tigeot 	callout_init_mp(&(_work)->timer);				\
92d8609fe4SFrançois Tigeot } while (0)
93d8609fe4SFrançois Tigeot 
94*c17dd299SFrançois Tigeot #define INIT_DELAYED_WORK_ONSTACK(work, _func)	INIT_DELAYED_WORK(work, _func)
956de42543SFrançois Tigeot 
96df8db295SFrançois Tigeot /* System-wide workqueues */
97df8db295SFrançois Tigeot extern struct workqueue_struct *system_wq;
982cecdd68SFrançois Tigeot extern struct workqueue_struct *system_highpri_wq;
99df8db295SFrançois Tigeot extern struct workqueue_struct *system_long_wq;
10096b26154SFrançois Tigeot extern struct workqueue_struct *system_unbound_wq;
1012cecdd68SFrançois Tigeot extern struct workqueue_struct *system_power_efficient_wq;
102df8db295SFrançois Tigeot 
103*c17dd299SFrançois Tigeot #define alloc_ordered_workqueue(name, flags) \
104*c17dd299SFrançois Tigeot 	_create_workqueue_common(name, (flags) | WQ_UNBOUND)
1052995d677SFrançois Tigeot 
106*c17dd299SFrançois Tigeot #define alloc_workqueue(name, flags, max_active) \
107*c17dd299SFrançois Tigeot 	_create_workqueue_common(name, flags)
1085dfe0225SFrançois Tigeot 
109*c17dd299SFrançois Tigeot #define create_singlethread_workqueue(name) \
110*c17dd299SFrançois Tigeot 	_create_workqueue_common(name, WQ_UNBOUND)
111*c17dd299SFrançois Tigeot 
112*c17dd299SFrançois Tigeot struct workqueue_struct *_create_workqueue_common(const char *name, int flags);
113*c17dd299SFrançois Tigeot 
114*c17dd299SFrançois Tigeot int queue_work(struct workqueue_struct *wq, struct work_struct *work);
115*c17dd299SFrançois Tigeot int queue_delayed_work(struct workqueue_struct *wq, struct delayed_work *work,
116*c17dd299SFrançois Tigeot     unsigned long delay);
1175ef31fe9SFrançois Tigeot 
118e470c808SFrançois Tigeot static inline bool
schedule_work(struct work_struct * work)119*c17dd299SFrançois Tigeot schedule_work(struct work_struct *work)
120e470c808SFrançois Tigeot {
121*c17dd299SFrançois Tigeot 	return queue_work(system_wq, work);
122e470c808SFrançois Tigeot }
123e470c808SFrançois Tigeot 
schedule_delayed_work(struct delayed_work * dwork,unsigned long delay)124*c17dd299SFrançois Tigeot static inline bool schedule_delayed_work(struct delayed_work *dwork,
125*c17dd299SFrançois Tigeot                                          unsigned long delay)
126*c17dd299SFrançois Tigeot {
127*c17dd299SFrançois Tigeot         return queue_delayed_work(system_wq, dwork, delay);
128*c17dd299SFrançois Tigeot }
129*c17dd299SFrançois Tigeot 
130*c17dd299SFrançois Tigeot bool cancel_work_sync(struct work_struct *work);
131*c17dd299SFrançois Tigeot bool cancel_delayed_work(struct delayed_work *dwork);
132*c17dd299SFrançois Tigeot bool cancel_delayed_work_sync(struct delayed_work *dwork);
133*c17dd299SFrançois Tigeot 
134*c17dd299SFrançois Tigeot /* XXX: Return value not used in drm code */
135*c17dd299SFrançois Tigeot static inline bool
mod_delayed_work(struct workqueue_struct * wq,struct delayed_work * dwork,unsigned long delay)136*c17dd299SFrançois Tigeot mod_delayed_work(struct workqueue_struct *wq,
137*c17dd299SFrançois Tigeot 		 struct delayed_work *dwork, unsigned long delay)
138*c17dd299SFrançois Tigeot {
139*c17dd299SFrançois Tigeot 	cancel_delayed_work(dwork);
140*c17dd299SFrançois Tigeot 	queue_delayed_work(wq, dwork, delay);
141*c17dd299SFrançois Tigeot 	return false;
142*c17dd299SFrançois Tigeot }
143*c17dd299SFrançois Tigeot 
144*c17dd299SFrançois Tigeot void drain_workqueue(struct workqueue_struct *wq);
145*c17dd299SFrançois Tigeot void flush_workqueue(struct workqueue_struct *wq);
146*c17dd299SFrançois Tigeot 
147*c17dd299SFrançois Tigeot bool flush_work(struct work_struct *work);
148*c17dd299SFrançois Tigeot bool flush_delayed_work(struct delayed_work *dwork);
149*c17dd299SFrançois Tigeot 
150*c17dd299SFrançois Tigeot static inline void
flush_scheduled_work(void)151*c17dd299SFrançois Tigeot flush_scheduled_work(void)
152*c17dd299SFrançois Tigeot {
153*c17dd299SFrançois Tigeot 	flush_workqueue(system_wq);
154*c17dd299SFrançois Tigeot }
155*c17dd299SFrançois Tigeot 
156*c17dd299SFrançois Tigeot unsigned int work_busy(struct work_struct *work);
157*c17dd299SFrançois Tigeot bool work_pending(struct work_struct *work);
158*c17dd299SFrançois Tigeot 
159*c17dd299SFrançois Tigeot bool delayed_work_pending(struct delayed_work *dw);
160*c17dd299SFrançois Tigeot 
161*c17dd299SFrançois Tigeot void destroy_workqueue(struct workqueue_struct *wq);
162*c17dd299SFrançois Tigeot 
163*c17dd299SFrançois Tigeot void destroy_work_on_stack(struct work_struct *work);
164*c17dd299SFrançois Tigeot 
165*c17dd299SFrançois Tigeot void destroy_delayed_work_on_stack(struct delayed_work *work);
166*c17dd299SFrançois Tigeot 
167d8609fe4SFrançois Tigeot #endif	/* _LINUX_WORKQUEUE_H_ */
168