xref: /openbmc/linux/io_uring/slist.h (revision fa780334)
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