diff options
Diffstat (limited to 'include/linux/list.h')
-rw-r--r-- | include/linux/list.h | 87 |
1 files changed, 78 insertions, 9 deletions
diff --git a/include/linux/list.h b/include/linux/list.h index 453916bc0412..db35ef02e745 100644 --- a/include/linux/list.h +++ b/include/linux/list.h | |||
@@ -214,22 +214,62 @@ static inline int list_is_singular(const struct list_head *head) | |||
214 | return !list_empty(head) && (head->next == head->prev); | 214 | return !list_empty(head) && (head->next == head->prev); |
215 | } | 215 | } |
216 | 216 | ||
217 | static inline void __list_cut_position(struct list_head *list, | ||
218 | struct list_head *head, struct list_head *entry) | ||
219 | { | ||
220 | struct list_head *new_first = entry->next; | ||
221 | list->next = head->next; | ||
222 | list->next->prev = list; | ||
223 | list->prev = entry; | ||
224 | entry->next = list; | ||
225 | head->next = new_first; | ||
226 | new_first->prev = head; | ||
227 | } | ||
228 | |||
229 | /** | ||
230 | * list_cut_position - cut a list into two | ||
231 | * @list: a new list to add all removed entries | ||
232 | * @head: a list with entries | ||
233 | * @entry: an entry within head, could be the head itself | ||
234 | * and if so we won't cut the list | ||
235 | * | ||
236 | * This helper moves the initial part of @head, up to and | ||
237 | * including @entry, from @head to @list. You should | ||
238 | * pass on @entry an element you know is on @head. @list | ||
239 | * should be an empty list or a list you do not care about | ||
240 | * losing its data. | ||
241 | * | ||
242 | */ | ||
243 | static inline void list_cut_position(struct list_head *list, | ||
244 | struct list_head *head, struct list_head *entry) | ||
245 | { | ||
246 | if (list_empty(head)) | ||
247 | return; | ||
248 | if (list_is_singular(head) && | ||
249 | (head->next != entry && head != entry)) | ||
250 | return; | ||
251 | if (entry == head) | ||
252 | INIT_LIST_HEAD(list); | ||
253 | else | ||
254 | __list_cut_position(list, head, entry); | ||
255 | } | ||
256 | |||
217 | static inline void __list_splice(const struct list_head *list, | 257 | static inline void __list_splice(const struct list_head *list, |
218 | struct list_head *head) | 258 | struct list_head *prev, |
259 | struct list_head *next) | ||
219 | { | 260 | { |
220 | struct list_head *first = list->next; | 261 | struct list_head *first = list->next; |
221 | struct list_head *last = list->prev; | 262 | struct list_head *last = list->prev; |
222 | struct list_head *at = head->next; | ||
223 | 263 | ||
224 | first->prev = head; | 264 | first->prev = prev; |
225 | head->next = first; | 265 | prev->next = first; |
226 | 266 | ||
227 | last->next = at; | 267 | last->next = next; |
228 | at->prev = last; | 268 | next->prev = last; |
229 | } | 269 | } |
230 | 270 | ||
231 | /** | 271 | /** |
232 | * list_splice - join two lists | 272 | * list_splice - join two lists, this is designed for stacks |
233 | * @list: the new list to add. | 273 | * @list: the new list to add. |
234 | * @head: the place to add it in the first list. | 274 | * @head: the place to add it in the first list. |
235 | */ | 275 | */ |
@@ -237,7 +277,19 @@ static inline void list_splice(const struct list_head *list, | |||
237 | struct list_head *head) | 277 | struct list_head *head) |
238 | { | 278 | { |
239 | if (!list_empty(list)) | 279 | if (!list_empty(list)) |
240 | __list_splice(list, head); | 280 | __list_splice(list, head, head->next); |
281 | } | ||
282 | |||
283 | /** | ||
284 | * list_splice_tail - join two lists, each list being a queue | ||
285 | * @list: the new list to add. | ||
286 | * @head: the place to add it in the first list. | ||
287 | */ | ||
288 | static inline void list_splice_tail(struct list_head *list, | ||
289 | struct list_head *head) | ||
290 | { | ||
291 | if (!list_empty(list)) | ||
292 | __list_splice(list, head->prev, head); | ||
241 | } | 293 | } |
242 | 294 | ||
243 | /** | 295 | /** |
@@ -251,7 +303,24 @@ static inline void list_splice_init(struct list_head *list, | |||
251 | struct list_head *head) | 303 | struct list_head *head) |
252 | { | 304 | { |
253 | if (!list_empty(list)) { | 305 | if (!list_empty(list)) { |
254 | __list_splice(list, head); | 306 | __list_splice(list, head, head->next); |
307 | INIT_LIST_HEAD(list); | ||
308 | } | ||
309 | } | ||
310 | |||
311 | /** | ||
312 | * list_splice_tail_init - join two lists and reinitialise the emptied list | ||
313 | * @list: the new list to add. | ||
314 | * @head: the place to add it in the first list. | ||
315 | * | ||
316 | * Each of the lists is a queue. | ||
317 | * The list at @list is reinitialised | ||
318 | */ | ||
319 | static inline void list_splice_tail_init(struct list_head *list, | ||
320 | struct list_head *head) | ||
321 | { | ||
322 | if (!list_empty(list)) { | ||
323 | __list_splice(list, head->prev, head); | ||
255 | INIT_LIST_HEAD(list); | 324 | INIT_LIST_HEAD(list); |
256 | } | 325 | } |
257 | } | 326 | } |