From 4a2c524e14af49551065b5705942ffce48c16b70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Thu, 28 Nov 2013 18:30:01 +0100 Subject: [PATCH] Add tailq linked list --- include/ucore/tailq.h | 141 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 include/ucore/tailq.h diff --git a/include/ucore/tailq.h b/include/ucore/tailq.h new file mode 100644 index 0000000..08a2d47 --- /dev/null +++ b/include/ucore/tailq.h @@ -0,0 +1,141 @@ +#ifndef UC_TAILQ_H_ +#define UC_TAILQ_H_ + +#ifdef __GNUC__ +//#define UC_INLINE __attribute__((always_inline,flatten)) +#define UC_INLINE inline +#else +#define UC_INLINE inline +#endif +/** + * Doubly Linked List. + * It is used either as + * 1) a linked list "head" - a node serving to hold pointer to the + * first and last node in a list + * 2) a linked list entry - a node in the linked list + * + * This is variant of sys/queue.h TAILQ which avoids too many conditionals. + * The struct TailQ serves both as an entry/node in a linked list, + * and as head of a linked list. + * + * Note that unlike the sys/queue.h TAILQ, the list does + * not begin/end with a NULL pointer. For a entry node, the beginning/end + * is a back pointer to the head node. + * Traditional linked list TailQ + * node->prev == NULL node->prev == head + * node->next == NULL node->next == head + * + * Do not ever add an entry that's a NULL pointer. + * + */ +struct TailQ { + //pointer to next element, or for a head node, + //pointer to the first entry + struct TailQ *next; + //pointer to previous element, or for a head node, + //pointer to the last node + struct TailQ *prev; +}; + +#define UC_TAILQ_HEAD_INIT(name) {&(name), &(name)} + +#define UC_TAILQ_HEAD(name)\ +struct TailQ name = UC_TAILQ_HEAD_INIT(name) + + +static UC_INLINE void uc_tailq_init(struct TailQ *head) +{ + head->prev = head; + head->next = head; +} + +/** Test if the tailq is empty + */ +static UC_INLINE int uc_tailq_empty(const struct TailQ *head) +{ + return head->next == head->prev; +} + +/** Insert the entry between prev and next + */ +static UC_INLINE void uc_tailq_insert(struct TailQ *entry, + struct TailQ *prev, + struct TailQ *next) +{ + entry->prev = prev; + prev->next = entry; + + entry->next = next; + next->prev = entry; +} + +/** Insert entry to the tail(end) of the list + */ +static UC_INLINE void uc_tailq_insert_tail(struct TailQ *head, struct TailQ *entry) +{ + //head becomes entry->next, signalling the end of the list + uc_tailq_insert(entry, head->prev, head); +} + +/** Insert entry to the head(start) of the list + */ +static UC_INLINE void uc_tailq_insert_head(struct TailQ *head, struct TailQ *entry) +{ + //head becomes entry->prev, signalling the end of the list + uc_tailq_insert(entry, head, head->next); +} + +/** Remove the entry from the list it is part of. + * (It *must* already be part of a list. + */ +static UC_INLINE void uc_tailq_remove(struct TailQ *entry) +{ + entry->prev->next = entry->next; + entry->next->prev = entry->prev; + +//help catch illegal use: + entry->next = (void*)0x101; + entry->prev = (void*)0x102; +} + +/** Iterate over a tailq. The list cannot be altered while iterating. + * + * @param entry a struct TailQ* to which each element is assigned. + * @param head the struct TailQ* head of the tailq + */ +#define UC_TAILQ_FOREACH(entry, head)\ + for ((entry) = (head)->next; (entry) != (head); (entry) = (entry)->next) + +/** Iterate over a tailq in reverse order. The list cannot be altered while + * iterating. + * + * @param entry a struct TailQ* to which each element is assigned. + * @param head the struct TailQ* head of the tailq + */ +#define UC_TAILQ_FOREACH_REVERSE(entry, head)\ + for ((entry) = (head)->prev; (entry) != (head); (entry) = (entry)->prev) + +/** Iterate over a tailq. safe to remove the entry when iterating. + * + * @param entry a struct TailQ* to which each element is assigned. + * @param nxt a struct TailQ* needed for temporary storage. + * @param head the struct TailQ* head of the tailq + */ +#define UC_TAILQ_FOREACH_SAFE(entry, nxt, head)\ + for ((entry) = (head)->next, nxt = (entry)->next; \ + (entry) != (head); \ + (entry) = (nxt), (nxt) = (entry)->next) + +/** Iterate over a tailq in reverse order. safe to remove the entry when + * iterating. + * + * @param entry a struct TailQ* to which each element is assigned. + * @param prv a struct TailQ* needed for temporary storage. + * @param head the struct TailQ* head of the tailq + */ +#define UC_TAILQ_FOREACH_REVERSE_SAFE(entry, prv, head)\ + for ((entry) = (head)->prev, prev = (entry)->prev; \ + (entry) != (head); \ + (entry) = (prv), (prv) = (entry)->prev) + +#endif