From 4263ff50a4fb794214d76510b7a89d1f06e45941 Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Thu, 4 Aug 2011 12:15:28 +0200 Subject: [PATCH] Cleanup in buflib: * Rework debugging parts (new buflib_get_num_blocks(), buflib_print_block_at()) * More comments in buflib.h * Cleanup in debug_menu. and core_alloc.c --- apps/debug_menu.c | 28 +++---------- firmware/buflib.c | 75 ++++++++++++++++++---------------- firmware/core_alloc.c | 12 ++---- firmware/include/buflib.h | 93 +++++++++++++++++++++++++++++++++++-------- firmware/include/core_alloc.h | 18 +++++---- 5 files changed, 136 insertions(+), 90 deletions(-) diff --git a/apps/debug_menu.c b/apps/debug_menu.c index ffa8232d9..fb8575ec6 100644 --- a/apps/debug_menu.c +++ b/apps/debug_menu.c @@ -417,40 +417,22 @@ static bool dbg_buffering_thread(void) #endif /* CONFIG_CODEC */ #endif /* HAVE_LCD_BITMAP */ -static char bf_buf[1024]; -static int bf_buf_used; -static int bf_items; - -static void print(const char* buf) -{ - char* dst = &bf_buf[bf_buf_used]; - snprintf(dst, sizeof(bf_buf) - bf_buf_used, "%s", buf); - bf_buf_used += strlen(dst) + 1; - bf_items++; -} - static const char* bf_getname(int selected_item, void *data, char *buffer, size_t buffer_len) { - int i = 0; - (void)data;(void)buffer;(void)buffer_len; - char* src = bf_buf; - while(i++ < selected_item) - src = strchr(src, 0) + 1; - - return src; + (void)data; + core_print_block_at(selected_item, buffer, buffer_len); + return buffer; } static bool dbg_buflib_allocs(void) { struct simplelist_info info; - bf_items = 0; - bf_buf_used = 0; - core_print_blocks(print); - simplelist_info_init(&info, "mem allocs", bf_items, NULL); + simplelist_info_init(&info, "mem allocs", core_get_num_blocks(), NULL); info.get_name = bf_getname; return simplelist_show_list(&info); } + #if (CONFIG_PLATFORM & PLATFORM_NATIVE) static const char* dbg_partitions_getname(int selected_item, void *data, char *buffer, size_t buffer_len) diff --git a/firmware/buflib.c b/firmware/buflib.c index 445777242..43d7dd139 100644 --- a/firmware/buflib.c +++ b/firmware/buflib.c @@ -56,16 +56,6 @@ */ static struct buflib_callbacks default_callbacks; -#if defined(ROCKBOX) -#define YIELD() yield() -#elif defined(__unix) && (__unix == 1) -#include -#define YIELD() sched_yield() -#else -#warning YIELD not defined. Will busy-wait -#define YIELD() -#endif - #define B_ALIGN_DOWN(x) \ ALIGN_DOWN(x, sizeof(union buflib_data)) @@ -369,9 +359,6 @@ int buflib_alloc_ex(struct buflib_context *ctx, size_t size, const char *name, struct buflib_callbacks *ops) { - /* busy wait if there's a thread owning the lock */ - while (ctx->handle_lock != 0) YIELD(); - union buflib_data *handle, *block; size_t name_len = name ? B_ALIGN_UP(strlen(name)+1) : 0; bool last; @@ -533,11 +520,6 @@ buflib_free(struct buflib_context *ctx, int handle_num) */ if (block < ctx->first_free_block) ctx->first_free_block = block; - - /* if the handle is the one aquired with buflib_alloc_maximum() - * unlock buflib_alloc() as part of the shrink */ - if (ctx->handle_lock == handle_num) - ctx->handle_lock = 0; } /* Return the maximum allocatable memory in bytes */ @@ -567,17 +549,12 @@ buflib_available(struct buflib_context* ctx) int buflib_alloc_maximum(struct buflib_context* ctx, const char* name, size_t *size, struct buflib_callbacks *ops) { - int handle; - /* limit name to 16 since that's what buflib_available() accounts for it */ char buf[16]; *size = buflib_available(ctx); strlcpy(buf, name, sizeof(buf)); - handle = buflib_alloc_ex(ctx, *size, buf, ops); - if (handle > 0) /* shouldn't happen ?? */ - ctx->handle_lock = handle; - return handle; + return buflib_alloc_ex(ctx, *size, buf, ops); } /* Shrink the allocation indicated by the handle according to new_start and @@ -665,11 +642,6 @@ buflib_shrink(struct buflib_context* ctx, int handle, void* new_start, size_t ne ctx->first_free_block = new_next_block; } - /* if the handle is the one aquired with buflib_alloc_maximum() - * unlock buflib_alloc() as part of the shrink */ - if (ctx->handle_lock == handle) - ctx->handle_lock = 0; - return true; } @@ -682,7 +654,9 @@ const char* buflib_get_name(struct buflib_context *ctx, int handle) return data[-len].name; } -void buflib_print_allocs(struct buflib_context *ctx, void (*print)(const char*)) +#ifdef BUFLIB_DEBUG_BLOCKS +void buflib_print_allocs(struct buflib_context *ctx, + void (*print)(int, const char*)) { union buflib_data *this, *end = ctx->handle_table; char buf[128]; @@ -706,20 +680,53 @@ void buflib_print_allocs(struct buflib_context *ctx, void (*print)(const char*)) " \t%p\n" " \t%ld\n", name?:"(null)", handle_num, block_start, alloc_start, alloc_len); - print(buf); + /* handle_num is 1-based */ + print(handle_num - 1, buf); } } -void buflib_print_blocks(struct buflib_context *ctx, void (*print)(const char*)) +void buflib_print_blocks(struct buflib_context *ctx, + void (*print)(int, const char*)) { + char buf[128]; + int i = 0; for(union buflib_data* this = ctx->buf_start; this < ctx->alloc_end; this += abs(this->val)) { - char buf[128] = { 0 }; snprintf(buf, sizeof(buf), "%8p: val: %4ld (%s)", this, this->val, this->val > 0? this[3].name:""); - print(buf); + print(i++, buf); } } +#endif + +#ifdef BUFLIB_DEBUG_BLOCK_SINGLE +int buflib_get_num_blocks(struct buflib_context *ctx) +{ + int i = 0; + for(union buflib_data* this = ctx->buf_start; + this < ctx->alloc_end; + this += abs(this->val)) + { + i++; + } + return i; +} + +void buflib_print_block_at(struct buflib_context *ctx, int block_num, + char* buf, size_t bufsize) +{ + union buflib_data* this = ctx->buf_start; + while(block_num > 0 && this < ctx->alloc_end) + { + this += abs(this->val); + block_num -= 1; + } + snprintf(buf, bufsize, "%8p: val: %4ld (%s)", + this, this->val, + this->val > 0? this[3].name:""); +} + +#endif diff --git a/firmware/core_alloc.c b/firmware/core_alloc.c index 93c4f705e..9a4388cbf 100644 --- a/firmware/core_alloc.c +++ b/firmware/core_alloc.c @@ -46,16 +46,12 @@ bool core_shrink(int handle, void* new_start, size_t new_size) return buflib_shrink(&core_ctx, handle, new_start, new_size); } -void core_print_allocs(void (*print)(const char*)) +int core_get_num_blocks(void) { - buflib_print_allocs(&core_ctx, print); -} -void core_print_blocks(void (*print)(const char*)) -{ - buflib_print_blocks(&core_ctx, print); + return buflib_get_num_blocks(&core_ctx); } -const char* core_get_alloc_name(int handle) +void core_print_block_at(int block_num, char* buf, size_t bufsize) { - return buflib_get_name(&core_ctx, handle); + buflib_print_block_at(&core_ctx, block_num, buf, bufsize); } diff --git a/firmware/include/buflib.h b/firmware/include/buflib.h index e6ddc0714..5e46cca75 100644 --- a/firmware/include/buflib.h +++ b/firmware/include/buflib.h @@ -30,7 +30,8 @@ #include #include - +/* enable single block debugging */ +#define BUFLIB_DEBUG_BLOCK_SINGLE union buflib_data { @@ -49,7 +50,6 @@ struct buflib_context union buflib_data *first_free_block; union buflib_data *buf_start; union buflib_data *alloc_end; - volatile int handle_lock; bool compact; }; @@ -86,7 +86,7 @@ struct buflib_callbacks { * Move data around as you need and call core_shrink() from within the * callback to do the shrink (buflib will not move data as part of shrinking) * - * hint: bit mask containing hints on how shrinking is desired + * hint: bit mask containing hints on how shrinking is desired (see below) * handle: The corresponding handle * start: The old start of the allocation * @@ -174,6 +174,24 @@ int buflib_alloc_maximum(struct buflib_context* ctx, const char* name, size_t *size, struct buflib_callbacks *ops); /** + * Queries the data pointer for the given handle. It's actually a cheap operation, + * so don't hesitate using it extensivly. + * + * Notice that you need to re-query after every direct or indirect yield(), + * because compaction can happen by other threads which may get your data + * moved around (or you can get notified about changes by callbacks, + * see further above). + * + * handle: The handle corresponding to the allocation + * + * Returns: The start pointer of the allocation + */ +static inline void* buflib_get_data(struct buflib_context *context, int handle) +{ + return (void*)(context->handle_table[-handle].alloc); +} + +/** * Shrink the memory allocation associated with the given handle * Mainly intended to be used with the shrink callback (call this in the * callback and get return BUFLIB_CB_OK, but it can also be called outside @@ -198,7 +216,33 @@ bool buflib_shrink(struct buflib_context *ctx, int handle, void* newstart, size_ * Frees memory associated with the given handle */ void buflib_free(struct buflib_context *context, int handle); + +/** + * Moves the underlying buflib buffer up by size bytes (as much as + * possible for size == 0) without moving the end. This effectively + * reduces the available space by taking away managable space from the + * front. This space is not available for new allocations anymore. + * + * To make space available in the front, everything is moved up. + * It does _NOT_ call the move callbacks + * + * + * size: size in bytes to move the buffer up (take away). The actual + * bytes moved is returned in this + * Returns: The new start of the underlying buflib buffer + */ void* buflib_buffer_out(struct buflib_context *ctx, size_t *size); + +/** + * Moves the underlying buflib buffer down by size bytes without + * moving the end. This grows the buflib buffer by adding space to the front. + * The new bytes are available for new allocations. + * + * Everything is moved down, and the new free space will be in the middle. + * It does _NOT_ call the move callbacks. + * + * size: size in bytes to move the buffer down (new free space) + */ void buflib_buffer_in(struct buflib_context *ctx, int size); /* debugging */ @@ -216,25 +260,40 @@ const char* buflib_get_name(struct buflib_context *ctx, int handle); /** * Prints an overview of all current allocations with the help * of the passed printer helper + * + * This walks only the handle table and prints only valid allocations + * + * Only available if BUFLIB_DEBUG_BLOCKS is defined */ -void buflib_print_allocs(struct buflib_context *ctx, void (*print)(const char*)); -void buflib_print_blocks(struct buflib_context *ctx, void (*print)(const char*)); +void buflib_print_allocs(struct buflib_context *ctx, void (*print)(int, const char*)); /** - * Queries the data pointer for the given handle. It's actually a cheap operation, - * so don't hesitate using it extensivly. + * Prints an overview of all blocks in the buflib buffer, allocated + * or unallocated, with the help pf the passted printer helper * - * Notice that you need to re-query after every direct or indirect yield(), - * because compaction can happen by other threads which may get your data - * moved around (or you can get notified about changes by callbacks, - * see further below). + * This walks the entire buffer and prints unallocated space also. + * The output is also different from buflib_print_allocs(). * - * handle: The handle corresponding to the allocation + * Only available if BUFLIB_DEBUG_BLOCKS is defined + */ +void buflib_print_blocks(struct buflib_context *ctx, void (*print)(int, const char*)); + +/** + * Gets the number of blocks in the entire buffer, allocated or unallocated * - * Returns: The start pointer of the allocation + * Only available if BUFLIB_DEBUG_BLOCK_SIGNLE is defined */ -static inline void* buflib_get_data(struct buflib_context *context, int handle) -{ - return (void*)(context->handle_table[-handle].alloc); -} +int buflib_get_num_blocks(struct buflib_context *ctx); + +/** + * Print information about a single block as indicated by block_num + * into buf + * + * buflib_get_num_blocks() beforehand to get the total number of blocks, + * as passing an block_num higher than that is undefined + * + * Only available if BUFLIB_DEBUG_BLOCK_SIGNLE is defined + */ +void buflib_print_block_at(struct buflib_context *ctx, int block_num, + char* buf, size_t bufsize); #endif diff --git a/firmware/include/core_alloc.h b/firmware/include/core_alloc.h index c7d76517e..4ea7e9a09 100644 --- a/firmware/include/core_alloc.h +++ b/firmware/include/core_alloc.h @@ -11,20 +11,22 @@ void core_allocator_init(void); int core_alloc(const char* name, size_t size); int core_alloc_ex(const char* name, size_t size, struct buflib_callbacks *ops); - -void core_free(int handle); - - int core_alloc_maximum(const char* name, size_t *size, struct buflib_callbacks *ops); - bool core_shrink(int handle, void* new_start, size_t new_size); - +void core_free(int handle); size_t core_available(void); +/* DO NOT ADD wrappers for buflib_buffer_out/in. They do not call + * the move callbacks and are therefore unsafe in the core */ + +#ifdef BUFLIB_DEBUG_BLOCKS void core_print_allocs(void (*print)(const char*)); void core_print_blocks(void (*print)(const char*)); - -const char* core_get_alloc_name(int handle); +#endif +#ifdef BUFLIB_DEBUG_BLOCK_SINGLE +int core_get_num_blocks(void); +void core_print_block_at(int block_num, char* buf, size_t bufsize); +#endif static inline void* core_get_data(int handle) { -- 2.11.4.GIT