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.
This commit is contained in:
Alexandre Julliard 2009-02-04 12:27:36 +01:00
parent 55d6f07e31
commit ae7490d362
2 changed files with 50 additions and 31 deletions

View File

@ -29,6 +29,7 @@
#include "objbase.h" #include "objbase.h"
#include "oaidl.h" #include "oaidl.h"
#include "winnls.h" #include "winnls.h"
#include "wine/list.h"
#include "wine/unicode.h" #include "wine/unicode.h"
#include "cvconst.h" #include "cvconst.h"
@ -37,13 +38,14 @@
struct pool /* poor's man */ struct pool /* poor's man */
{ {
struct pool_arena* first; struct list arena_list;
unsigned arena_size; 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_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); char* pool_strdup(struct pool* a, const char* str);
struct vector struct vector

View File

@ -34,14 +34,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
struct pool_arena struct pool_arena
{ {
struct pool_arena* next; struct list entry;
char* current; 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->arena_size = arena_size;
a->first = NULL;
} }
void pool_destroy(struct pool* pool) void pool_destroy(struct pool* pool)
@ -50,58 +52,73 @@ void pool_destroy(struct pool* pool)
struct pool_arena* next; struct pool_arena* next;
#ifdef USE_STATS #ifdef USE_STATS
unsigned alloc, used, num; size_t alloc, used, num;
alloc = used = num = 0; alloc = used = num = 0;
arena = pool->first; LIST_FOR_EACH_ENTRY( arena, &pool->arena_list, struct pool_arena, entry )
while (arena)
{ {
alloc += pool->arena_size; alloc += arena->end - (char *)arena;
used += arena->current - (char*)arena;
num++;
}
LIST_FOR_EACH_ENTRY( arena, &pool->arena_full, struct pool_arena, entry )
{
alloc += arena->end - (char *)arena;
used += arena->current - (char*)arena; used += arena->current - (char*)arena;
num++; num++;
arena = arena->next;
} }
if (alloc == 0) alloc = 1; /* avoid division by zero */ if (alloc == 0) alloc = 1; /* avoid division by zero */
FIXME("STATS: pool %p has allocated %u kbytes, used %u kbytes in %u arenas,\n" FIXME("STATS: pool %p has allocated %u kbytes, used %u kbytes in %u arenas, non-allocation ratio: %.2f%%\n",
"\t\t\t\tnon-allocation ratio: %.2f%%\n", pool, (unsigned)(alloc >> 10), (unsigned)(used >> 10), (unsigned)num,
pool, alloc >> 10, used >> 10, num, 100.0 - (float)used / (float)alloc * 100.0); 100.0 - (float)used / (float)alloc * 100.0);
#endif #endif
arena = pool->first; LIST_FOR_EACH_ENTRY_SAFE( arena, next, &pool->arena_list, struct pool_arena, entry )
while (arena)
{ {
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); 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; struct pool_arena* arena;
void* ret; void* ret;
size_t size;
len = (len + 3) & ~3; /* round up size on DWORD boundary */ 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; ret = arena->current;
arena->current += len; arena->current += len;
if (arena->current + 16 >= arena->end)
{
list_remove( &arena->entry );
list_add_tail( &pool->arena_full, &arena->entry );
}
return ret; return ret;
} }
} }
arena = HeapAlloc(GetProcessHeap(), 0, pool->arena_size); size = max( pool->arena_size, len + sizeof(struct pool_arena) );
if (!arena) {ERR("OOM\n");return NULL;} arena = HeapAlloc(GetProcessHeap(), 0, size);
if (!arena) {ERR("OOM for %u\n", size);return NULL;}
ret = (char*)arena + sizeof(*arena); ret = arena + 1;
arena->next = pool->first;
pool->first = arena;
arena->current = (char*)ret + len; 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; return ret;
} }