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/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/include/ucore/logging.h b/include/ucore/logging.h index bbaebe0..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 * @@ -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. diff --git a/include/ucore/tailq.h b/include/ucore/tailq.h new file mode 100644 index 0000000..010fb8a --- /dev/null +++ b/include/ucore/tailq.h @@ -0,0 +1,252 @@ +#ifndef UC_TAILQ_H_ +#define UC_TAILQ_H_ + +#ifdef __GNUC__ +#define UC_INLINE inline __attribute__((always_inline,flatten)) +#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) + +//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) +{ + 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 tailq + */ +static UC_INLINE void uc_tailq_insert_tail(struct TailQ *head, struct TailQ *entry) +{ + //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 tailq + */ +static UC_INLINE void uc_tailq_insert_head(struct TailQ *head, struct TailQ *entry) +{ + //head becomes entry->prev, signalling the end of the tailq + 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 tailq it is part of. + * (It *must* already be part of a tailq. + */ +static UC_INLINE void uc_tailq_remove(struct TailQ *entry) +{ + uc_tailq_link(entry->prev, entry->next); + +//help catch illegal use: + entry->next = (void*)0x101; + entry->prev = (void*)0x102; +} + +/** 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_tailq_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_tailq_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. + * @param head the struct TailQ* head of the tailq + */ +#define UC_TAILQ_FOREACH(entry, head)\ + for ((entry) = UC_TAILQ_FIRST(head); \ + (entry) != (head); \ + (entry) = UC_TAILQ_NEXT(entry)) + +/** 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) = 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. + * + * @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) = UC_TAILQ_FIRST(head), (nxt) = UC_TAILQ_NEXT(entry); \ + (entry) != (head); \ + (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. + * + * @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) = UC_TAILQ_LAST(head), (prv) = UC_TAILQ_PREV(entry); \ + (entry) != (head); \ + (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 + +#endif 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 */ 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--; - } -} 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); 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" }; diff --git a/test/tailq_example.c b/test/tailq_example.c new file mode 100644 index 0000000..e91609f --- /dev/null +++ b/test/tailq_example.c @@ -0,0 +1,97 @@ +#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 Block *entry; + printf("File: %s\n", f->name); + 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 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 Block *entry, *next; + UC_TAILQ_FOREACH_CONTAINER_SAFE(entry, next, blocks, &f->head) { + free(entry); + } + 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("\nReverse order:"); + print_file_reverse(&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; +} + + 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;