Remove custom pool memory allocator per wesnoth-dev mailing list discussion

This affects the cmake and scons scripts, and various project files in
projectfiles/. I have only tested my changes to scons (and loonycyborg
might still want to review the diff regarding a line in src/SConscript
involving game.cpp).
This commit is contained in:
Ignacio R. Morelle 2012-02-19 18:43:20 +00:00
parent 5f79fb5439
commit 20bcf49f3e
12 changed files with 6 additions and 5644 deletions

View file

@ -76,7 +76,6 @@ option(ENABLE_SERVER "Enable compilation of server" ON)
option(ENABLE_TOOLS "Enable building and installation of tools for artists and WML maintainers")
option(ENABLE_TESTS "Build unit tests")
option(ENABLE_NLS "Enable building of translations" ON)
option(ENABLE_POOL_ALLOC "Enable custom pool malloc" OFF)
option(ENABLE_LOW_MEM "Reduce memory usage by removing extra functionality" OFF)
option(ENABLE_OMP "Enables OpenMP, and has additional dependencies" OFF)
@ -150,10 +149,6 @@ if(NOT WIN32)
add_definitions(-DWESNOTH_PATH=\\\"${DATADIR}\\\")
endif(NOT WIN32)
if(NOT ENABLE_POOL_ALLOC OR WIN32)
add_definitions(-DDISABLE_POOL_ALLOC)
endif(NOT ENABLE_POOL_ALLOC OR WIN32)
if(X11_FOUND)
add_definitions(-D_X11)
endif(X11_FOUND)

View file

@ -80,7 +80,6 @@ opts.AddVariables(
BoolVariable('raw_sockets', 'Set to use raw receiving sockets in the multiplayer network layer rather than the SDL_net facilities', False),
BoolVariable('forum_user_handler', 'Enable forum user handler in wesnothd', False),
BoolVariable('use_network_ana', 'Use the new network api', False),
BoolVariable('pool_alloc', 'Enable custom pool malloc', False),
('server_gid', 'group id of the user who runs wesnothd', ""),
('server_uid', 'user id of the user who runs wesnothd', ""),
BoolVariable('strict', 'Set to strict compilation', False),
@ -425,9 +424,6 @@ for env in [test_env, client_env, env]:
if env['internal_data']:
env.Append(CPPDEFINES = "USE_INTERNAL_DATA")
if env["PLATFORM"] == "win32":
env["pool_alloc"] = False
if have_X:
env.Append(CPPDEFINES = "_X11")

View file

@ -211,9 +211,7 @@
<Unit filename="../../src/formula_string_utils.hpp" />
<Unit filename="../../src/formula_tokenizer.cpp" />
<Unit filename="../../src/formula_tokenizer.hpp" />
<Unit filename="../../src/game.cpp">
<Option compiler="gcc" use="1" buildCommand="$compiler $options -DDISABLE_POOL_ALLOC $includes -c $file -o $object" />
</Unit>
<Unit filename="../../src/game.cpp" />
<Unit filename="../../src/game_config.cpp" />
<Unit filename="../../src/game_config.hpp" />
<Unit filename="../../src/game_display.cpp" />
@ -517,10 +515,6 @@
<Unit filename="../../src/lobby_preferences.hpp" />
<Unit filename="../../src/log.cpp" />
<Unit filename="../../src/log.hpp" />
<Unit filename="../../src/malloc.c">
<Option compilerVar="CC" />
<Option compiler="gcc" use="1" buildCommand="$compiler $options -DDISABLE_POOL_ALLOC $includes -c $file -o $object" />
</Unit>
<Unit filename="../../src/map.cpp" />
<Unit filename="../../src/map.hpp" />
<Unit filename="../../src/map_create.cpp" />
@ -584,10 +578,6 @@
<Unit filename="../../src/playsingle_controller.hpp" />
<Unit filename="../../src/playturn.cpp" />
<Unit filename="../../src/playturn.hpp" />
<Unit filename="../../src/poolalloc.c">
<Option compilerVar="CC" />
<Option compiler="gcc" use="1" buildCommand="$compiler $options -DDISABLE_POOL_ALLOC $includes -c $file -o $object" />
</Unit>
<Unit filename="../../src/portrait.cpp" />
<Unit filename="../../src/portrait.hpp" />
<Unit filename="../../src/preferences.cpp" />

View file

@ -253,9 +253,7 @@
<Unit filename="..\..\src\formula_string_utils.hpp" />
<Unit filename="..\..\src\formula_tokenizer.cpp" />
<Unit filename="..\..\src\formula_tokenizer.hpp" />
<Unit filename="..\..\src\game.cpp">
<Option compiler="gcc" use="1" buildCommand="$compiler $options -DDISABLE_POOL_ALLOC $includes -c $file -o $object" />
</Unit>
<Unit filename="..\..\src\game.cpp" />
<Unit filename="..\..\src\game_config.cpp" />
<Unit filename="..\..\src\game_config.hpp" />
<Unit filename="..\..\src\game_controller.cpp" />
@ -641,10 +639,6 @@
<Unit filename="..\..\src\lua\lzio.h" />
<Unit filename="..\..\src\lua_jailbreak_exception.cpp" />
<Unit filename="..\..\src\lua_jailbreak_exception.hpp" />
<Unit filename="..\..\src\malloc.c">
<Option compilerVar="CC" />
<Option compiler="gcc" use="1" buildCommand="$compiler $options -DDISABLE_POOL_ALLOC $includes -c $file -o $object" />
</Unit>
<Unit filename="..\..\src\map.cpp" />
<Unit filename="..\..\src\map.hpp" />
<Unit filename="..\..\src\map_create.cpp" />
@ -713,10 +707,6 @@
<Unit filename="..\..\src\playsingle_controller.hpp" />
<Unit filename="..\..\src\playturn.cpp" />
<Unit filename="..\..\src\playturn.hpp" />
<Unit filename="..\..\src\poolalloc.c">
<Option compilerVar="CC" />
<Option compiler="gcc" use="1" buildCommand="$compiler $options -DDISABLE_POOL_ALLOC $includes -c $file -o $object" />
</Unit>
<Unit filename="..\..\src\portrait.cpp" />
<Unit filename="..\..\src\portrait.hpp" />
<Unit filename="..\..\src\preferences.cpp" />

View file

@ -1310,11 +1310,7 @@
<ClCompile Include="..\..\src\formula_function.cpp" />
<ClCompile Include="..\..\src\formula_string_utils.cpp" />
<ClCompile Include="..\..\src\formula_tokenizer.cpp" />
<ClCompile Include="..\..\src\game.cpp">
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug (fast)|Win32'">DISABLE_POOL_ALLOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">DISABLE_POOL_ALLOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">DISABLE_POOL_ALLOC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="..\..\src\game.cpp" />
<ClCompile Include="..\..\src\game_controller.cpp" />
<ClCompile Include="..\..\src\game_controller_abstract.cpp" />
<ClCompile Include="..\..\src\game_controller_new.cpp" />

View file

@ -15130,54 +15130,6 @@
<File
RelativePath="..\..\src\game.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="DISABLE_POOL_ALLOC"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="DISABLE_POOL_ALLOC"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug (fast)|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="DISABLE_POOL_ALLOC"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug_with_VLD|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="DISABLE_POOL_ALLOC"
/>
</FileConfiguration>
<FileConfiguration
Name="Test_Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="DISABLE_POOL_ALLOC"
/>
</FileConfiguration>
<FileConfiguration
Name="Test_Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
PreprocessorDefinitions="DISABLE_POOL_ALLOC"
/>
</FileConfiguration>
</File>
<File
RelativePath="..\..\src\game_config.hpp"

View file

@ -323,7 +323,7 @@
B5599B690EC62181008DD061 /* game_events.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5599A7B0EC62181008DD061 /* game_events.cpp */; };
B5599B6A0EC62181008DD061 /* game_display.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5599A7E0EC62181008DD061 /* game_display.cpp */; settings = {COMPILER_FLAGS = "-DHAVE_GROWL"; }; };
B5599B6B0EC62181008DD061 /* game_config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5599A800EC62181008DD061 /* game_config.cpp */; settings = {COMPILER_FLAGS = "-DWESNOTH_PATH='\"./\"'"; }; };
B5599B6C0EC62181008DD061 /* game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5599A810EC62181008DD061 /* game.cpp */; settings = {COMPILER_FLAGS = "-DDISABLE_POOL_ALLOC"; }; };
B5599B6C0EC62181008DD061 /* game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5599A810EC62181008DD061 /* game.cpp */; };
B5599B6D0EC62181008DD061 /* formula_tokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5599A830EC62181008DD061 /* formula_tokenizer.cpp */; };
B5599B6E0EC62181008DD061 /* formula_function.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5599A860EC62181008DD061 /* formula_function.cpp */; };
B5599B700EC62181008DD061 /* formula.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5599A8C0EC62181008DD061 /* formula.cpp */; };

View file

@ -223,14 +223,6 @@ set(libwesnoth-core_STAT_SRC
${REVISION_FILE}
)
if(ENABLE_POOL_ALLOC AND NOT WIN32)
set(libwesnoth-core_STAT_SRC
${libwesnoth-core_STAT_SRC}
malloc.c
poolalloc.c
)
endif(ENABLE_POOL_ALLOC AND NOT WIN32)
# a 'lib' is automatically set in front when creating the library (as in the filename)
# internal reference is the name given here
add_library(wesnoth-core STATIC EXCLUDE_FROM_ALL ${libwesnoth-core_STAT_SRC})

View file

@ -35,11 +35,6 @@ libwesnoth_core_sources = Split("""
serialization/validator.cpp
tools/schema/tag.cpp
""")
if env["pool_alloc"]:
libwesnoth_core_sources.extend(Split("""
malloc.c
poolalloc.c
"""))
libwesnoth_core_sources.extend(env.Object("network_worker.cpp", EXTRA_DEFINE = env['raw_sockets'] and "NETWORK_USE_RAW_SOCKETS" or None))
@ -483,7 +478,7 @@ def WesnothProgram(env, target, source, can_build, **kw):
for env in [test_env, client_env, env]:
env.AddMethod(WesnothProgram)
game_cpp = client_env.Object("game.cpp", EXTRA_DEFINE = not env["pool_alloc"] and "DISABLE_POOL_ALLOC" or None);
game_cpp = client_env.Object("game.cpp");
wesnoth_objects = [game_cpp, libwesnoth_extras, libwesnoth_core, libwesnoth_sdl,
libwesnoth, env["wesnoth_res"]]

View file

@ -582,12 +582,6 @@ static int do_gameloop(int argc, char** argv)
}
}
#ifndef DISABLE_POOL_ALLOC
extern "C" {
void init_custom_malloc();
}
#endif
#ifdef __native_client__
int wesnoth_main(int argc, char** argv)
@ -618,9 +612,7 @@ int main(int argc, char** argv)
execv(argv[0], argv);
}
#endif
#ifndef DISABLE_POOL_ALLOC
init_custom_malloc();
#endif
if(SDL_Init(SDL_INIT_TIMER) < 0) {
fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
return(1);

File diff suppressed because it is too large Load diff

View file

@ -1,468 +0,0 @@
/* $Id$ */
#ifndef DISABLE_POOL_ALLOC
/*
Copyright (C) 2008 by David White <dave@whitevine.net>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2
or at your option any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.
See the COPYING file for more details.
*/
/*
This file defines a custom allocator that is optimized for doing memory
allocations for Wesnoth. Its primary consideration is space, though it
should be pretty fast too.
The largest consideration is meta-data: Wesnoth allocates many small chunks,
and so we want to minimize per-chunk meta-data. Typical general-purpose
allocators have a per-chunk overhead of one or two pointers. This allocator
has no per-chunk overhead, just memory overhead of less than 2%.
The allocator is designed to handle small chunks. We include dlmalloc's source,
and allocations that are not considered small are simply punted to dlmalloc
to allocate.
Some basic terminology:
- chunk: a single allocation, allocated with malloc.
- block: a block of memory from which we allocate chunks. A block has a header
and then its data section. A block should be a multiple of the page size.
A given block is dedicated to allocating chunks of a specific size. All blocks
are the same size (4096 bytes by default, which should be the minimum).
- superblock: we allocate one huge block from which all blocks are allocated.
*/
#include <assert.h>
#include <errno.h>
#include <inttypes.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void* dlmalloc(size_t size);
void* dlcalloc(size_t count, size_t size);
void* dlvalloc(size_t size);
void* dlmemalign(size_t alignment, size_t size);
void* dlrealloc(void* ptr, size_t size);
void dlfree(void* ptr);
#define BLOCK_SIZE (4096)
#define MAX_CHUNK_SIZE (256)
#define CHUNK_SIZE_STEP (sizeof(void*))
#define NUM_POOLS ((MAX_CHUNK_SIZE/CHUNK_SIZE_STEP) + 1)
// find the index of the pool that a chunk of size n will be allocated from.
#define GET_POOL_INDEX(n) ((n)/CHUNK_SIZE_STEP)
#define ROUNDUP_SIZE(n) (((n)%CHUNK_SIZE_STEP) ? ((n) + CHUNK_SIZE_STEP - ((n)%CHUNK_SIZE_STEP)) : (n))
#define CUSTOM_MEMORY_SIZE (1024*1024*40)
uint8_t* begin_superblock_range = NULL;
uint8_t* begin_superblock = NULL;
uint8_t* end_superblock = NULL;
#define IS_OUR_PTR(ptr) ((uint8_t*)(ptr) >= begin_superblock_range && (uint8_t*)(ptr) < end_superblock)
pthread_t main_thread;
void init_custom_malloc()
{
main_thread = pthread_self();
// allocate the memory -- allocate an extra block at the end, so that
// if the address we get back isn't block-aligned, we can advance
// the pointer until it is.
void* alloc = dlmalloc(CUSTOM_MEMORY_SIZE + BLOCK_SIZE);
assert(alloc);
begin_superblock = (uint8_t*)alloc;
while(((uintptr_t)begin_superblock)%BLOCK_SIZE) {
++begin_superblock;
}
end_superblock = begin_superblock + CUSTOM_MEMORY_SIZE;
begin_superblock_range = begin_superblock;
}
typedef struct BlockHeader {
uint32_t check_a;
struct Block* next;
struct Block* prev;
uint8_t* uninit;
void* free_list;
uint32_t chunk_size;
uint32_t allocated_chunks;
uint32_t check_b;
} BlockHeader;
typedef struct Block {
BlockHeader header;
char data[BLOCK_SIZE - sizeof(BlockHeader)];
} Block;
#define BLOCK_EMPTY(b) ((b)->header.allocated_chunks == 0)
#define BLOCK_FULL(b) ((b)->header.uninit == NULL && (b)->header.free_list == NULL)
void* allocate_chunk_from_block(Block* b)
{
b->header.allocated_chunks++;
if(b->header.uninit) {
void* result = b->header.uninit;
b->header.uninit += b->header.chunk_size;
//check if we've run out of uninitialized elements.
if(b->header.uninit + b->header.chunk_size > (uint8_t*)(b+1)) {
b->header.uninit = NULL;
}
return result;
}
assert(b->header.free_list);
void* result = b->header.free_list;
b->header.free_list = *(void**)result;
return result;
}
// inline causes linker errors in debug builds with gcc 4.3.2(-std=c99 and -O0)
#ifdef DEBUG
#define inline
#endif
inline Block* get_block_from_chunk(void* chunk)
#ifdef DEBUG
#undef inline
#endif
{
int8_t* block_ptr = ((int8_t*)chunk) - ((uintptr_t)chunk)%BLOCK_SIZE;
return (Block*)block_ptr;
}
Block* free_chunk_from_block(void* chunk)
{
Block* block = get_block_from_chunk(chunk);
block->header.allocated_chunks--;
*(void**)chunk = block->header.free_list;
block->header.free_list = chunk;
return block;
}
Block* format_block(Block* ptr, int chunk_size)
{
BlockHeader* block = &ptr->header;
block->check_a = 0xFFFFFFFF;
block->check_b = 0xFFFFFFFF;
block->next = NULL;
block->prev = NULL;
block->uninit = (uint8_t*)(block+1);
block->free_list = NULL;
block->chunk_size = chunk_size;
block->allocated_chunks = 0;
return ptr;
}
Block* block_free_list = NULL;
Block* allocate_new_block(uint32_t chunk_size)
{
if(block_free_list == NULL && begin_superblock >= end_superblock) {
return NULL;
}
Block* block;
if(block_free_list != NULL) {
block = block_free_list;
block_free_list = block->header.next;
} else {
block = (Block*)begin_superblock;
begin_superblock += sizeof(Block);
}
return format_block(block, chunk_size);
}
void return_block_to_free_list(Block* block)
{
block->header.next = block_free_list;
block_free_list = block;
}
Block* block_pools[NUM_POOLS];
#define IS_BLOCK_ORPHAN(block) ((block)->header.next == NULL && (block)->header.prev == NULL && block_pools[GET_POOL_INDEX(block->header.chunk_size)] != (block))
void add_block_to_pool(Block* block)
{
assert(block->header.chunk_size > 0 && block->header.chunk_size <= MAX_CHUNK_SIZE);
Block** target = &block_pools[GET_POOL_INDEX(block->header.chunk_size)];
block->header.next = *target;
block->header.prev = NULL;
if(*target) {
(*target)->header.prev = block;
}
*target = block;
}
void make_block_orphan(Block* block)
{
BlockHeader* header = &block->header;
if(block_pools[GET_POOL_INDEX(header->chunk_size)] == block) {
block_pools[GET_POOL_INDEX(header->chunk_size)] = header->next;
}
if(header->prev) {
header->prev->header.next = header->next;
}
if(header->next) {
header->next->header.prev = header->prev;
}
header->prev = NULL;
header->next = NULL;
}
// A list of the chunks that were allocated in the main thread, but free()
// was called in another thread. We can't deallocate them from another thread,
// so we put them in this array. The main thread will free all these chunks,
// whenever it can't immediately allocate memory.
void** free_chunks;
size_t nfree_chunks, capacity_free_chunks;
pthread_mutex_t free_chunks_mutex = PTHREAD_MUTEX_INITIALIZER;
//mutex to protect all calls to dlmalloc.
pthread_mutex_t dlmalloc_mutex = PTHREAD_MUTEX_INITIALIZER;
void free_memory(void* ptr);
void collect_memory_from_other_threads()
{
pthread_mutex_lock(&free_chunks_mutex);
int n;
for(n = 0; n != nfree_chunks; ++n) {
free_memory(free_chunks[n]);
}
nfree_chunks = 0;
pthread_mutex_unlock(&free_chunks_mutex);
}
void free_memory_from_other_thread(void* ptr)
{
pthread_mutex_lock(&free_chunks_mutex);
if(nfree_chunks == capacity_free_chunks) {
capacity_free_chunks *= 2;
if(capacity_free_chunks < 16) {
capacity_free_chunks = 16;
}
pthread_mutex_lock(&dlmalloc_mutex);
void** new_free_chunks = (void**)dlrealloc(free_chunks, sizeof(void*)*capacity_free_chunks);
pthread_mutex_unlock(&dlmalloc_mutex);
if(!new_free_chunks) {
pthread_mutex_unlock(&free_chunks_mutex);
fprintf(stderr, "DLREALLOC FAILED!\n");
return;
}
free_chunks = new_free_chunks;
}
free_chunks[nfree_chunks++] = ptr;
pthread_mutex_unlock(&free_chunks_mutex);
}
Block* get_block(uint32_t chunk_size)
{
const int index = GET_POOL_INDEX(chunk_size);
assert(index >= 0 && index < sizeof(block_pools)/sizeof(*block_pools));
if(block_pools[index]) {
return block_pools[index];
}
// free memory from other threads and then try again. This requires a mutex
// lock, but this code should be rarely reached.
collect_memory_from_other_threads();
if(block_pools[index]) {
return block_pools[index];
}
Block* block = allocate_new_block(chunk_size);
if(block == NULL) {
return block;
}
add_block_to_pool(block);
return block;
}
void* allocate_memory(int32_t size)
{
Block* block = get_block(size);
if(block == NULL) {
return NULL;
}
void* result = allocate_chunk_from_block(block);
if(BLOCK_FULL(block)) {
make_block_orphan(block);
}
return result;
}
void free_memory(void* ptr)
{
Block* block = free_chunk_from_block(ptr);
if(IS_BLOCK_ORPHAN(block)) {
add_block_to_pool(block);
} else if(BLOCK_EMPTY(block)) {
//since the block is empty, return it to the global free list of
//blocks, so it can be moved to a different pool.
make_block_orphan(block);
return_block_to_free_list(block);
}
}
void* malloc(size_t size)
{
if(pthread_equal(pthread_self(), main_thread) && size > 0 && size <= MAX_CHUNK_SIZE) {
size = ROUNDUP_SIZE(size);
void* result = allocate_memory(size);
if(result != NULL) {
return result;
}
}
pthread_mutex_lock(&dlmalloc_mutex);
void* result = dlmalloc(size);
pthread_mutex_unlock(&dlmalloc_mutex);
return result;
}
void* calloc(size_t count, size_t size)
{
pthread_mutex_lock(&dlmalloc_mutex);
void* result = dlcalloc(count, size);
pthread_mutex_unlock(&dlmalloc_mutex);
return result;
}
void* valloc(size_t size)
{
pthread_mutex_lock(&dlmalloc_mutex);
void* result = dlvalloc(size);
pthread_mutex_unlock(&dlmalloc_mutex);
return result;
}
void* memalign(size_t alignment, size_t size)
{
pthread_mutex_lock(&dlmalloc_mutex);
void* result = dlmemalign(alignment, size);
pthread_mutex_unlock(&dlmalloc_mutex);
return result;
}
// Note this function might not be entirely POSIX compatible, but it seems to
// work.
int posix_memalign(void **memptr, size_t alignment, size_t size)
{
pthread_mutex_lock(&dlmalloc_mutex);
*memptr = dlmemalign(alignment, size);
pthread_mutex_unlock(&dlmalloc_mutex);
return errno;
}
void* realloc(void* ptr, size_t size)
{
if(IS_OUR_PTR(ptr)) {
if(size == 0) {
free(ptr);
return NULL;
}
void* new_memory = malloc(size);
if(new_memory == NULL) {
return NULL;
}
const int old_size = get_block_from_chunk(ptr)->header.chunk_size;
const size_t nbytes = size < old_size ? size : old_size;
memcpy(new_memory, ptr, nbytes);
free(ptr);
return new_memory;
}
pthread_mutex_lock(&dlmalloc_mutex);
void* result = dlrealloc(ptr, size);
pthread_mutex_unlock(&dlmalloc_mutex);
return result;
}
void free(void* ptr)
{
if(IS_OUR_PTR(ptr)) {
if(!pthread_equal(pthread_self(), main_thread)) {
//this will queue up the free to be performed later in the
//main thread when it wants more memory.
free_memory_from_other_thread(ptr);
return;
}
free_memory(ptr);
return;
}
pthread_mutex_lock(&dlmalloc_mutex);
dlfree(ptr);
pthread_mutex_unlock(&dlmalloc_mutex);
}
#ifdef TEST_POOLED_ALLOC
int main()
{
init_custom_malloc();
void** items = NULL;
int number_of_items = 0;
while(number_of_items < 100000) {
if(number_of_items) {
int clear = rand()%number_of_items;
while(--clear >= 0) {
int len = rand()%1000;
free(items[clear]);
items[clear] = malloc(len);
assert(items[clear]);
memset(items[clear], 10, len);
}
}
int i = number_of_items;
number_of_items += rand()%100;
items = realloc(items, sizeof(*items)*number_of_items);
while(i != number_of_items) {
int len = rand()%1000;
items[i] = malloc(len);
assert(items[i]);
memset(items[i], 10, len);
++i;
}
}
while(number_of_items--) {
free(items[number_of_items]);
}
return 0;
}
#endif
#endif