From 04f101c699a0e2b0910fc1ff2006917b00c64895 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Tue, 26 Nov 2013 23:58:50 +0100 Subject: [PATCH 01/15] initialize peer to Unknown --- test/udp_heartbeat.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test/udp_heartbeat.c b/test/udp_heartbeat.c index 4eb3847..f964bca 100644 --- a/test/udp_heartbeat.c +++ b/test/udp_heartbeat.c @@ -102,6 +102,7 @@ void peer_add_addr(struct HBContext *ctx, const struct sockaddr_in *addr) peer->timer.callback = peer_timer_cb; peer->timer.cookie_ptr = ctx; + peer->state = PeerUnknown; sec = rand() % PEER_HB_SEC; usec = rand() % 1000000; 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 02/15] 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 From 6156fcbbb5c1f123ebda3a4df4beaba9efcc68ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Thu, 28 Nov 2013 18:30:14 +0100 Subject: [PATCH 03/15] Add tailq example --- test/tailq_example.c | 89 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 test/tailq_example.c diff --git a/test/tailq_example.c b/test/tailq_example.c new file mode 100644 index 0000000..11419b6 --- /dev/null +++ b/test/tailq_example.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include + +struct Block { + char text[64]; + struct TailQ blocks; +}; + +struct File { + char name[128]; + struct TailQ head; +}; + +void add_block(struct File *f, const char *txt) +{ + struct Block *b = malloc(sizeof *b); + strcpy(b->text,txt); + uc_tailq_insert_tail(&f->head, &b->blocks); +} + +void print_file(struct File *f) +{ + struct TailQ *entry; + printf("File: %s\n", f->name); + UC_TAILQ_FOREACH(entry, &f->head) { + struct Block *b = UC_CONTAINER_OF(entry, struct Block, blocks); + printf("Block: %s\n", b->text); + } +} + +void delete_block(struct File *f, const char *txt) +{ + struct TailQ *entry, *next; + UC_TAILQ_FOREACH_SAFE(entry, next, &f->head) { + struct Block *b = UC_CONTAINER_OF(entry, struct Block, blocks); + if (strcmp(txt, b->text) == 0) { + uc_tailq_remove(entry); + free(b); + } + } +} + +void delete_all_blocks(struct File *f) +{ + struct TailQ *entry, *next; + UC_TAILQ_FOREACH_SAFE(entry, next, &f->head) { + struct Block *b = UC_CONTAINER_OF(entry, struct Block, blocks); + free(b); + } + uc_tailq_init(&f->head); +} + +int main(void) +{ + struct File f; + uc_tailq_init(&f.head); + printf("Is Empty: %d\n", uc_tailq_empty(&f.head)); + strcpy(f.name,"Test.f"); + add_block(&f,"one"); + add_block(&f,"two"); + add_block(&f,"three"); + + print_file(&f); + printf("Is Empty: %d\n", uc_tailq_empty(&f.head)); + + puts("\nDeleting three"); + delete_block(&f, "three"); + print_file(&f); + + puts("\nAdding 2 blocks"); + add_block(&f,"three"); + add_block(&f,"three"); + print_file(&f); + + puts("\nDeleting three"); + delete_block(&f, "three"); + print_file(&f); + + delete_all_blocks(&f); + printf("Is Empty: %d\n", uc_tailq_empty(&f.head)); + + + return 0; +} + + From 80d73629bfca732e6bb847708689c8a03933b963 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Thu, 28 Nov 2013 20:01:25 +0100 Subject: [PATCH 04/15] add uc_tailq_link() and use it in uc_tailq_remove() --- include/ucore/tailq.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/include/ucore/tailq.h b/include/ucore/tailq.h index 08a2d47..ab4f0e2 100644 --- a/include/ucore/tailq.h +++ b/include/ucore/tailq.h @@ -85,13 +85,20 @@ static UC_INLINE void uc_tailq_insert_head(struct TailQ *head, struct TailQ *ent uc_tailq_insert(entry, head, head->next); } +/** Link the first and second entry together, + */ +static UC_INLINE void uc_tailq_link(struct TailQ *first, struct TailQ *second) +{ + first->next = second; + second->prev = first; +} + /** 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; + uc_tailq_link(entry->prev, entry->next); //help catch illegal use: entry->next = (void*)0x101; From f5d918e77d0e3eebfd881d2820b65205ffe6f36f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Thu, 28 Nov 2013 22:50:03 +0100 Subject: [PATCH 05/15] Add a _move_head and _move_tail function to move a node Also be more consisten in cometns about tailq instead of list --- include/ucore/tailq.h | 37 ++++++++++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/include/ucore/tailq.h b/include/ucore/tailq.h index ab4f0e2..3a4acda 100644 --- a/include/ucore/tailq.h +++ b/include/ucore/tailq.h @@ -21,7 +21,8 @@ * 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 + * + * Traditional linked list TailQ * node->prev == NULL node->prev == head * node->next == NULL node->next == head * @@ -69,19 +70,19 @@ static UC_INLINE void uc_tailq_insert(struct TailQ *entry, next->prev = entry; } -/** Insert entry to the tail(end) of the list +/** Insert entry to the tail(end) of the tailq */ static UC_INLINE void uc_tailq_insert_tail(struct TailQ *head, struct TailQ *entry) { - //head becomes entry->next, signalling the end of the list + //head becomes entry->next, signalling the end of the tailq uc_tailq_insert(entry, head->prev, head); } -/** Insert entry to the head(start) of the list +/** Insert entry to the head(start) of the tailq */ static UC_INLINE void uc_tailq_insert_head(struct TailQ *head, struct TailQ *entry) { - //head becomes entry->prev, signalling the end of the list + //head becomes entry->prev, signalling the end of the tailq uc_tailq_insert(entry, head, head->next); } @@ -93,8 +94,8 @@ static UC_INLINE void uc_tailq_link(struct TailQ *first, struct TailQ *second) second->prev = first; } -/** Remove the entry from the list it is part of. - * (It *must* already be part of a list. +/** Remove the entry from the tailq it is part of. + * (It *must* already be part of a tailq. */ static UC_INLINE void uc_tailq_remove(struct TailQ *entry) { @@ -105,7 +106,25 @@ static UC_INLINE void uc_tailq_remove(struct TailQ *entry) entry->prev = (void*)0x102; } -/** Iterate over a tailq. The list cannot be altered while iterating. +/** Move entry from its current tailq to the head of another tailq. + * (entry must be part of a tailq) + */ +static UC_INLINE void uc_tailq_move_head(struct TailQ *entry, struct TailQ *head) +{ + uc_tailq_link(entry->prev, entry->next); + uc_taiq_insert(entry, head, head->next); +} + +/** Move entry from its current tailq to the tail of another tailq. + * (entry must be part of a tailq) + */ +static UC_INLINE void uc_tailq_move_tail(struct TailQ *entry, struct TailQ *head) +{ + uc_tailq_link(entry->prev, entry->next); + uc_taiq_insert(entry, head->prev, head); +} + +/** Iterate over a tailq. The tailq 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 @@ -113,7 +132,7 @@ static UC_INLINE void uc_tailq_remove(struct TailQ *entry) #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 +/** Iterate over a tailq in reverse order. The tailq cannot be altered while * iterating. * * @param entry a struct TailQ* to which each element is assigned. From 44b86f2fde37acb4a35fc019fc26a3ae340e3387 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Thu, 28 Nov 2013 23:21:56 +0100 Subject: [PATCH 06/15] Add FIRST/NEXT/LAST/PREV macros, analogous to sys/queue.h --- include/ucore/tailq.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/include/ucore/tailq.h b/include/ucore/tailq.h index 3a4acda..f8e82f4 100644 --- a/include/ucore/tailq.h +++ b/include/ucore/tailq.h @@ -124,6 +124,23 @@ static UC_INLINE void uc_tailq_move_tail(struct TailQ *entry, struct TailQ *head uc_taiq_insert(entry, head->prev, head); } +//FIRST/NEXT/LAST/PREV macros similar to sys/queue.h +//Note that unlike the standard TAILQ, you have to check +// == head instead of == NULL to determine if the tailq entry +// exists + +#define UC_TAILQ_FIRST(head)\ +((head)->next) + +#define UC_TAILQ_NEXT(entry)\ +((entry)->next) + +#define UC_TAILQ_LAST(head)\ +((head)->prev) + +#define UC_TAILQ_PREV(entry)\ +((entry)->prev) + /** Iterate over a tailq. The tailq cannot be altered while iterating. * * @param entry a struct TailQ* to which each element is assigned. From f9ef8d620f9e35619faf0bd5caa8018e93b9271e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Thu, 28 Nov 2013 23:30:44 +0100 Subject: [PATCH 07/15] style cleanups --- include/ucore/utils.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/ucore/utils.h b/include/ucore/utils.h index 0b2e358..f3bedef 100644 --- a/include/ucore/utils.h +++ b/include/ucore/utils.h @@ -60,20 +60,21 @@ const typeof( ((const type *)0)->member ) *__mptr = (ptr); \ /** * Test if x is a power of 2 * - * @param x value + * @param x value, must be an unsigned type * @return 1 if x is a power of 20, 0 if it is not */ #define UC_IS_POW2(x) ((x) && !((x) & (x) - 1)) /** - * * Expands @x and turns it into a string. - * */ + * Expands @x and turns it into a string. + */ #define UC_STRINGIFY(x) UC_STRINGIFY_HLP(x) #define UC_STRINGIFY_HLP(x) #x /** Macro that expands to a string for the current file:line */ #define UC_SRC_LOCATION __FILE__ ":" UC_STRINGIFY(__LINE__) + /** * assert() that is not affected by NDEBUG define */ From ad9021545269d3f6807824abc6766226af4b2405 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Sat, 30 Nov 2013 03:24:43 +0100 Subject: [PATCH 08/15] Add UC_TAILQ_CONTAINER. Fix spelling error --- include/ucore/tailq.h | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/include/ucore/tailq.h b/include/ucore/tailq.h index f8e82f4..a890b93 100644 --- a/include/ucore/tailq.h +++ b/include/ucore/tailq.h @@ -2,8 +2,7 @@ #define UC_TAILQ_H_ #ifdef __GNUC__ -//#define UC_INLINE __attribute__((always_inline,flatten)) -#define UC_INLINE inline +#define UC_INLINE inline __attribute__((always_inline,flatten)) #else #define UC_INLINE inline #endif @@ -43,6 +42,15 @@ struct TailQ { #define UC_TAILQ_HEAD(name)\ struct TailQ name = UC_TAILQ_HEAD_INIT(name) +//given 'ptr' as a pointer to a struct 'member', +//find the struct that ptr is the member of, where +//'type' is the type of the containing struct +//This is basically UC_CONTAINER_OF in ucore/utils.h, this is here +//to make tailq.h a standalone header +#define UC_TAILQ_CONTAINER(ptr, type, member) ({\ +typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)((void *)(unsigned char *)__mptr - offsetof(type, member) ); }) + static UC_INLINE void uc_tailq_init(struct TailQ *head) { @@ -112,7 +120,7 @@ static UC_INLINE void uc_tailq_remove(struct TailQ *entry) static UC_INLINE void uc_tailq_move_head(struct TailQ *entry, struct TailQ *head) { uc_tailq_link(entry->prev, entry->next); - uc_taiq_insert(entry, head, head->next); + uc_tailq_insert(entry, head, head->next); } /** Move entry from its current tailq to the tail of another tailq. @@ -121,7 +129,7 @@ static UC_INLINE void uc_tailq_move_head(struct TailQ *entry, struct TailQ *head static UC_INLINE void uc_tailq_move_tail(struct TailQ *entry, struct TailQ *head) { uc_tailq_link(entry->prev, entry->next); - uc_taiq_insert(entry, head->prev, head); + uc_tailq_insert(entry, head->prev, head); } //FIRST/NEXT/LAST/PREV macros similar to sys/queue.h From 6706d59b4bb201ea2c30a27477a56e10f31a2f74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Sat, 30 Nov 2013 03:26:45 +0100 Subject: [PATCH 09/15] undef UC_INLINE --- include/ucore/tailq.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/ucore/tailq.h b/include/ucore/tailq.h index a890b93..3e4ce17 100644 --- a/include/ucore/tailq.h +++ b/include/ucore/tailq.h @@ -189,4 +189,6 @@ static UC_INLINE void uc_tailq_move_tail(struct TailQ *entry, struct TailQ *head (entry) != (head); \ (entry) = (prv), (prv) = (entry)->prev) +#undef UC_INLINE + #endif From ec63c1e88f71bc94cf13110c8830ff745ea1add9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Sat, 30 Nov 2013 04:39:59 +0100 Subject: [PATCH 10/15] Guard the UC_DEBUGF/UC_DEBUGFR with do{}while(0) --- include/ucore/logging.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/ucore/logging.h b/include/ucore/logging.h index bbaebe0..3da4baa 100644 --- a/include/ucore/logging.h +++ b/include/ucore/logging.h @@ -280,8 +280,8 @@ void uc_logf(int log_level, int module, int raw, # define UC_DEBUGFR(mod, fmt, ...)\ uc_logf(UC_LL_DEBUG, mod,1 , UC_SRC_LOCATION, fmt, ## __VA_ARGS__) #else -# define UC_DEBUGF(mod, fmt, ...) -# define UC_DEBUGFR(mod, fmt, ...) +# define UC_DEBUGF(mod, fmt, ...) do {} while (0) +# define UC_DEBUGFR(mod, fmt, ...) do {} while (0) #endif /** Main macro that should be used for logging. From bcafaace292642c4cabeb79bfa136340c29df5fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Sat, 30 Nov 2013 04:48:26 +0100 Subject: [PATCH 11/15] Fix the log level string of NONE. --- include/ucore/logging.h | 2 +- src/logging.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/ucore/logging.h b/include/ucore/logging.h index 3da4baa..b0a956f 100644 --- a/include/ucore/logging.h +++ b/include/ucore/logging.h @@ -239,7 +239,7 @@ void uc_log_destination_set_module_loglevel( * SHORT_NAME_1=LEVEL:SHORT_NAME_2=LEVEL:SHORT_NAME_N=LEVEL * * The SHORT_NAME_N is the .short_name within a struct uc_log_module - * LEVEL is one of DEBUG,INFO, WARNING or ERROR + * LEVEL is one of DEBUG, INFO, WARNING, ERROR or NONE * Example: * DB=DEBUG:IO=ERROR:POLLER=INFO * diff --git a/src/logging.c b/src/logging.c index 248e548..24445cd 100644 --- a/src/logging.c +++ b/src/logging.c @@ -75,6 +75,7 @@ static const char *const g_log_levels[] = { "WARNING", "UNKNOWN_6", "ERROR", + "UNKNOWN_8", "NONE" }; From 6dc59ccbf8d15202a970ce645a936832620c744b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Sat, 30 Nov 2013 13:40:05 +0100 Subject: [PATCH 12/15] Add macros for iterating the containing entry --- include/ucore/tailq.h | 74 ++++++++++++++++++++++++++++++++++++++----- test/tailq_example.c | 36 +++++++++++++-------- 2 files changed, 88 insertions(+), 22 deletions(-) diff --git a/include/ucore/tailq.h b/include/ucore/tailq.h index 3e4ce17..761259a 100644 --- a/include/ucore/tailq.h +++ b/include/ucore/tailq.h @@ -155,16 +155,44 @@ static UC_INLINE void uc_tailq_move_tail(struct TailQ *entry, struct TailQ *head * @param head the struct TailQ* head of the tailq */ #define UC_TAILQ_FOREACH(entry, head)\ - for ((entry) = (head)->next; (entry) != (head); (entry) = (entry)->next) + for ((entry) = UC_TAILQ_FIRST(head); \ + (entry) != (head); \ + (entry) = UC_TAILQ_NEXT(entry)) -/** Iterate over a tailq in reverse order. The tailq cannot be altered while - * iterating. +/** Iterate over the containing element in a tailq. + * The tailq cannot be altered while iterating. + * + * @param ptr a pointer to the struct which the tailq nodes are member of + * @param member the member of ptr that is the tailq node + * @param head the struct TailQ* head of the tailq + */ +#define UC_TAILQ_FOREACH_CONTAINER(ptr, member, head)\ + for ((ptr) = UC_TAILQ_CONTAINER(UC_TAILQ_FIRST(head), typeof(*ptr), member);\ + &(ptr)->member != (head);\ + (ptr) = UC_TAILQ_CONTAINER(UC_TAILQ_NEXT(&(ptr)->member), typeof(*ptr), member)) + +/** Iterate over a tailq in reverse order. + * The tailq 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) + for ((entry) = UC_TAILQ_LAST(entry); \ + (entry) != (head); \ + (entry) = UC_TAILQ_PREV(entry) + +/** Iterate over the containing element in a tailq in reverse. + * The tailq cannot be altered while iterating. + * + * @param ptr a pointer to the struct which the tailq nodes are member of + * @param member the member of ptr that is the tailq node + * @param head the struct TailQ* head of the tailq + */ +#define UC_TAILQ_FOREACH_REVERSE_CONTAINER(ptr, member, head)\ + for ((ptr) = UC_TAILQ_CONTAINER(UC_TAILQ_LAST(head), typeof(*ptr), member);\ + &(ptr)->member != (head);\ + (ptr) = UC_TAILQ_CONTAINER(UC_TAILQ_PREV(&(ptr)->member), typeof(*ptr), member)) /** Iterate over a tailq. safe to remove the entry when iterating. * @@ -173,9 +201,24 @@ static UC_INLINE void uc_tailq_move_tail(struct TailQ *entry, struct TailQ *head * @param head the struct TailQ* head of the tailq */ #define UC_TAILQ_FOREACH_SAFE(entry, nxt, head)\ - for ((entry) = (head)->next, nxt = (entry)->next; \ + for ((entry) = UC_TAILQ_FIRST(head), (nxt) = UC_TAILQ_NEXT(entry); \ (entry) != (head); \ - (entry) = (nxt), (nxt) = (entry)->next) + (entry) = (nxt), (nxt) = UC_TAILQ_NEXT(entry))\ + +/** Iterate over the containing element in a tailq, safe to remove + * the entry when iterating + * + * @param ptr a pointer to the struct which the tailq nodes are member of + * @param nxt same type as ptr needed for temporary storage. + * @param member the member of ptr that is the tailq node + * @param head the struct TailQ* head of the tailq + */ +#define UC_TAILQ_FOREACH_CONTAINER_SAFE(ptr, nxt, member, head)\ + for ((ptr) = UC_TAILQ_CONTAINER(UC_TAILQ_FIRST(head), typeof(*ptr), member),\ + (nxt) = UC_TAILQ_CONTAINER(UC_TAILQ_NEXT(&(ptr)->member), typeof(*ptr), member);\ + &(ptr)->member != (head);\ + (ptr) = (nxt),\ + (nxt) = UC_TAILQ_CONTAINER(UC_TAILQ_NEXT(&(ptr)->member), typeof(*ptr), member)) /** Iterate over a tailq in reverse order. safe to remove the entry when * iterating. @@ -185,9 +228,24 @@ static UC_INLINE void uc_tailq_move_tail(struct TailQ *entry, struct TailQ *head * @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; \ + for ((entry) = UC_TAILQ_LAST(head), (prv) = UC_TAILQ_PREV(entry); \ (entry) != (head); \ - (entry) = (prv), (prv) = (entry)->prev) + (entry) = (prv), (prv) = UC_TAILQ_PREV(entry))\ + +/** Iterate over the containing element in a tailq in reverse order, safe + * to remove the entry when iterating + * + * @param ptr a pointer to the struct which the tailq nodes are member of + * @param prv same type as ptr needed for temporary storage. + * @param member the member of ptr that is the tailq node + * @param head the struct TailQ* head of the tailq + */ +#define UC_TAILQ_FOREACH_REVERSE_CONTAINER_SAFE(ptr, prv, member, head)\ + for ((ptr) = UC_TAILQ_CONTAINER(UC_TAILQ_LAST(head), typeof(*ptr), member),\ + (prv) = UC_TAILQ_CONTAINER(UC_TAILQ_PREV(&(ptr)->member), typeof(*ptr), member);\ + &(ptr)->member != (head);\ + (ptr) = (prv),\ + (prv) = UC_TAILQ_CONTAINER(UC_TAILQ_NEXT(&(ptr)->member), typeof(*ptr), member)) #undef UC_INLINE diff --git a/test/tailq_example.c b/test/tailq_example.c index 11419b6..e91609f 100644 --- a/test/tailq_example.c +++ b/test/tailq_example.c @@ -23,32 +23,38 @@ void add_block(struct File *f, const char *txt) void print_file(struct File *f) { - struct TailQ *entry; + struct Block *entry; printf("File: %s\n", f->name); - UC_TAILQ_FOREACH(entry, &f->head) { - struct Block *b = UC_CONTAINER_OF(entry, struct Block, blocks); - printf("Block: %s\n", b->text); + UC_TAILQ_FOREACH_CONTAINER(entry, blocks, &f->head) { + printf("Block: %s\n", entry->text); + } +} + +void print_file_reverse(struct File *f) +{ + struct Block *entry; + printf("File: %s\n", f->name); + UC_TAILQ_FOREACH_REVERSE_CONTAINER(entry, blocks, &f->head) { + printf("Block: %s\n", entry->text); } } void delete_block(struct File *f, const char *txt) { - struct TailQ *entry, *next; - UC_TAILQ_FOREACH_SAFE(entry, next, &f->head) { - struct Block *b = UC_CONTAINER_OF(entry, struct Block, blocks); - if (strcmp(txt, b->text) == 0) { - uc_tailq_remove(entry); - free(b); + struct Block *entry, *next; + UC_TAILQ_FOREACH_CONTAINER_SAFE(entry, next, blocks, &f->head) { + if (strcmp(txt, entry->text) == 0) { + uc_tailq_remove(&entry->blocks); + free(entry); } } } void delete_all_blocks(struct File *f) { - struct TailQ *entry, *next; - UC_TAILQ_FOREACH_SAFE(entry, next, &f->head) { - struct Block *b = UC_CONTAINER_OF(entry, struct Block, blocks); - free(b); + struct Block *entry, *next; + UC_TAILQ_FOREACH_CONTAINER_SAFE(entry, next, blocks, &f->head) { + free(entry); } uc_tailq_init(&f->head); } @@ -74,6 +80,8 @@ int main(void) add_block(&f,"three"); add_block(&f,"three"); print_file(&f); + puts("\nReverse order:"); + print_file_reverse(&f); puts("\nDeleting three"); delete_block(&f, "three"); From 2ac412917a73fc7862c5a1167b7b0ff74c31d628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Sat, 30 Nov 2013 13:42:49 +0100 Subject: [PATCH 13/15] Fix comment --- include/ucore/tailq.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/ucore/tailq.h b/include/ucore/tailq.h index 761259a..010fb8a 100644 --- a/include/ucore/tailq.h +++ b/include/ucore/tailq.h @@ -134,7 +134,7 @@ static UC_INLINE void uc_tailq_move_tail(struct TailQ *entry, struct TailQ *head //FIRST/NEXT/LAST/PREV macros similar to sys/queue.h //Note that unlike the standard TAILQ, you have to check -// == head instead of == NULL to determine if the tailq entry +// != head instead of != NULL to determine if the tailq entry // exists #define UC_TAILQ_FIRST(head)\ From 96934d7cf7ce4a25b26b247430cc6fd6137d5bc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Sun, 1 Dec 2013 21:12:18 +0100 Subject: [PATCH 14/15] minor name changes to make more sense --- include/ucore/htable.h | 6 +++--- src/htable.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/ucore/htable.h b/include/ucore/htable.h index e5dc9d1..1702c5f 100644 --- a/include/ucore/htable.h +++ b/include/ucore/htable.h @@ -83,7 +83,7 @@ static inline struct UHNode *uc_htable_first_bucket(const struct UHTable *table, * Get the next node in the bucket. * @return next node or NULL */ -static inline struct UHNode *uc_htable_next_bucket(const struct UHNode *node) +static inline struct UHNode *uc_htable_next_in_bucket(const struct UHNode *node) { return node->next; } @@ -112,7 +112,7 @@ static inline struct UHNode *uc_htable_next_hash(const struct UHNode *node) //internal helper -struct UHNode *uc_htable_iter_hlp(struct UHTable *table, size_t bucket); +struct UHNode *uc_htable_iter_hlp(struct UHTable *table, size_t start_bucket); /** Get the first node in the hash table * @@ -151,7 +151,7 @@ void uc_htable_swap(struct UHTable *a, struct UHTable *b); #define UC_HTABLE_FOREACH_BUCKET(table, node_iter, hash)\ for ((node_iter) = uc_htable_first_bucket((table), (hash));\ (node_iter) != NULL;\ - (node_iter) = uc_htable_next_bucket((node_iter))) + (node_iter) = uc_htable_next_in_bucket((node_iter))) /** * Iterate over all nodes that has the given hash. diff --git a/src/htable.c b/src/htable.c index 02fc876..51db6ae 100644 --- a/src/htable.c +++ b/src/htable.c @@ -50,13 +50,13 @@ struct UHNode *uc_htable_next_hash_hlp(struct UHNode *next, size_t hash) } //find a node, starting at bucket -struct UHNode *uc_htable_iter_hlp(struct UHTable *table, size_t bucket) +struct UHNode *uc_htable_iter_hlp(struct UHTable *table, size_t start_bucket) { size_t i; struct UHNode *found = NULL; //search through buckets until a node is found - for (i = bucket; i < table->cnt_buckets; i++) { + for (i = start_bucket; i < table->cnt_buckets; i++) { found = uc_htable_first_bucket(table, i); if (found != NULL) { break; @@ -69,7 +69,7 @@ struct UHNode *uc_htable_next(struct UHTable *table, struct UHNode *node) { struct UHNode *found; - found = uc_htable_next_bucket(node); + found = uc_htable_next_in_bucket(node); if (found == NULL) { size_t current_bucket = uc_htable_bucket(table, node->hash); found = uc_htable_iter_hlp(table, current_bucket + 1); From aa04b6ae330b42f8a2faaa8a038ce7efbf60cb3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Mon, 2 Dec 2013 21:51:26 +0100 Subject: [PATCH 15/15] Remove the wrong heapsort implementation --- include/ucore/heapsort.h | 21 -------------------- src/heapsort.c | 41 ---------------------------------------- 2 files changed, 62 deletions(-) delete mode 100644 include/ucore/heapsort.h delete mode 100644 src/heapsort.c diff --git a/include/ucore/heapsort.h b/include/ucore/heapsort.h deleted file mode 100644 index c5dbf01..0000000 --- a/include/ucore/heapsort.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef UC_HEAPSORT_H_ -#define UC_HEAPSORT_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif -///compare function. Needs only to return < 0 if -//the first element is less than the second -typedef int (*uc_hs_cmp)(const void *, const void *); - -void -uc_heapsort(void *base, size_t count, size_t width, - uc_hs_cmp cmp); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/src/heapsort.c b/src/heapsort.c deleted file mode 100644 index e291c89..0000000 --- a/src/heapsort.c +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include "ucore/heapsort.h" - -static void -uc_sift(unsigned char *base, size_t start, size_t count, size_t width, - uc_hs_cmp cmp) -{ - size_t root = start, child; - - while ((root * 2 + 1) < count) { - child = root * 2 + 1; - if (child < (count - 1) - && cmp(&base[child * width], &base[(child + 1) * width]) < 0) - child++; - - if (cmp(&base[root * width], &base[child * width]) < 0) { - memcpy(base + root * width, base + child * width, width); - root = child; - } else - return; - } -} - -void -uc_heapsort(void *base_, size_t count, size_t width, - uc_hs_cmp cmp) -{ - int start = count / 2 - 1, end = count - 1; - unsigned char *base = base_; - - while (start >= 0) { - uc_sift(base, start, count, width, cmp); - start--; - } - - while (end > 0) { - memcpy(base + end * width, base, width); - uc_sift(base, 0, end, width, cmp); - end--; - } -}