| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349 | /* Copyright (C) 2017 University of North Carolina at Chapel Hill and   Fortanix, Inc.   This file is part of Graphene Library OS.   Graphene Library OS 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 3 of the   License, or (at your option) any later version.   Graphene Library OS 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.   You should have received a copy of the GNU Lesser General Public License   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *//* * list.h * * This file defines the list API for the PAL and Library OS. */#ifndef LIST_H#define LIST_H// Use a new list implementation/* This list implementation stores a pointer to the next object and casts to * the object, rather than using offsetof().  We try to encapsulate this * change in a macro for declarations, which generates a type declaration for * each list object (giving marginally more help from the compiler * in detecting bugs. * * In particular, there is a small trade-off in that the association between * list heads and nodes is more explicit and a few more casting errors can be * caught by the compiler, but we add a parameter to some functions (well, * macros) to pass the field of the struct. *//* How-to: * * Each list has a pointer (listp) type, and a node (list)type.  We assume * list nodes are embedded in a larger structure; the name of this structure * is used as part of the list type. * * To define a listp/list pair for a struct foo: * * DEFINE_LIST(foo); * struct foo { *   int x; *   LIST_TYPE(foo) list; // The list node * }; * * DEFINE_LISTP(foo); * static LISTP_TYPE(foo) the_list = LISTP_INIT; * * ----- * * From here, you can use LISTP_ADD variants to add an object from the list: * * struct foo *f = malloc(sizeof(struct foo)); * f->x = 1; * INIT_LIST_HEAD(f, list); // The second parameter is the structure member * LISTP_ADD(f, &the_list, list); * * ----- * * There are a number of add variants, some that add in a given position, * others that add to the head or the tail. * * You can search for an object using a variant of listp_for_each_entry. The * safe variants are safe against deletion. * * You can remove an object from a list using LISTP_DEL. * * In this example, we delete everything with a key bigger than 5. * * LIST_TYPE(foo) *f, *n; // n is not used, just for scratch space * LISTP_FOR_EACH_ENTRY_SAFE(f, n, &the_list, list) { *    if (f->x > 4) { *         LISTP_DEL(f, &the_list, list); *         free(f); *    } * } * * * LISTP_SPLICE moves an entire listp onto another, and list_move_tail takes * an element off of one list and places it on another. * * static LISTP_TYPE(foo) other_list; // Assume it is full of goodies *  // Move everything on other_list to the_list * LISTP_SPLICE_TAIL(&other_list, &the_list, list, foo); // the third argument *                                                       // is the field; the *                                                       // fourth is the type *                                                       // of the nodes (not *                                                       // the head pointer). * * // Use LISTP_EMPTY to test for emptiness of the list * assert(LISTP_EMPTY(&other_ist)); * *  // Now move back anythign less than 6 back to other_list * LISTP_FOR_EACH_ENTRY_SAFE(f, n, &the_list, list) { *    if (f->x < 6) *         LISTP_MOVE_TAIL(f, &other_list, &the_list, list); * } * */// Maybe TODO?//// Change the order of (node, head, field) -> (head, node, field)// drop the listp type to reduce code changes?// Cleaner way to express types// Add assertion to delete (in debugging mode) that item is on list// There are a few places where knowing the listp for deletion is cumbersome;//    maybe drop this requirement?#include <stdbool.h>#ifdef DEBUG#include <assert.h>#define LIST_ASSERT(COND) assert(COND)#else#define LIST_ASSERT(COND)#endif#define LIST_TYPE(STRUCT_NAME)  struct list_head##_##STRUCT_NAME#define LISTP_TYPE(STRUCT_NAME) struct listp##_##STRUCT_NAME/* Declare the enclosing struct for convenience, on * the assumption that this is primarily used in structure * definitions, and harmless if duplicated. */#define DEFINE_LIST(STRUCT_NAME)  \    struct STRUCT_NAME;           \    LIST_TYPE(STRUCT_NAME) {      \        struct STRUCT_NAME* next; \        struct STRUCT_NAME* prev; \    }/* We use LISTP for pointers to a list.  This project only really needs * doubly-linked lists.  We used hlists to get a single pointer for more * efficient hash tables, but they were still effectively doubly-linked * lists. */#define DEFINE_LISTP(STRUCT)  \    LISTP_TYPE(STRUCT) {      \        struct STRUCT* first; \    }#define LISTP_INIT {NULL}/* A node not on a list uses NULL; on a list, you * store self pointers */#define INIT_LIST_HEAD(OBJECT, FIELD) \    do {                              \        (OBJECT)->FIELD.next = NULL;  \        (OBJECT)->FIELD.prev = NULL;  \    } while (0)#define INIT_LISTP(OBJECT)      \    do {                        \        (OBJECT)->first = NULL; \    } while (0)#define LISTP_EMPTY(HEAD) ((HEAD)->first == NULL)#define LIST_EMPTY(NODE, FIELD) ((NODE)->FIELD.next == NULL)/* This helper takes 3 arguments - all should be containing structures, * and the field to use for the offset to the list node */#define __LIST_ADD(NEW, NEXT, PREV, FIELD)       \    do {                                         \        __typeof__(NEW) __tmp_next = (NEXT);     \        __typeof__(NEW) __tmp_prev = (PREV);     \        __tmp_prev->FIELD.next     = (NEW);      \        __tmp_next->FIELD.prev     = (NEW);      \        (NEW)->FIELD.next          = __tmp_next; \        (NEW)->FIELD.prev          = __tmp_prev; \    } while (0)#define LIST_ADD(NEW, HEAD, FIELD) __LIST_ADD(NEW, (HEAD)->FIELD.next, HEAD, FIELD)#define LISTP_ADD(NEW, HEAD, FIELD)                                           \    do {                                                                      \        if ((HEAD)->first == NULL) {                                          \            (HEAD)->first     = (NEW);                                        \            (NEW)->FIELD.next = (NEW);                                        \            (NEW)->FIELD.prev = (NEW);                                        \        } else {                                                              \            __LIST_ADD(NEW, (HEAD)->first, (HEAD)->first->FIELD.prev, FIELD); \            (HEAD)->first = (NEW);                                            \        }                                                                     \    } while (0)/* If NODE is defined, add NEW after NODE; if not, * put NEW at the front of the list */#define LISTP_ADD_AFTER(NEW, NODE, HEAD, FIELD) \    do {                                        \        if (NODE)                               \            LIST_ADD(NEW, NODE, FIELD);         \        else                                    \            LISTP_ADD(NEW, HEAD, FIELD);        \    } while (0)#define LIST_ADD_TAIL(NEW, HEAD, FIELD) __LIST_ADD(NEW, HEAD, (HEAD)->FIELD.prev, FIELD)#define LISTP_ADD_TAIL(NEW, HEAD, FIELD)              \    do {                                              \        if ((HEAD)->first == NULL) {                  \            (HEAD)->first     = (NEW);                \            (NEW)->FIELD.next = (NEW);                \            (NEW)->FIELD.prev = (NEW);                \        } else                                        \            LIST_ADD_TAIL(NEW, (HEAD)->first, FIELD); \    } while (0)/* Or deletion needs to know the list root */#define LISTP_DEL(NODE, HEAD, FIELD)                           \    do {                                                       \        if ((HEAD)->first == (NODE)) {                         \            if ((NODE)->FIELD.next == (NODE)) {                \                (HEAD)->first = NULL;                          \            } else {                                           \                (HEAD)->first = (NODE)->FIELD.next;            \            }                                                  \        }                                                      \        LIST_ASSERT((NODE)->FIELD.prev->FIELD.next == (NODE)); \        LIST_ASSERT((NODE)->FIELD.next->FIELD.prev == (NODE)); \        (NODE)->FIELD.prev->FIELD.next = (NODE)->FIELD.next;   \        (NODE)->FIELD.next->FIELD.prev = (NODE)->FIELD.prev;   \    } while (0)#define LISTP_DEL_INIT(NODE, HEAD, FIELD) \    do {                                  \        LISTP_DEL(NODE, HEAD, FIELD);     \        INIT_LIST_HEAD(NODE, FIELD);      \    } while (0)/* Keep vestigial TYPE and FIELD parameters to minimize disruption * when switching from Linux list implementation */#define LISTP_FIRST_ENTRY(LISTP, TYPE, FIELD) ((LISTP)->first)/* New API: return last entry in list */#define LISTP_LAST_ENTRY(LISTP, TYPE, FIELD) ((LISTP)->first->FIELD.prev)/* New API: return next entry in list */#define LISTP_NEXT_ENTRY(NODE, LISTP, FIELD) \    ((NODE) == (LISTP)->first->FIELD.prev ? NULL : (NODE)->FIELD.next)/* New API: return previous entry in list */#define LISTP_PREV_ENTRY(NODE, LISTP, FIELD) ((NODE) == (LISTP)->first ? NULL : (NODE)->FIELD.prev)/* Vestigial - for compat with Linux list code; rename to listp? */#define LIST_ENTRY(LISTP, TYPE, FIELD) (LISTP)#define LISTP_FOR_EACH_ENTRY(CURSOR, HEAD, FIELD)                       \    for (bool first_iter = ((CURSOR) = (HEAD)->first, !!(HEAD)->first); \         first_iter || (CURSOR) != (HEAD)->first;                       \         (CURSOR) = (CURSOR)->FIELD.next, first_iter = false)#define LISTP_FOR_EACH_ENTRY_REVERSE(CURSOR, HEAD, FIELD)                             \    for (bool first_iter =                                                            \             ((CURSOR) = ((HEAD)->first ? (HEAD)->first->FIELD.prev : (HEAD)->first), \             !!(HEAD)->first);                                                        \         first_iter || ((CURSOR) && (CURSOR)->FIELD.next != (HEAD)->first);           \         (CURSOR) = (CURSOR)->FIELD.prev, first_iter = false)#define LISTP_FOR_EACH_ENTRY_SAFE(CURSOR, TMP, HEAD, FIELD)                                        \    for (bool first_iter = ((CURSOR) = (HEAD)->first,                                              \                           (TMP) = ((CURSOR) ? (CURSOR)->FIELD.next : (CURSOR)), !!(HEAD)->first); \         (HEAD)->first &&                                                                          \         (first_iter || (CURSOR) != (HEAD)->first);                                                \         /* Handle the case where the first element was removed. */                                \         first_iter = first_iter && (TMP) != (CURSOR) && (HEAD)->first == (TMP), (CURSOR) = (TMP), \              (TMP) = (TMP)->FIELD.next)/* Continue safe iteration with CURSOR->next */#define LISTP_FOR_EACH_ENTRY_SAFE_CONTINUE(CURSOR, TMP, HEAD, FIELD)    \    for ((CURSOR) = (CURSOR)->FIELD.next, (TMP) = (CURSOR)->FIELD.next; \         (CURSOR) != (HEAD)->first && (HEAD)->first; (CURSOR) = (TMP), (TMP) = (TMP)->FIELD.next)/* Assertion code written in Graphene project */#define CHECK_LIST_HEAD(TYPE, HEAD, FIELD)                               \    do {                                                                 \        TYPE pos;                                                        \        LISTP_FOR_EACH_ENTRY(pos, HEAD, FIELD) {                         \            assert((pos->FIELD.prev != pos && pos->FIELD.next != pos) || \                   (pos->FIELD.prev == pos && pos->FIELD.next == pos));  \            assert(pos->FIELD.prev->FIELD.next == pos);                  \            assert(pos->FIELD.next->FIELD.prev == pos);                  \        }                                                                \    } while (0)// Add NEW to OLD at position first (assuming first is all we need for now)// Can probably drop TYPE with some preprocessor smarts#define LISTP_SPLICE(NEW, OLD, FIELD, TYPE)                                      \    do {                                                                         \        if (!LISTP_EMPTY(NEW)) {                                                 \            if (LISTP_EMPTY(OLD)) {                                              \                (OLD)->first = (NEW)->first;                                     \            } else {                                                             \                struct TYPE* last_old                = (OLD)->first->FIELD.prev; \                (OLD)->first->FIELD.prev->FIELD.next = (NEW)->first;             \                (OLD)->first->FIELD.prev             = (NEW)->first->FIELD.prev; \                (NEW)->first->FIELD.prev->FIELD.next = (OLD)->first;             \                (NEW)->first->FIELD.prev             = last_old;                 \                (OLD)->first                         = (NEW)->first;             \            }                                                                    \        }                                                                        \    } while (0)// Add NEW to OLD at last position// Can probably drop TYPE with some preprocessor smarts#define LISTP_SPLICE_TAIL(NEW, OLD, FIELD, TYPE)                                 \    do {                                                                         \        if (!LISTP_EMPTY(NEW)) {                                                 \            if (LISTP_EMPTY(OLD)) {                                              \                (OLD)->first = (NEW)->first;                                     \            } else {                                                             \                struct TYPE* last_old                = (OLD)->first->FIELD.prev; \                last_old->FIELD.next                 = (NEW)->first;             \                (OLD)->first->FIELD.prev             = (NEW)->first->FIELD.prev; \                (NEW)->first->FIELD.prev->FIELD.next = (OLD)->first;             \                (NEW)->first->FIELD.prev             = last_old;                 \            }                                                                    \        }                                                                        \    } while (0)#define LISTP_SPLICE_INIT(NEW, OLD, FIELD, TYPE) \    do {                                         \        LISTP_SPLICE(NEW, OLD, FIELD, TYPE);     \        INIT_LISTP(NEW);                         \    } while (0);#define LISTP_SPLICE_TAIL_INIT(NEW, OLD, FIELD, TYPE) \    do {                                              \        LISTP_SPLICE_TAIL(NEW, OLD, FIELD, TYPE);     \        INIT_LISTP(NEW);                              \    } while (0);// list_move_tail - delete from OLD, make tail of NEW#define LISTP_MOVE_TAIL(NODE, NEW, OLD, FIELD) \    do {                                       \        LISTP_DEL_INIT(NODE, OLD, FIELD);      \        LISTP_ADD_TAIL(NODE, NEW, FIELD);      \    } while (0)#endif  // LIST_H
 |