xref: /openbsd-src/sys/dev/pci/drm/include/linux/llist.h (revision 5a38ef86d0b61900239c7913d24a05e7b88a58f0)
1 /* Public domain. */
2 
3 #ifndef _LINUX_LLIST_H
4 #define _LINUX_LLIST_H
5 
6 #include <sys/atomic.h>
7 
8 struct llist_node {
9 	struct llist_node *next;
10 };
11 
12 struct llist_head {
13 	struct llist_node *first;
14 };
15 
16 #define llist_entry(ptr, type, member) \
17 	((ptr) ? container_of(ptr, type, member) : NULL)
18 
19 static inline struct llist_node *
20 llist_del_all(struct llist_head *head)
21 {
22 	return atomic_swap_ptr(&head->first, NULL);
23 }
24 
25 static inline struct llist_node *
26 llist_del_first(struct llist_head *head)
27 {
28 	struct llist_node *first, *next;
29 
30 	do {
31 		first = head->first;
32 		if (first == NULL)
33 			return NULL;
34 		next = first->next;
35 	} while (atomic_cas_ptr(&head->first, first, next) != first);
36 
37 	return first;
38 }
39 
40 static inline bool
41 llist_add(struct llist_node *new, struct llist_head *head)
42 {
43 	struct llist_node *first;
44 
45 	do {
46 		new->next = first = head->first;
47 	} while (atomic_cas_ptr(&head->first, first, new) != first);
48 
49 	return (first == NULL);
50 }
51 
52 static inline bool
53 llist_add_batch(struct llist_node *new_first, struct llist_node *new_last,
54     struct llist_head *head)
55 {
56 	struct llist_node *first;
57 
58 	do {
59 		new_last->next = first = head->first;
60 	} while (atomic_cas_ptr(&head->first, first, new_first) != first);
61 
62 	return (first == NULL);
63 }
64 
65 static inline void
66 init_llist_head(struct llist_head *head)
67 {
68 	head->first = NULL;
69 }
70 
71 static inline bool
72 llist_empty(struct llist_head *head)
73 {
74 	return (head->first == NULL);
75 }
76 
77 #define llist_for_each_safe(pos, n, node)				\
78 	for ((pos) = (node);						\
79 	    (pos) != NULL &&						\
80 	    ((n) = (pos)->next, pos);					\
81 	    (pos) = (n))
82 
83 #define llist_for_each_entry_safe(pos, n, node, member) 		\
84 	for (pos = llist_entry((node), __typeof(*pos), member); 	\
85 	    pos != NULL &&						\
86 	    (n = llist_entry(pos->member.next, __typeof(*pos), member), pos); \
87 	    pos = n)
88 
89 #define llist_for_each_entry(pos, node, member)				\
90 	for ((pos) = llist_entry((node), __typeof(*(pos)), member);	\
91 	    (pos) != NULL;						\
92 	    (pos) = llist_entry((pos)->member.next, __typeof(*(pos)), member))
93 
94 #endif
95