/* * list.h * * DSP-BIOS Bridge driver support functions for TI OMAP processors. * * Declarations of list management control structures and definitions * of inline list management functions. * * Copyright (C) 2008 Texas Instruments, Inc. * * This package is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #ifndef LIST_ #define LIST_ #include #include #define LST_IS_EMPTY(l) list_empty(&(l)->head) struct lst_list { struct list_head head; }; /* * ======== lst_first ======== * Purpose: * Returns a pointer to the first element of the list, or NULL if the list * is empty. * Parameters: * lst: Pointer to list control structure. * Returns: * Pointer to first list element, or NULL. * Requires: * - LST initialized. * - lst != NULL. * Ensures: */ static inline struct list_head *lst_first(struct lst_list *lst) { if (lst && !list_empty(&lst->head)) return lst->head.next; return NULL; } /* * ======== lst_get_head ======== * Purpose: * Pops the head off the list and returns a pointer to it. * Details: * If the list is empty, returns NULL. * Else, removes the element at the head of the list, making the next * element the head of the list. * The head is removed by making the tail element of the list point its * "next" pointer at the next element after the head, and by making the * "prev" pointer of the next element after the head point at the tail * element. So the next element after the head becomes the new head of * the list. * Parameters: * lst: Pointer to list control structure of list whose head * element is to be removed * Returns: * Pointer to element that was at the head of the list (success) * NULL No elements in list * Requires: * - LST initialized. * - lst != NULL. * Ensures: * Notes: * Because the tail of the list points forward (its "next" pointer) to * the head of the list, and the head of the list points backward (its * "prev" pointer) to the tail of the list, this list is circular. */ static inline struct list_head *lst_get_head(struct lst_list *lst) { struct list_head *elem_list; if (!lst || list_empty(&lst->head)) return NULL; elem_list = lst->head.next; lst->head.next = elem_list->next; elem_list->next->prev = &lst->head; return elem_list; } /* * ======== lst_init_elem ======== * Purpose: * Initializes a list element to default (cleared) values * Details: * Parameters: * elem_list: Pointer to list element to be reset * Returns: * Requires: * LST initialized. * Ensures: * Notes: * This function must not be called to "reset" an element in the middle * of a list chain -- that would break the chain. * */ static inline void lst_init_elem(struct list_head *elem_list) { if (elem_list) { elem_list->next = NULL; elem_list->prev = NULL; } } /* * ======== lst_insert_before ======== * Purpose: * Insert the element before the existing element. * Parameters: * lst: Pointer to list control structure. * elem_list: Pointer to element in list to insert. * elem_existing: Pointer to existing list element. * Returns: * Requires: * - LST initialized. * - lst != NULL. * - elem_list != NULL. * - elem_existing != NULL. * Ensures: */ static inline void lst_insert_before(struct lst_list *lst, struct list_head *elem_list, struct list_head *elem_existing) { if (lst && elem_list && elem_existing) list_add_tail(elem_list, elem_existing); } /* * ======== lst_next ======== * Purpose: * Returns a pointer to the next element of the list, or NULL if the next * element is the head of the list or the list is empty. * Parameters: * lst: Pointer to list control structure. * cur_elem: Pointer to element in list to remove. * Returns: * Pointer to list element, or NULL. * Requires: * - LST initialized. * - lst != NULL. * - cur_elem != NULL. * Ensures: */ static inline struct list_head *lst_next(struct lst_list *lst, struct list_head *cur_elem) { if (lst && !list_empty(&lst->head) && cur_elem && (cur_elem->next != &lst->head)) return cur_elem->next; return NULL; } /* * ======== lst_put_tail ======== * Purpose: * Adds the specified element to the tail of the list * Details: * Sets new element's "prev" pointer to the address previously held by * the head element's prev pointer. This is the previous tail member of * the list. * Sets the new head's prev pointer to the address of the element. * Sets next pointer of the previous tail member of the list to point to * the new element (rather than the head, which it had been pointing at). * Sets new element's next pointer to the address of the head element. * Sets head's prev pointer to the address of the new element. * Parameters: * lst: Pointer to list control structure to which *elem_list will be * added * elem_list: Pointer to list element to be added * Returns: * Void * Requires: * *elem_list and *lst must both exist. * LST initialized. * Ensures: * Notes: * Because the tail is always "just before" the head of the list (the * tail's "next" pointer points at the head of the list, and the head's * "prev" pointer points at the tail of the list), the list is circular. */ static inline void lst_put_tail(struct lst_list *lst, struct list_head *elem_list) { if (lst && elem_list) list_add_tail(elem_list, &lst->head); } /* * ======== lst_remove_elem ======== * Purpose: * Removes (unlinks) the given element from the list, if the list is not * empty. Does not free the list element. * Parameters: * lst: Pointer to list control structure. * cur_elem: Pointer to element in list to remove. * Returns: * Requires: * - LST initialized. * - lst != NULL. * - cur_elem != NULL. * Ensures: */ static inline void lst_remove_elem(struct lst_list *lst, struct list_head *cur_elem) { if (lst && !list_empty(&lst->head) && cur_elem) list_del_init(cur_elem); } #endif /* LIST_ */