0001 #ifndef INTERNAL_IO_SLIST_H
0002 #define INTERNAL_IO_SLIST_H
0003
0004 #include <linux/io_uring_types.h>
0005
0006 #define wq_list_for_each(pos, prv, head) \
0007 for (pos = (head)->first, prv = NULL; pos; prv = pos, pos = (pos)->next)
0008
0009 #define wq_list_for_each_resume(pos, prv) \
0010 for (; pos; prv = pos, pos = (pos)->next)
0011
0012 #define wq_list_empty(list) (READ_ONCE((list)->first) == NULL)
0013
0014 #define INIT_WQ_LIST(list) do { \
0015 (list)->first = NULL; \
0016 } while (0)
0017
0018 static inline void wq_list_add_after(struct io_wq_work_node *node,
0019 struct io_wq_work_node *pos,
0020 struct io_wq_work_list *list)
0021 {
0022 struct io_wq_work_node *next = pos->next;
0023
0024 pos->next = node;
0025 node->next = next;
0026 if (!next)
0027 list->last = node;
0028 }
0029
0030
0031
0032
0033
0034
0035
0036 static inline struct io_wq_work_node *wq_list_merge(struct io_wq_work_list *list0,
0037 struct io_wq_work_list *list1)
0038 {
0039 struct io_wq_work_node *ret;
0040
0041 if (!list0->first) {
0042 ret = list1->first;
0043 } else {
0044 ret = list0->first;
0045 list0->last->next = list1->first;
0046 }
0047 INIT_WQ_LIST(list0);
0048 INIT_WQ_LIST(list1);
0049 return ret;
0050 }
0051
0052 static inline void wq_list_add_tail(struct io_wq_work_node *node,
0053 struct io_wq_work_list *list)
0054 {
0055 node->next = NULL;
0056 if (!list->first) {
0057 list->last = node;
0058 WRITE_ONCE(list->first, node);
0059 } else {
0060 list->last->next = node;
0061 list->last = node;
0062 }
0063 }
0064
0065 static inline void wq_list_add_head(struct io_wq_work_node *node,
0066 struct io_wq_work_list *list)
0067 {
0068 node->next = list->first;
0069 if (!node->next)
0070 list->last = node;
0071 WRITE_ONCE(list->first, node);
0072 }
0073
0074 static inline void wq_list_cut(struct io_wq_work_list *list,
0075 struct io_wq_work_node *last,
0076 struct io_wq_work_node *prev)
0077 {
0078
0079 if (!prev)
0080 WRITE_ONCE(list->first, last->next);
0081 else
0082 prev->next = last->next;
0083
0084 if (last == list->last)
0085 list->last = prev;
0086 last->next = NULL;
0087 }
0088
0089 static inline void __wq_list_splice(struct io_wq_work_list *list,
0090 struct io_wq_work_node *to)
0091 {
0092 list->last->next = to->next;
0093 to->next = list->first;
0094 INIT_WQ_LIST(list);
0095 }
0096
0097 static inline bool wq_list_splice(struct io_wq_work_list *list,
0098 struct io_wq_work_node *to)
0099 {
0100 if (!wq_list_empty(list)) {
0101 __wq_list_splice(list, to);
0102 return true;
0103 }
0104 return false;
0105 }
0106
0107 static inline void wq_stack_add_head(struct io_wq_work_node *node,
0108 struct io_wq_work_node *stack)
0109 {
0110 node->next = stack->next;
0111 stack->next = node;
0112 }
0113
0114 static inline void wq_list_del(struct io_wq_work_list *list,
0115 struct io_wq_work_node *node,
0116 struct io_wq_work_node *prev)
0117 {
0118 wq_list_cut(list, node, prev);
0119 }
0120
0121 static inline
0122 struct io_wq_work_node *wq_stack_extract(struct io_wq_work_node *stack)
0123 {
0124 struct io_wq_work_node *node = stack->next;
0125
0126 stack->next = node->next;
0127 return node;
0128 }
0129
0130 static inline struct io_wq_work *wq_next_work(struct io_wq_work *work)
0131 {
0132 if (!work->list.next)
0133 return NULL;
0134
0135 return container_of(work->list.next, struct io_wq_work, list);
0136 }
0137
0138 #endif