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