| /* |
| * SPDX-License-Identifier: BSD-2-Clause |
| * |
| * Simple doubly-linked list library. |
| * |
| * Adapted from Xvisor source file libs/include/libs/list.h |
| * |
| * Copyright (c) 2020 Western Digital Corporation or its affiliates. |
| * |
| * Authors: |
| * Anup Patel <anup.patel@wdc.com> |
| */ |
| |
| #ifndef __SBI_LIST_H__ |
| #define __SBI_LIST_H__ |
| |
| #include <sbi/sbi_types.h> |
| |
| #define SBI_LIST_POISON_PREV 0xDEADBEEF |
| #define SBI_LIST_POISON_NEXT 0xFADEBABE |
| |
| struct sbi_dlist { |
| struct sbi_dlist *next, *prev; |
| }; |
| |
| #define SBI_LIST_HEAD_INIT(__lname) { &(__lname), &(__lname) } |
| |
| #define SBI_LIST_HEAD(_lname) \ |
| struct sbi_dlist _lname = SBI_LIST_HEAD_INIT(_lname) |
| |
| #define SBI_INIT_LIST_HEAD(ptr) \ |
| do { \ |
| (ptr)->next = ptr; (ptr)->prev = ptr; \ |
| } while (0) |
| |
| static inline void __sbi_list_add(struct sbi_dlist *new, |
| struct sbi_dlist *prev, |
| struct sbi_dlist *next) |
| { |
| new->prev = prev; |
| new->next = next; |
| prev->next = new; |
| next->prev = new; |
| } |
| |
| /** |
| * Checks if the list is empty or not. |
| * @param head List head |
| * |
| * Returns true if list is empty, false otherwise. |
| */ |
| static inline bool sbi_list_empty(struct sbi_dlist *head) |
| { |
| return head->next == head; |
| } |
| |
| /** |
| * Adds the new node after the given head. |
| * @param new New node that needs to be added to list. |
| * @param head List head after which the "new" node should be added. |
| * Note: the new node is added after the head. |
| */ |
| static inline void sbi_list_add(struct sbi_dlist *new, struct sbi_dlist *head) |
| { |
| __sbi_list_add(new, head, head->next); |
| } |
| |
| /** |
| * Adds a node at the tail where tnode points to tail node. |
| * @param new The new node to be added before tail. |
| * @param tnode The current tail node. |
| * Note: the new node is added before tail node. |
| */ |
| static inline void sbi_list_add_tail(struct sbi_dlist *new, |
| struct sbi_dlist *tnode) |
| { |
| __sbi_list_add(new, tnode->prev, tnode); |
| } |
| |
| static inline void __sbi_list_del(struct sbi_dlist *prev, |
| struct sbi_dlist *next) |
| { |
| prev->next = next; |
| next->prev = prev; |
| } |
| |
| static inline void __sbi_list_del_entry(struct sbi_dlist *entry) |
| { |
| __sbi_list_del(entry->prev, entry->next); |
| } |
| |
| /** |
| * Deletes a given entry from list. |
| * @param node Node to be deleted. |
| */ |
| static inline void sbi_list_del(struct sbi_dlist *entry) |
| { |
| __sbi_list_del(entry->prev, entry->next); |
| entry->next = (void *)SBI_LIST_POISON_NEXT; |
| entry->prev = (void *)SBI_LIST_POISON_PREV; |
| } |
| |
| /** |
| * Deletes entry from list and reinitialize it. |
| * @param entry the element to delete from the list. |
| */ |
| static inline void sbi_list_del_init(struct sbi_dlist *entry) |
| { |
| __sbi_list_del_entry(entry); |
| SBI_INIT_LIST_HEAD(entry); |
| } |
| |
| /** |
| * Get the struct for this entry |
| * @param ptr the &struct list_head pointer. |
| * @param type the type of the struct this is embedded in. |
| * @param member the name of the list_struct within the struct. |
| */ |
| #define sbi_list_entry(ptr, type, member) \ |
| container_of(ptr, type, member) |
| |
| /** |
| * Get the first element from a list |
| * @param ptr the list head to take the element from. |
| * @param type the type of the struct this is embedded in. |
| * @param member the name of the list_struct within the struct. |
| * |
| * Note: that list is expected to be not empty. |
| */ |
| #define sbi_list_first_entry(ptr, type, member) \ |
| sbi_list_entry((ptr)->next, type, member) |
| |
| /** |
| * Get the last element from a list |
| * @param ptr the list head to take the element from. |
| * @param type the type of the struct this is embedded in. |
| * @param member the name of the list_head within the struct. |
| * |
| * Note: that list is expected to be not empty. |
| */ |
| #define sbi_list_last_entry(ptr, type, member) \ |
| sbi_list_entry((ptr)->prev, type, member) |
| |
| /** |
| * Iterate over a list |
| * @param pos the &struct list_head to use as a loop cursor. |
| * @param head the head for your list. |
| */ |
| #define sbi_list_for_each(pos, head) \ |
| for (pos = (head)->next; pos != (head); pos = pos->next) |
| |
| /** |
| * Iterate over list of given type |
| * @param pos the type * to use as a loop cursor. |
| * @param head the head for your list. |
| * @param member the name of the list_struct within the struct. |
| */ |
| #define sbi_list_for_each_entry(pos, head, member) \ |
| for (pos = sbi_list_entry((head)->next, typeof(*pos), member); \ |
| &pos->member != (head); \ |
| pos = sbi_list_entry(pos->member.next, typeof(*pos), member)) |
| |
| #endif |