diff options
author | Roland McGrath <roland@gnu.org> | 2000-02-04 03:21:18 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 2000-02-04 03:21:18 +0000 |
commit | 9fd51e9b0ad33a89a83fdbbb66bd20d85f7893fb (patch) | |
tree | 8845b79f170028cb4380045c50277bbf075b5b7d /pfinet/linux-src/include/linux/dlists.h | |
download | hurd-9fd51e9b0ad33a89a83fdbbb66bd20d85f7893fb.tar.gz hurd-9fd51e9b0ad33a89a83fdbbb66bd20d85f7893fb.tar.bz2 hurd-9fd51e9b0ad33a89a83fdbbb66bd20d85f7893fb.zip |
Import of Linux 2.2.12 subset (ipv4 stack and related)
Diffstat (limited to 'pfinet/linux-src/include/linux/dlists.h')
-rw-r--r-- | pfinet/linux-src/include/linux/dlists.h | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/pfinet/linux-src/include/linux/dlists.h b/pfinet/linux-src/include/linux/dlists.h new file mode 100644 index 00000000..f92485e4 --- /dev/null +++ b/pfinet/linux-src/include/linux/dlists.h @@ -0,0 +1,108 @@ +#ifndef DLISTS_H +#define DLISTS_H +/* + * include/linux/dlists.h - macros for double linked lists + * + * Copyright (C) 1997, Thomas Schoebel-Theuer, + * <schoebel@informatik.uni-stuttgart.de>. + */ + +/* dlists are cyclic ringlists, so the last element cannot be tested + * for NULL. Use the following construct for traversing cyclic lists: + * ptr = anchor; + * if(ptr) do { + * ... + * ptr = ptr->{something}_{next,prev}; + * } while(ptr != anchor); + * The effort here is paid off with much simpler inserts/removes. + * Examples for usage of these macros can be found in fs/ninode.c. + * To access the last element in constant time, simply use + * anchor->{something}_prev. + */ + +#define DEF_GENERIC_INSERT(CHANGE,PREFIX,NAME,TYPE,NEXT,PREV) \ +static inline void PREFIX##NAME(TYPE ** anchor, TYPE * elem)\ +{\ + TYPE * oldfirst = *anchor;\ + if(!oldfirst) {\ + elem->NEXT = elem->PREV = *anchor = elem;\ + } else {\ + elem->PREV = oldfirst->PREV;\ + elem->NEXT = oldfirst;\ + oldfirst->PREV->NEXT = elem;\ + oldfirst->PREV = elem;\ + if(CHANGE)\ + *anchor = elem;\ + }\ +} + +/* insert_* is always at the first position */ +#define DEF_INSERT(NAME,TYPE,NEXT,PREV) \ + DEF_GENERIC_INSERT(1,insert_,NAME,TYPE,NEXT,PREV) + +/* append_* is always at the tail */ +#define DEF_APPEND(NAME,TYPE,NEXT,PREV) \ + DEF_GENERIC_INSERT(0,append_,NAME,TYPE,NEXT,PREV) + +/* use this to insert _before_ oldelem somewhere in the middle of the list. + * the list must not be empty, and oldelem must be already a member.*/ +#define DEF_INSERT_MIDDLE(NAME,TYPE) \ +static inline void insert_middle_##NAME(TYPE ** anchor, TYPE * oldelem, TYPE * elem)\ +{\ + int status = (oldelem == *anchor);\ + insert_##NAME(&oldelem, elem);\ + if(status)\ + *anchor = oldelem;\ +} + +/* remove can be done with any element in the list */ +#define DEF_REMOVE(NAME,TYPE,NEXT,PREV) \ +static inline void remove_##NAME(TYPE ** anchor, TYPE * elem)\ +{\ + TYPE * next = elem->NEXT;\ + if(next == elem) {\ + *anchor = NULL;\ + } else {\ + TYPE * prev = elem->PREV;\ + prev->NEXT = next;\ + next->PREV = prev;\ + elem->NEXT = elem->PREV = NULL;/*leave this during debugging*/\ + if(*anchor == elem)\ + *anchor = next;\ + }\ +} + + +/* According to ideas from David S. Miller, here is a slightly + * more efficient plug-in compatible version using non-cyclic lists, + * but allowing neither backward traversals nor constant time access + * to the last element. + * Note that although the interface is the same, the PPREV pointer must be + * declared doubly indirect and the test for end-of-list is different. */ + +/* as above, this inserts always at the head */ +#define DEF_LIN_INSERT(NAME,TYPE,NEXT,PPREV) \ +static inline void insert_##NAME(TYPE ** anchor, TYPE * elem)\ +{\ + TYPE * first;\ + if((elem->NEXT = first = *anchor))\ + first->PPREV = &elem->NEXT;\ + *anchor = elem;\ + elem->PPREV = anchor;\ +} + +/* as above, this works with any list element */ +#define DEF_LIN_REMOVE(NAME,TYPE,NEXT,PPREV) \ +static inline void remove_##NAME(TYPE ** anchor, TYPE * elem)\ +{\ + TYPE * pprev;\ + if((pprev = elem->PPREV)) {\ + TYPE * next;\ + if((next = elem->NEXT))\ + next->PPREV = pprev;\ + *pprev = next;\ + elem->PPREV = elem->NEXT = NULL; /*leave this for debugging*/\ + }\ +} + +#endif |