]>
Commit | Line | Data |
---|---|---|
f5b92a66 BB |
1 | #ifndef _SPL_LIST_H |
2 | #define _SPL_LIST_H | |
3 | ||
dc0f9207 | 4 | #include <sys/types.h> |
d702c04f | 5 | #include <linux/list.h> |
dc0f9207 | 6 | |
d702c04f BB |
7 | /* NOTE: We have implemented the Solaris list API in terms of the native |
8 | * linux API. This has certain advantages in terms of leveraging the linux | |
9 | * list debugging infrastructure, but it also means that the internals of a | |
10 | * list differ slightly than on Solaris. This is not a problem as long as | |
11 | * all callers stick to the published API. The two major differences are: | |
12 | * | |
13 | * 1) A list_node_t is mapped to a linux list_head struct which changes | |
14 | * the name of the list_next/list_prev pointers to next/prev respectively. | |
15 | * | |
16 | * 2) A list_node_t which is not attached to a list on Solaris is denoted | |
17 | * by having its list_next/list_prev pointers set to NULL. Under linux | |
18 | * the next/prev pointers are set to LIST_POISON1 and LIST_POISON2 | |
19 | * respectively. At this moment this only impacts the implementation | |
20 | * of the list_link_init() and list_link_active() functions. | |
21 | */ | |
22 | ||
23 | typedef struct list_head list_node_t; | |
dc0f9207 BB |
24 | |
25 | typedef struct list { | |
d702c04f BB |
26 | size_t list_size; |
27 | size_t list_offset; | |
28 | list_node_t list_head; | |
dc0f9207 BB |
29 | } list_t; |
30 | ||
d702c04f BB |
31 | #define list_d2l(a, obj) ((list_node_t *)(((char *)obj) + (a)->list_offset)) |
32 | #define list_object(a, node) ((void *)(((char *)node) - (a)->list_offset)) | |
33 | ||
34 | static inline int | |
35 | list_is_empty(list_t *list) | |
36 | { | |
37 | return list_empty(&list->list_head); | |
38 | } | |
39 | ||
40 | static inline void | |
41 | list_link_init(list_node_t *node) | |
42 | { | |
43 | node->next = LIST_POISON1; | |
44 | node->prev = LIST_POISON2; | |
45 | } | |
46 | ||
47 | static inline void | |
48 | list_create(list_t *list, size_t size, size_t offset) | |
49 | { | |
50 | ASSERT(list); | |
51 | ASSERT(size > 0); | |
52 | ASSERT(size >= offset + sizeof(list_node_t)); | |
53 | ||
54 | list->list_size = size; | |
55 | list->list_offset = offset; | |
56 | INIT_LIST_HEAD(&list->list_head); | |
57 | } | |
58 | ||
59 | static inline void | |
60 | list_destroy(list_t *list) | |
61 | { | |
62 | ASSERT(list); | |
63 | ASSERT(list_is_empty(list)); | |
64 | ||
65 | list_del(&list->list_head); | |
66 | } | |
67 | ||
68 | static inline void | |
69 | list_insert_head(list_t *list, void *object) | |
70 | { | |
71 | list_add(list_d2l(list, object), &list->list_head); | |
72 | } | |
73 | ||
74 | static inline void | |
75 | list_insert_tail(list_t *list, void *object) | |
76 | { | |
77 | list_add_tail(list_d2l(list, object), &list->list_head); | |
78 | } | |
79 | ||
80 | static inline void | |
81 | list_insert_after(list_t *list, void *object, void *nobject) | |
82 | { | |
83 | if (object == NULL) | |
84 | list_insert_head(list, nobject); | |
85 | else | |
86 | list_add(list_d2l(list, nobject), list_d2l(list, object)); | |
87 | } | |
88 | ||
89 | static inline void | |
90 | list_insert_before(list_t *list, void *object, void *nobject) | |
91 | { | |
92 | if (object == NULL) | |
93 | list_insert_tail(list, nobject); | |
94 | else | |
95 | list_add_tail(list_d2l(list, nobject), list_d2l(list, object)); | |
96 | } | |
97 | ||
98 | static inline void | |
99 | list_remove(list_t *list, void *object) | |
100 | { | |
101 | ASSERT(!list_is_empty(list)); | |
102 | list_del(list_d2l(list, object)); | |
103 | } | |
104 | ||
105 | static inline void * | |
106 | list_remove_head(list_t *list) | |
107 | { | |
108 | list_node_t *head = list->list_head.next; | |
109 | if (head == &list->list_head) | |
110 | return NULL; | |
111 | ||
112 | list_del(head); | |
113 | return list_object(list, head); | |
114 | } | |
115 | ||
116 | static inline void * | |
117 | list_remove_tail(list_t *list) | |
118 | { | |
119 | list_node_t *tail = list->list_head.prev; | |
120 | if (tail == &list->list_head) | |
121 | return NULL; | |
122 | ||
123 | list_del(tail); | |
124 | return list_object(list, tail); | |
125 | } | |
126 | ||
127 | static inline void * | |
128 | list_head(list_t *list) | |
129 | { | |
130 | if (list_is_empty(list)) | |
131 | return NULL; | |
132 | ||
133 | return list_object(list, list->list_head.next); | |
134 | } | |
135 | ||
136 | static inline void * | |
137 | list_tail(list_t *list) | |
138 | { | |
139 | if (list_is_empty(list)) | |
140 | return NULL; | |
141 | ||
142 | return list_object(list, list->list_head.prev); | |
143 | } | |
144 | ||
145 | static inline void * | |
146 | list_next(list_t *list, void *object) | |
147 | { | |
148 | list_node_t *node = list_d2l(list, object); | |
149 | ||
150 | if (node->next != &list->list_head) | |
151 | return list_object(list, node->next); | |
152 | ||
153 | return NULL; | |
154 | } | |
dc0f9207 | 155 | |
d702c04f BB |
156 | static inline void * |
157 | list_prev(list_t *list, void *object) | |
158 | { | |
159 | list_node_t *node = list_d2l(list, object); | |
dc0f9207 | 160 | |
d702c04f BB |
161 | if (node->prev != &list->list_head) |
162 | return list_object(list, node->prev); | |
dc0f9207 | 163 | |
d702c04f BB |
164 | return NULL; |
165 | } | |
dc0f9207 | 166 | |
d702c04f BB |
167 | static inline int |
168 | list_link_active(list_node_t *node) | |
169 | { | |
170 | return (node->next != LIST_POISON1) && (node->prev != LIST_POISON2); | |
171 | } | |
dc0f9207 | 172 | |
759dfe7d BB |
173 | static inline void |
174 | spl_list_move_tail(list_t *dst, list_t *src) | |
175 | { | |
176 | list_splice_init(&src->list_head, dst->list_head.prev); | |
177 | } | |
178 | ||
179 | #define list_move_tail(dst, src) spl_list_move_tail(dst, src) | |
180 | ||
f5b92a66 | 181 | #endif /* SPL_LIST_H */ |