1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef INTERNAL_IO_WQ_H
3 #define INTERNAL_IO_WQ_H
4
5 #include <linux/refcount.h>
6 #include <linux/io_uring_types.h>
7
8 struct io_wq;
9
10 enum {
11 IO_WQ_WORK_CANCEL = 1,
12 IO_WQ_WORK_HASHED = 2,
13 IO_WQ_WORK_UNBOUND = 4,
14 IO_WQ_WORK_CONCURRENT = 16,
15
16 IO_WQ_HASH_SHIFT = 24, /* upper 8 bits are used for hash key */
17 };
18
19 enum io_wq_cancel {
20 IO_WQ_CANCEL_OK, /* cancelled before started */
21 IO_WQ_CANCEL_RUNNING, /* found, running, and attempted cancelled */
22 IO_WQ_CANCEL_NOTFOUND, /* work not found */
23 };
24
25 struct io_wq_hash {
26 refcount_t refs;
27 unsigned long map;
28 struct wait_queue_head wait;
29 };
30
io_wq_put_hash(struct io_wq_hash * hash)31 static inline void io_wq_put_hash(struct io_wq_hash *hash)
32 {
33 if (refcount_dec_and_test(&hash->refs))
34 kfree(hash);
35 }
36
37 struct io_wq_data {
38 struct io_wq_hash *hash;
39 struct task_struct *task;
40 };
41
42 struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data);
43 void io_wq_exit_start(struct io_wq *wq);
44 void io_wq_put_and_exit(struct io_wq *wq);
45 void io_wq_set_exit_on_idle(struct io_wq *wq, bool enable);
46
47 void io_wq_enqueue(struct io_wq *wq, struct io_wq_work *work);
48 void io_wq_hash_work(struct io_wq_work *work, void *val);
49
50 int io_wq_cpu_affinity(struct io_uring_task *tctx, cpumask_var_t mask);
51 int io_wq_max_workers(struct io_wq *wq, int *new_count);
52 bool io_wq_worker_stopped(void);
53
__io_wq_is_hashed(unsigned int work_flags)54 static inline bool __io_wq_is_hashed(unsigned int work_flags)
55 {
56 return work_flags & IO_WQ_WORK_HASHED;
57 }
58
io_wq_is_hashed(struct io_wq_work * work)59 static inline bool io_wq_is_hashed(struct io_wq_work *work)
60 {
61 return __io_wq_is_hashed(atomic_read(&work->flags));
62 }
63
64 typedef bool (work_cancel_fn)(struct io_wq_work *, void *);
65
66 enum io_wq_cancel io_wq_cancel_cb(struct io_wq *wq, work_cancel_fn *cancel,
67 void *data, bool cancel_all);
68
69 #if defined(CONFIG_IO_WQ)
70 extern void io_wq_worker_sleeping(struct task_struct *);
71 extern void io_wq_worker_running(struct task_struct *);
72 #else
io_wq_worker_sleeping(struct task_struct * tsk)73 static inline void io_wq_worker_sleeping(struct task_struct *tsk)
74 {
75 }
io_wq_worker_running(struct task_struct * tsk)76 static inline void io_wq_worker_running(struct task_struct *tsk)
77 {
78 }
79 #endif
80
io_wq_current_is_worker(void)81 static inline bool io_wq_current_is_worker(void)
82 {
83 return in_task() && (current->flags & PF_IO_WORKER) &&
84 current->worker_private;
85 }
86 #endif
87