]>
Commit | Line | Data |
---|---|---|
9f95a23c TL |
1 | /*- |
2 | * BSD LICENSE | |
3 | * | |
4 | * Copyright (c) Intel Corporation. | |
5 | * All rights reserved. | |
6 | * | |
7 | * Redistribution and use in source and binary forms, with or without | |
8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | |
10 | * | |
11 | * * Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | |
13 | * * Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in | |
15 | * the documentation and/or other materials provided with the | |
16 | * distribution. | |
17 | * * Neither the name of Intel Corporation nor the names of its | |
18 | * contributors may be used to endorse or promote products derived | |
19 | * from this software without specific prior written permission. | |
20 | * | |
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
22 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
24 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
25 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
26 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
27 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
31 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
32 | */ | |
33 | ||
34 | #ifndef __OCF_LIST_H__ | |
35 | #define __OCF_LIST_H__ | |
36 | ||
37 | #define LIST_POISON1 ((void *) 0x00100100) | |
38 | #define LIST_POISON2 ((void *) 0x00200200) | |
39 | ||
40 | /** | |
41 | * List entry structure mimicking linux kernel based one. | |
42 | */ | |
43 | struct list_head { | |
44 | struct list_head *next; | |
45 | struct list_head *prev; | |
46 | }; | |
47 | ||
48 | /** | |
49 | * start an empty list | |
50 | */ | |
51 | #define INIT_LIST_HEAD(l) { (l)->prev = l; (l)->next = l; } | |
52 | ||
53 | /** | |
54 | * Add item to list head. | |
55 | * @param it list entry to be added | |
56 | * @param l1 list main node (head) | |
57 | */ | |
58 | static inline void list_add(struct list_head *it, struct list_head *l1) | |
59 | { | |
60 | it->prev = l1; | |
61 | it->next = l1->next; | |
62 | ||
63 | l1->next->prev = it; | |
64 | l1->next = it; | |
65 | } | |
66 | ||
67 | /** | |
68 | * Add item it to tail. | |
69 | * @param it list entry to be added | |
70 | * @param l1 list main node (head) | |
71 | */ | |
72 | static inline void list_add_tail(struct list_head *it, struct list_head *l1) | |
73 | { | |
74 | it->prev = l1->prev; | |
75 | it->next = l1; | |
76 | ||
77 | l1->prev->next = it; | |
78 | l1->prev = it; | |
79 | } | |
80 | ||
81 | /** | |
82 | * check if a list is empty (return true) | |
83 | */ | |
84 | static inline int list_empty(struct list_head *it) | |
85 | { | |
86 | return it->next == it; | |
87 | } | |
88 | ||
89 | /** | |
90 | * delete an entry from a list | |
91 | */ | |
92 | static inline void list_del(struct list_head *it) | |
93 | { | |
94 | it->next->prev = it->prev; | |
95 | it->prev->next = it->next; | |
96 | } | |
97 | ||
98 | static inline void list_move_tail(struct list_head *list, | |
99 | struct list_head *head) | |
100 | { | |
101 | list_del(list); | |
102 | list_add_tail(list, head); | |
103 | } | |
104 | ||
105 | static inline void list_move(struct list_head *list, | |
106 | struct list_head *head) | |
107 | { | |
108 | list_del(list); | |
109 | list_add(list, head); | |
110 | } | |
111 | ||
112 | /** | |
113 | * Extract an entry. | |
114 | * @param list_head_i list head item, from which entry is extracted | |
115 | * @param item_type type (struct) of list entry | |
116 | * @param field_name name of list_head field within item_type | |
117 | */ | |
118 | #define list_entry(list_head_i, item_type, field_name) \ | |
119 | (item_type *)(((void*)(list_head_i)) - offsetof(item_type, field_name)) | |
120 | ||
121 | #define list_first_entry(list_head_i, item_type, field_name) \ | |
122 | list_entry((list_head_i)->next, item_type, field_name) | |
123 | ||
124 | /** | |
125 | * @param iterator uninitialized list_head pointer, to be used as iterator | |
126 | * @param plist list head (main node) | |
127 | */ | |
128 | #define list_for_each(iterator, plist) \ | |
129 | for (iterator = (plist)->next; \ | |
130 | (iterator)->next != (plist)->next; \ | |
131 | iterator = (iterator)->next) | |
132 | ||
133 | /** | |
134 | * Safe version of list_for_each which works even if entries are deleted during | |
135 | * loop. | |
136 | * @param iterator uninitialized list_head pointer, to be used as iterator | |
137 | * @param q another uninitialized list_head, used as helper | |
138 | * @param plist list head (main node) | |
139 | */ | |
140 | /* | |
141 | * Algorithm handles situation, where q is deleted. | |
142 | * consider in example 3 element list with header h: | |
143 | * | |
144 | * h -> 1 -> 2 -> 3 -> | |
145 | *1. i q | |
146 | * | |
147 | *2. i q | |
148 | * | |
149 | *3. q i | |
150 | */ | |
151 | #define list_for_each_safe(iterator, q, plist) \ | |
152 | for (iterator = (q = (plist)->next->next)->prev; \ | |
153 | (q) != (plist)->next; \ | |
154 | iterator = (q = (q)->next)->prev) | |
155 | ||
156 | #define _list_entry_helper(item, head, field_name) list_entry(head, typeof(*item), field_name) | |
157 | ||
158 | /** | |
159 | * Iterate over list entries. | |
160 | * @param list pointer to list item (iterator) | |
161 | * @param plist pointer to list_head item | |
162 | * @param field_name name of list_head field in list entry | |
163 | */ | |
164 | #define list_for_each_entry(item, plist, field_name) \ | |
165 | for (item = _list_entry_helper(item, (plist)->next, field_name); \ | |
166 | _list_entry_helper(item, (item)->field_name.next, field_name) !=\ | |
167 | _list_entry_helper(item, (plist)->next, field_name); \ | |
168 | item = _list_entry_helper(item, (item)->field_name.next, field_name)) | |
169 | ||
170 | /** | |
171 | * Safe version of list_for_each_entry which works even if entries are deleted | |
172 | * during loop. | |
173 | * @param list pointer to list item (iterator) | |
174 | * @param q another pointer to list item, used as helper | |
175 | * @param plist pointer to list_head item | |
176 | * @param field_name name of list_head field in list entry | |
177 | */ | |
178 | #define list_for_each_entry_safe(item, q, plist, field_name) \ | |
179 | for (item = _list_entry_helper(item, (plist)->next, field_name), \ | |
180 | q = _list_entry_helper(item, (item)->field_name.next, field_name); \ | |
181 | _list_entry_helper(item, (item)->field_name.next, field_name) != \ | |
182 | _list_entry_helper(item, (plist)->next, field_name); \ | |
183 | item = q, q = _list_entry_helper(q, (q)->field_name.next, field_name)) | |
184 | ||
185 | #endif |