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