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