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