1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
|
/* Doubly linked list macros compatible with Linux kernel's version
* Copyright (c) 2015 by Takashi Iwai <tiwai@suse.de>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*/
#ifndef _LIST_H
#define _LIST_H
#include <stddef.h>
struct list_head {
struct list_head *next;
struct list_head *prev;
};
/* one-shot definition of a list head */
#define LIST_HEAD(x) \
struct list_head x = { &x, &x }
/* initialize a list head explicitly */
static inline void INIT_LIST_HEAD(struct list_head *p)
{
p->next = p->prev = p;
}
#define list_entry_offset(p, type, offset) \
((type *)((char *)(p) - (offset)))
/* list_entry - retrieve the original struct from list_head
* @p: list_head pointer
* @type: struct type
* @member: struct field member containing the list_head
*/
#define list_entry(p, type, member) \
list_entry_offset(p, type, offsetof(type, member))
/* list_for_each - iterate over the linked list
* @p: iterator, a list_head pointer variable
* @list: list_head pointer containing the list
*/
#define list_for_each(p, list) \
for (p = (list)->next; p != (list); p = p->next)
/* list_for_each_safe - iterate over the linked list, safe to delete
* @p: iterator, a list_head pointer variable
* @s: a temporary variable to keep the next, a list_head pointer, too
* @list: list_head pointer containing the list
*/
#define list_for_each_safe(p, s, list) \
for (p = (list)->next; s = p->next, p != (list); p = s)
/* list_add - prepend a list entry at the head
* @p: the new list entry to add
* @list: the list head
*/
static inline void list_add(struct list_head *p, struct list_head *list)
{
struct list_head *first = list->next;
p->next = first;
first->prev = p;
list->next = p;
p->prev = list;
}
/* list_add_tail - append a list entry at the tail
* @p: the new list entry to add
* @list: the list head
*/
static inline void list_add_tail(struct list_head *p, struct list_head *list)
{
struct list_head *last = list->prev;
last->next = p;
p->prev = last;
p->next = list;
list->prev = p;
}
/* list_insert - insert a new list entry between two known consecutive entries
* @p: the new entry to be inserted between prev and next
* @prev: the left-side entry
* @next: the right-side entry
*/
static inline void list_insert(struct list_head *p,
struct list_head *prev,
struct list_head *next)
{
next->prev = p;
p->next = next;
p->prev = prev;
prev->next = p;
}
/* list_del - delete the given list entry */
static inline void list_del(struct list_head *p)
{
p->prev->next = p->next;
p->next->prev = p->prev;
}
/* list_empty - returns 1 if the given list is empty */
static inline int list_empty(const struct list_head *p)
{
return p->next == p;
}
/* list_splice - join two lists
* @list: the new list to add
* @head: the place to add it in the first list
*/
static inline void list_splice(const struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
struct list_head *first = list->next;
struct list_head *last = list->prev;
struct list_head *at = head->next;
first->prev = head;
head->next = first;
last->next = at;
at->prev = last;
}
}
/* list_splice_init - join two lists and reinitialize the emptied list
* @list: the new list to add
* @head: the place to add it in the first list
*
* The list at @list is reinitialized
*/
static inline void list_splice_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
list_splice(list, head);
INIT_LIST_HEAD(list);
}
}
#endif /* _LIST_H */
|