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