diff options
author | Kay Sievers <kay.sievers@vrfy.org> | 2008-09-26 19:44:53 +0200 |
---|---|---|
committer | Kay Sievers <kay.sievers@vrfy.org> | 2008-09-26 19:44:53 +0200 |
commit | e345e2670a8c17f5e1145cc554b7a7646e271032 (patch) | |
tree | 26b6f0a269bf6782bb1ea56754babf20d7f50cec /udev/list.h | |
parent | 9921484458e0233e1aae868bfa8cc1481aa460a8 (diff) |
libudev: rework list handling
Diffstat (limited to 'udev/list.h')
-rw-r--r-- | udev/list.h | 183 |
1 files changed, 183 insertions, 0 deletions
diff --git a/udev/list.h b/udev/list.h new file mode 100644 index 0000000000..c679e50ace --- /dev/null +++ b/udev/list.h @@ -0,0 +1,183 @@ +/* + * Simple doubly linked list implementation. + * + * Based on list.h in the Linux kernel source tree, licensed under + * the GNU GPL version 2. + */ + +#ifndef _LIST_H +#define _LIST_H + +/** + * container_of: + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + * cast a member of a structure out to the containing structure + */ +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +/* + * These are non-NULL pointers that will result in page faults + * under normal circumstances, used to verify that nobody uses + * non-initialized list entries. + */ +#define LIST_POISON1 ((void *) 0x00100100) +#define LIST_POISON2 ((void *) 0x00200200) + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* Insert a new entry between two known consecutive entries. */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add: + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail: + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + */ +static inline void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del: + * @entry: the element to delete from the list. + * + * deletes entry from list. + * + * Note: list_empty on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = LIST_POISON1; + entry->prev = LIST_POISON2; +} + +/** + * list_move + * @list: the entry to move + * @head: the head that will precede our entry + * delete from one list and add as another's head + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail + * @list: the entry to move + * @head: the head that will follow our entry + * + * delete from one list and add as another's tail + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_empty: + * @head: the list to test. + * + * tests whether a list is empty + */ +static inline int list_empty(struct list_head *head) +{ + return head->next == head; +} + +/** + * list_entry: + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + * + * get the struct for this entry + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_for_each_entry: + * @pos: the type * to use as a loop counter. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * iterate over list of given type + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_safe: + * @pos: the type * to use as a loop counter. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * iterate over list of given type safe against removal of list entry + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +#endif /* _LIST_H */ |