Module: wine Branch: master Commit: ae7490d362e684eb52d15c4351697bfe0b0510e5 URL: http://source.winehq.org/git/wine.git/?a=commit;h=ae7490d362e684eb52d15c4351...
Author: Alexandre Julliard julliard@winehq.org Date: Wed Feb 4 12:27:36 2009 +0100
dbghelp: Fix pool allocation routines to be able to support arbitrary sizes.
Also move full arenas to a separate list to avoid searching through them again and again.
---
dlls/dbghelp/dbghelp_private.h | 10 +++-- dlls/dbghelp/storage.c | 71 ++++++++++++++++++++++++--------------- 2 files changed, 50 insertions(+), 31 deletions(-)
diff --git a/dlls/dbghelp/dbghelp_private.h b/dlls/dbghelp/dbghelp_private.h index 880aed9..77fb47e 100644 --- a/dlls/dbghelp/dbghelp_private.h +++ b/dlls/dbghelp/dbghelp_private.h @@ -29,6 +29,7 @@ #include "objbase.h" #include "oaidl.h" #include "winnls.h" +#include "wine/list.h" #include "wine/unicode.h"
#include "cvconst.h" @@ -37,13 +38,14 @@
struct pool /* poor's man */ { - struct pool_arena* first; - unsigned arena_size; + struct list arena_list; + struct list arena_full; + size_t arena_size; };
-void pool_init(struct pool* a, unsigned arena_size); +void pool_init(struct pool* a, size_t arena_size); void pool_destroy(struct pool* a); -void* pool_alloc(struct pool* a, unsigned len); +void* pool_alloc(struct pool* a, size_t len); char* pool_strdup(struct pool* a, const char* str);
struct vector diff --git a/dlls/dbghelp/storage.c b/dlls/dbghelp/storage.c index ec8a37d..23a45e1 100644 --- a/dlls/dbghelp/storage.c +++ b/dlls/dbghelp/storage.c @@ -34,14 +34,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
struct pool_arena { - struct pool_arena* next; - char* current; + struct list entry; + char *current; + char *end; };
-void pool_init(struct pool* a, unsigned arena_size) +void pool_init(struct pool* a, size_t arena_size) { + list_init( &a->arena_list ); + list_init( &a->arena_full ); a->arena_size = arena_size; - a->first = NULL; }
void pool_destroy(struct pool* pool) @@ -50,58 +52,73 @@ void pool_destroy(struct pool* pool) struct pool_arena* next;
#ifdef USE_STATS - unsigned alloc, used, num; - + size_t alloc, used, num; + alloc = used = num = 0; - arena = pool->first; - while (arena) + LIST_FOR_EACH_ENTRY( arena, &pool->arena_list, struct pool_arena, entry ) + { + alloc += arena->end - (char *)arena; + used += arena->current - (char*)arena; + num++; + } + LIST_FOR_EACH_ENTRY( arena, &pool->arena_full, struct pool_arena, entry ) { - alloc += pool->arena_size; + alloc += arena->end - (char *)arena; used += arena->current - (char*)arena; num++; - arena = arena->next; } if (alloc == 0) alloc = 1; /* avoid division by zero */ - FIXME("STATS: pool %p has allocated %u kbytes, used %u kbytes in %u arenas,\n" - "\t\t\t\tnon-allocation ratio: %.2f%%\n", - pool, alloc >> 10, used >> 10, num, 100.0 - (float)used / (float)alloc * 100.0); + FIXME("STATS: pool %p has allocated %u kbytes, used %u kbytes in %u arenas, non-allocation ratio: %.2f%%\n", + pool, (unsigned)(alloc >> 10), (unsigned)(used >> 10), (unsigned)num, + 100.0 - (float)used / (float)alloc * 100.0); #endif
- arena = pool->first; - while (arena) + LIST_FOR_EACH_ENTRY_SAFE( arena, next, &pool->arena_list, struct pool_arena, entry ) { - next = arena->next; + list_remove( &arena->entry ); + HeapFree(GetProcessHeap(), 0, arena); + } + LIST_FOR_EACH_ENTRY_SAFE( arena, next, &pool->arena_full, struct pool_arena, entry ) + { + list_remove( &arena->entry ); HeapFree(GetProcessHeap(), 0, arena); - arena = next; } - pool_init(pool, 0); }
-void* pool_alloc(struct pool* pool, unsigned len) +void* pool_alloc(struct pool* pool, size_t len) { struct pool_arena* arena; void* ret; + size_t size;
len = (len + 3) & ~3; /* round up size on DWORD boundary */ - assert(sizeof(struct pool_arena) + len <= pool->arena_size && len);
- for (arena = pool->first; arena; arena = arena->next) + LIST_FOR_EACH_ENTRY( arena, &pool->arena_list, struct pool_arena, entry ) { - if ((char*)arena + pool->arena_size - arena->current >= len) + if (arena->end - arena->current >= len) { ret = arena->current; arena->current += len; + if (arena->current + 16 >= arena->end) + { + list_remove( &arena->entry ); + list_add_tail( &pool->arena_full, &arena->entry ); + } return ret; } }
- arena = HeapAlloc(GetProcessHeap(), 0, pool->arena_size); - if (!arena) {ERR("OOM\n");return NULL;} + size = max( pool->arena_size, len + sizeof(struct pool_arena) ); + arena = HeapAlloc(GetProcessHeap(), 0, size); + if (!arena) {ERR("OOM for %u\n", size);return NULL;}
- ret = (char*)arena + sizeof(*arena); - arena->next = pool->first; - pool->first = arena; + ret = arena + 1; arena->current = (char*)ret + len; + arena->end = (char *)arena + size; + if (arena->current + 16 >= arena->end) + list_add_tail( &pool->arena_full, &arena->entry ); + else + list_add_head( &pool->arena_list, &arena->entry ); return ret; }