1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef INTERNAL_IO_SLIST_H 3 #define INTERNAL_IO_SLIST_H 4 5 #include <linux/io_uring_types.h> 6 7 #define __wq_list_for_each(pos, head) \ 8 for (pos = (head)->first; pos; pos = (pos)->next) 9 10 #define wq_list_for_each(pos, prv, head) \ 11 for (pos = (head)->first, prv = NULL; pos; prv = pos, pos = (pos)->next) 12 13 #define wq_list_empty(list) (READ_ONCE((list)->first) == NULL) 14 15 #define INIT_WQ_LIST(list) do { \ 16 (list)->first = NULL; \ 17 } while (0) 18 19 static inline void wq_list_add_after(struct io_wq_work_node *node, 20 struct io_wq_work_node *pos, 21 struct io_wq_work_list *list) 22 { 23 struct io_wq_work_node *next = pos->next; 24 25 pos->next = node; 26 node->next = next; 27 if (!next) 28 list->last = node; 29 } 30 31 static inline void wq_list_add_tail(struct io_wq_work_node *node, 32 struct io_wq_work_list *list) 33 { 34 node->next = NULL; 35 if (!list->first) { 36 list->last = node; 37 WRITE_ONCE(list->first, node); 38 } else { 39 list->last->next = node; 40 list->last = node; 41 } 42 } 43 44 static inline void wq_list_cut(struct io_wq_work_list *list, 45 struct io_wq_work_node *last, 46 struct io_wq_work_node *prev) 47 { 48 /* first in the list, if prev==NULL */ 49 if (!prev) 50 WRITE_ONCE(list->first, last->next); 51 else 52 prev->next = last->next; 53 54 if (last == list->last) 55 list->last = prev; 56 last->next = NULL; 57 } 58 59 static inline void wq_stack_add_head(struct io_wq_work_node *node, 60 struct io_wq_work_node *stack) 61 { 62 node->next = stack->next; 63 stack->next = node; 64 } 65 66 static inline void wq_list_del(struct io_wq_work_list *list, 67 struct io_wq_work_node *node, 68 struct io_wq_work_node *prev) 69 { 70 wq_list_cut(list, node, prev); 71 } 72 73 static inline 74 struct io_wq_work_node *wq_stack_extract(struct io_wq_work_node *stack) 75 { 76 struct io_wq_work_node *node = stack->next; 77 78 stack->next = node->next; 79 return node; 80 } 81 82 static inline struct io_wq_work *wq_next_work(struct io_wq_work *work) 83 { 84 if (!work->list.next) 85 return NULL; 86 87 return container_of(work->list.next, struct io_wq_work, list); 88 } 89 90 #endif // INTERNAL_IO_SLIST_H 91