Alexandre Julliard : dbghelp: Fix pool allocation routines to be able to support arbitrary sizes.
Alexandre Julliard
julliard at winehq.org
Wed Feb 4 09:15:35 CST 2009
Module: wine
Branch: master
Commit: ae7490d362e684eb52d15c4351697bfe0b0510e5
URL: http://source.winehq.org/git/wine.git/?a=commit;h=ae7490d362e684eb52d15c4351697bfe0b0510e5
Author: Alexandre Julliard <julliard at 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;
}
More information about the wine-cvs
mailing list