#define __WRITE_ONCE(x, val) \ do { \ *(volatile typeof(x) *)&(x) = (val); \ } while (0)
#define WRITE_ONCE(x, val) \ do { \ compiletime_assert_rwonce_type(x); \ __WRITE_ONCE(x, val); \ } while (0)
/** * INIT_LIST_HEAD - Initialize a list_head structure * @list: list_head structure to be initialized. * * Initializes the list_head to point to itself. If it is a list header, * the result is an empty list. */ staticinlinevoidINIT_LIST_HEAD(struct list_head *list) { WRITE_ONCE(list->next, list); list->prev = list; }
/* * Insert a new entry between two known consecutive entries. * * This is only for internal list manipulation where we know * the prev/next entries already! */ staticinlinevoid __list_add(struct list_head *new, struct list_head *prev, struct list_head *next) { if (!__list_add_valid(new, prev, next)) return;
/** * list_add - add a new entry * @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. */ staticinlinevoidlist_add(struct list_head *new, struct list_head *head) { __list_add(new, head, head->next); }
/** * list_add_tail - add a new entry * @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. */ staticinlinevoidlist_add_tail(struct list_head *new, struct list_head *head) { __list_add(new, head->prev, head); }
/* * Delete a list entry and clear the 'prev' pointer. * * This is a special-purpose list clearing method used in the networking code * for lists allocated as per-cpu, where we don't want to incur the extra * WRITE_ONCE() overhead of a regular list_del_init(). The code that uses this * needs to check the node 'prev' pointer instead of calling list_empty(). */ staticinlinevoid __list_del_clearprev(struct list_head *entry) { __list_del(entry->prev, entry->next); entry->prev = NULL; }
staticinlinevoid __list_del_entry(struct list_head *entry) { if (!__list_del_entry_valid(entry)) return;
__list_del(entry->prev, entry->next); }
/** * list_del - deletes entry from list. * @entry: the element to delete from the list. * Note: list_empty() on entry does not return true after this, the entry is * in an undefined state. */ staticinlinevoidlist_del(struct list_head *entry) { __list_del_entry(entry); entry->next = LIST_POISON1; entry->prev = LIST_POISON2; }
/** * list_del_init - deletes entry from list and reinitialize it. * @entry: the element to delete from the list. */ staticinlinevoidlist_del_init(struct list_head *entry) { __list_del_entry(entry); INIT_LIST_HEAD(entry); }
/* * Architectures might want to move the poison pointer offset * into some well-recognized area such as 0xdead000000000000, * that is also not mappable by user-space exploits: */ #ifdef CONFIG_ILLEGAL_POINTER_VALUE # define POISON_POINTER_DELTA _AC(CONFIG_ILLEGAL_POINTER_VALUE, UL) #else # define POISON_POINTER_DELTA 0 #endif
/* * 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 *) 0x100 + POISON_POINTER_DELTA) #define LIST_POISON2 ((void *) 0x122 + POISON_POINTER_DELTA)
/** * list_replace - replace old entry by new one * @old : the element to be replaced * @new : the new element to insert * * If @old was empty, it will be overwritten. */ staticinlinevoidlist_replace(struct list_head *old, struct list_head *new) { new->next = old->next; new->next->prev = new; new->prev = old->prev; new->prev->next = new; }
/** * list_replace_init - replace old entry by new one and initialize the old one * @old : the element to be replaced * @new : the new element to insert * * If @old was empty, it will be overwritten. */ staticinlinevoidlist_replace_init(struct list_head *old, struct list_head *new) { list_replace(old, new); INIT_LIST_HEAD(old); }
将前后两个指针分别指向新节点,新节点自身的两个指针指向前后即可。
节点交换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/** * list_swap - replace entry1 with entry2 and re-add entry1 at entry2's position * @entry1: the location to place entry2 * @entry2: the location to place entry1 */ staticinlinevoidlist_swap(struct list_head *entry1, struct list_head *c) { structlist_head *pos = ->prev;
/** * list_move - delete from one list and add as another's head * @list: the entry to move * @head: the head that will precede our entry */ staticinlinevoidlist_move(struct list_head *list, struct list_head *head) { __list_del_entry(list); list_add(list, head); }
/** * list_move_tail - delete from one list and add as another's tail * @list: the entry to move * @head: the head that will follow our entry */ staticinlinevoidlist_move_tail(struct list_head *list, struct list_head *head) { __list_del_entry(list); list_add_tail(list, head); }
/** * list_is_first -- tests whether @list is the first entry in list @head * @list: the entry to test * @head: the head of the list */ staticinlineintlist_is_first(conststruct list_head *list, conststruct list_head *head) { returnlist->prev == head; }
检测是否最后一个节点
1 2 3 4 5 6 7 8 9 10
/** * list_is_last - tests whether @list is the last entry in list @head * @list: the entry to test * @head: the head of the list */ staticinlineintlist_is_last(conststruct list_head *list, conststruct list_head *head) { returnlist->next == head; }
/** * list_empty - tests whether a list is empty * @head: the list to test. */ staticinlineintlist_empty(conststruct list_head *head) { return READ_ONCE(head->next) == head; }
/** * list_empty_careful - tests whether a list is empty and not being modified * @head: the list to test * * Description: * tests whether a list is empty _and_ checks that no other CPU might be * in the process of modifying either member (next or prev) * * NOTE: using list_empty_careful() without synchronization * can only be safe if the only activity that can happen * to the list entry is list_del_init(). Eg. it cannot be used * if another CPU could re-list_add() it. */ staticinlineintlist_empty_careful(conststruct list_head *head) { structlist_head *next = smp_load_acquire(&head->next); return (next == head) && (next == head->prev); }
检测是否只有一个节点
1 2 3 4 5 6 7 8
/** * list_is_singular - tests whether a list has just one entry. * @head: the list to test. */ staticinlineintlist_is_singular(conststruct list_head *head) { return !list_empty(head) && (head->next == head->prev); }