xref: /openbsd-src/sys/dev/pci/drm/include/linux/llist.h (revision 99fd087599a8791921855f21bd7e36130f39aadc)
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 void
53 init_llist_head(struct llist_head *head)
54 {
55 	head->first = NULL;
56 }
57 
58 static inline bool
59 llist_empty(struct llist_head *head)
60 {
61 	return (head->first == NULL);
62 }
63 
64 #define llist_for_each_entry_safe(pos, n, node, member) 		\
65 	for (pos = llist_entry((node), __typeof(*pos), member); 	\
66 	    pos != NULL &&						\
67 	    (n = llist_entry(pos->member.next, __typeof(*pos), member), pos); \
68 	    pos = n)
69 
70 #endif
71