1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef INTERNAL_IO_SLIST_H
3 #define INTERNAL_IO_SLIST_H
4
5 #include <linux/io_uring_types.h>
6
7 #define __wq_list_for_each(pos, head) \
8 for (pos = (head)->first; pos; pos = (pos)->next)
9
10 #define wq_list_for_each(pos, prv, head) \
11 for (pos = (head)->first, prv = NULL; pos; prv = pos, pos = (pos)->next)
12
13 #define wq_list_empty(list) (READ_ONCE((list)->first) == NULL)
14
15 #define INIT_WQ_LIST(list) do { \
16 (list)->first = NULL; \
17 } while (0)
18
wq_list_add_after(struct io_wq_work_node * node,struct io_wq_work_node * pos,struct io_wq_work_list * list)19 static inline void wq_list_add_after(struct io_wq_work_node *node,
20 struct io_wq_work_node *pos,
21 struct io_wq_work_list *list)
22 {
23 struct io_wq_work_node *next = pos->next;
24
25 pos->next = node;
26 node->next = next;
27 if (!next)
28 list->last = node;
29 }
30
wq_list_add_tail(struct io_wq_work_node * node,struct io_wq_work_list * list)31 static inline void wq_list_add_tail(struct io_wq_work_node *node,
32 struct io_wq_work_list *list)
33 {
34 node->next = NULL;
35 if (!list->first) {
36 list->last = node;
37 WRITE_ONCE(list->first, node);
38 } else {
39 list->last->next = node;
40 list->last = node;
41 }
42 }
43
wq_list_cut(struct io_wq_work_list * list,struct io_wq_work_node * last,struct io_wq_work_node * prev)44 static inline void wq_list_cut(struct io_wq_work_list *list,
45 struct io_wq_work_node *last,
46 struct io_wq_work_node *prev)
47 {
48 /* first in the list, if prev==NULL */
49 if (!prev)
50 WRITE_ONCE(list->first, last->next);
51 else
52 prev->next = last->next;
53
54 if (last == list->last)
55 list->last = prev;
56 last->next = NULL;
57 }
58
wq_stack_add_head(struct io_wq_work_node * node,struct io_wq_work_node * stack)59 static inline void wq_stack_add_head(struct io_wq_work_node *node,
60 struct io_wq_work_node *stack)
61 {
62 node->next = stack->next;
63 stack->next = node;
64 }
65
wq_list_del(struct io_wq_work_list * list,struct io_wq_work_node * node,struct io_wq_work_node * prev)66 static inline void wq_list_del(struct io_wq_work_list *list,
67 struct io_wq_work_node *node,
68 struct io_wq_work_node *prev)
69 {
70 wq_list_cut(list, node, prev);
71 }
72
73 static inline
wq_stack_extract(struct io_wq_work_node * stack)74 struct io_wq_work_node *wq_stack_extract(struct io_wq_work_node *stack)
75 {
76 struct io_wq_work_node *node = stack->next;
77
78 stack->next = node->next;
79 return node;
80 }
81
wq_next_work(struct io_wq_work * work)82 static inline struct io_wq_work *wq_next_work(struct io_wq_work *work)
83 {
84 if (!work->list.next)
85 return NULL;
86
87 return container_of(work->list.next, struct io_wq_work, list);
88 }
89
90 #endif // INTERNAL_IO_SLIST_H
91