1 | #ifndef INTERNAL_IO_SLIST_H |
2 | #define INTERNAL_IO_SLIST_H |
3 | |
4 | #include <linux/io_uring_types.h> |
5 | |
6 | #define __wq_list_for_each(pos, head) \ |
7 | for (pos = (head)->first; pos; pos = (pos)->next) |
8 | |
9 | #define wq_list_for_each(pos, prv, head) \ |
10 | for (pos = (head)->first, prv = NULL; pos; prv = pos, pos = (pos)->next) |
11 | |
12 | #define wq_list_for_each_resume(pos, prv) \ |
13 | for (; pos; prv = pos, pos = (pos)->next) |
14 | |
15 | #define wq_list_empty(list) (READ_ONCE((list)->first) == NULL) |
16 | |
17 | #define INIT_WQ_LIST(list) do { \ |
18 | (list)->first = NULL; \ |
19 | } while (0) |
20 | |
21 | static inline void wq_list_add_after(struct io_wq_work_node *node, |
22 | struct io_wq_work_node *pos, |
23 | struct io_wq_work_list *list) |
24 | { |
25 | struct io_wq_work_node *next = pos->next; |
26 | |
27 | pos->next = node; |
28 | node->next = next; |
29 | if (!next) |
30 | list->last = node; |
31 | } |
32 | |
33 | static inline void wq_list_add_tail(struct io_wq_work_node *node, |
34 | struct io_wq_work_list *list) |
35 | { |
36 | node->next = NULL; |
37 | if (!list->first) { |
38 | list->last = node; |
39 | WRITE_ONCE(list->first, node); |
40 | } else { |
41 | list->last->next = node; |
42 | list->last = node; |
43 | } |
44 | } |
45 | |
46 | static inline void wq_list_add_head(struct io_wq_work_node *node, |
47 | struct io_wq_work_list *list) |
48 | { |
49 | node->next = list->first; |
50 | if (!node->next) |
51 | list->last = node; |
52 | WRITE_ONCE(list->first, node); |
53 | } |
54 | |
55 | static inline void wq_list_cut(struct io_wq_work_list *list, |
56 | struct io_wq_work_node *last, |
57 | struct io_wq_work_node *prev) |
58 | { |
59 | /* first in the list, if prev==NULL */ |
60 | if (!prev) |
61 | WRITE_ONCE(list->first, last->next); |
62 | else |
63 | prev->next = last->next; |
64 | |
65 | if (last == list->last) |
66 | list->last = prev; |
67 | last->next = NULL; |
68 | } |
69 | |
70 | static inline void __wq_list_splice(struct io_wq_work_list *list, |
71 | struct io_wq_work_node *to) |
72 | { |
73 | list->last->next = to->next; |
74 | to->next = list->first; |
75 | INIT_WQ_LIST(list); |
76 | } |
77 | |
78 | static inline bool wq_list_splice(struct io_wq_work_list *list, |
79 | struct io_wq_work_node *to) |
80 | { |
81 | if (!wq_list_empty(list)) { |
82 | __wq_list_splice(list, to); |
83 | return true; |
84 | } |
85 | return false; |
86 | } |
87 | |
88 | static inline void wq_stack_add_head(struct io_wq_work_node *node, |
89 | struct io_wq_work_node *stack) |
90 | { |
91 | node->next = stack->next; |
92 | stack->next = node; |
93 | } |
94 | |
95 | static inline void wq_list_del(struct io_wq_work_list *list, |
96 | struct io_wq_work_node *node, |
97 | struct io_wq_work_node *prev) |
98 | { |
99 | wq_list_cut(list, last: node, prev); |
100 | } |
101 | |
102 | static inline |
103 | struct io_wq_work_node *(struct io_wq_work_node *stack) |
104 | { |
105 | struct io_wq_work_node *node = stack->next; |
106 | |
107 | stack->next = node->next; |
108 | return node; |
109 | } |
110 | |
111 | static inline struct io_wq_work *wq_next_work(struct io_wq_work *work) |
112 | { |
113 | if (!work->list.next) |
114 | return NULL; |
115 | |
116 | return container_of(work->list.next, struct io_wq_work, list); |
117 | } |
118 | |
119 | #endif // INTERNAL_IO_SLIST_H |
120 | |