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