0001
0002 #ifndef _LINUX_LIST_NULLS_H
0003 #define _LINUX_LIST_NULLS_H
0004
0005 #include <linux/poison.h>
0006 #include <linux/const.h>
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021 struct hlist_nulls_head {
0022 struct hlist_nulls_node *first;
0023 };
0024
0025 struct hlist_nulls_node {
0026 struct hlist_nulls_node *next, **pprev;
0027 };
0028 #define NULLS_MARKER(value) (1UL | (((long)value) << 1))
0029 #define INIT_HLIST_NULLS_HEAD(ptr, nulls) \
0030 ((ptr)->first = (struct hlist_nulls_node *) NULLS_MARKER(nulls))
0031
0032 #define hlist_nulls_entry(ptr, type, member) container_of(ptr,type,member)
0033
0034 #define hlist_nulls_entry_safe(ptr, type, member) \
0035 ({ typeof(ptr) ____ptr = (ptr); \
0036 !is_a_nulls(____ptr) ? hlist_nulls_entry(____ptr, type, member) : NULL; \
0037 })
0038
0039
0040
0041
0042
0043 static inline int is_a_nulls(const struct hlist_nulls_node *ptr)
0044 {
0045 return ((unsigned long)ptr & 1);
0046 }
0047
0048
0049
0050
0051
0052
0053
0054 static inline unsigned long get_nulls_value(const struct hlist_nulls_node *ptr)
0055 {
0056 return ((unsigned long)ptr) >> 1;
0057 }
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067 static inline int hlist_nulls_unhashed(const struct hlist_nulls_node *h)
0068 {
0069 return !h->pprev;
0070 }
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081 static inline int hlist_nulls_unhashed_lockless(const struct hlist_nulls_node *h)
0082 {
0083 return !READ_ONCE(h->pprev);
0084 }
0085
0086 static inline int hlist_nulls_empty(const struct hlist_nulls_head *h)
0087 {
0088 return is_a_nulls(READ_ONCE(h->first));
0089 }
0090
0091 static inline void hlist_nulls_add_head(struct hlist_nulls_node *n,
0092 struct hlist_nulls_head *h)
0093 {
0094 struct hlist_nulls_node *first = h->first;
0095
0096 n->next = first;
0097 WRITE_ONCE(n->pprev, &h->first);
0098 h->first = n;
0099 if (!is_a_nulls(first))
0100 WRITE_ONCE(first->pprev, &n->next);
0101 }
0102
0103 static inline void __hlist_nulls_del(struct hlist_nulls_node *n)
0104 {
0105 struct hlist_nulls_node *next = n->next;
0106 struct hlist_nulls_node **pprev = n->pprev;
0107
0108 WRITE_ONCE(*pprev, next);
0109 if (!is_a_nulls(next))
0110 WRITE_ONCE(next->pprev, pprev);
0111 }
0112
0113 static inline void hlist_nulls_del(struct hlist_nulls_node *n)
0114 {
0115 __hlist_nulls_del(n);
0116 WRITE_ONCE(n->pprev, LIST_POISON2);
0117 }
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127 #define hlist_nulls_for_each_entry(tpos, pos, head, member) \
0128 for (pos = (head)->first; \
0129 (!is_a_nulls(pos)) && \
0130 ({ tpos = hlist_nulls_entry(pos, typeof(*tpos), member); 1;}); \
0131 pos = pos->next)
0132
0133
0134
0135
0136
0137
0138
0139
0140 #define hlist_nulls_for_each_entry_from(tpos, pos, member) \
0141 for (; (!is_a_nulls(pos)) && \
0142 ({ tpos = hlist_nulls_entry(pos, typeof(*tpos), member); 1;}); \
0143 pos = pos->next)
0144
0145 #endif