diff options
author | 2007-12-17 15:19:59 +0000 | |
---|---|---|
committer | 2007-12-17 15:19:59 +0000 | |
commit | 7b77f1218624ea26dbb2efd85a19f795f5d4e02e (patch) | |
tree | 19209304095572b4fd61c2a2d6a5aa75c4e471ad /src/emu/restrack.c | |
parent | 3da7f476068b3ffef713218ba2fc1bd5030f2c38 (diff) |
Initial checkin of MAME 0.121.mame0121
Diffstat (limited to 'src/emu/restrack.c')
-rw-r--r-- | src/emu/restrack.c | 368 |
1 files changed, 368 insertions, 0 deletions
diff --git a/src/emu/restrack.c b/src/emu/restrack.c new file mode 100644 index 00000000000..3c4bdbe42ad --- /dev/null +++ b/src/emu/restrack.c @@ -0,0 +1,368 @@ +/*************************************************************************** + + restrack.c + + Core MAME resource tracking. + + Copyright (c) 1996-2007, Nicola Salmoria and the MAME Team. + Visit http://mamedev.org for licensing and usage restrictions. + +***************************************************************************/ + +#include "restrack.h" +#include "pool.h" +#include "timer.h" +#include "state.h" + + + +/*************************************************************************** + TYPE DEFINITIONS +***************************************************************************/ + +typedef enum _memory_block_overlap memory_block_overlap; +enum _memory_block_overlap +{ + OVERLAP_NONE, + OVERLAP_PARTIAL, + OVERLAP_FULL +}; + + + +/*************************************************************************** + GLOBAL VARIABLES +***************************************************************************/ + +/* pool list */ +static object_pool *pools[64]; + +/* resource tracking */ +int resource_tracking_tag = 0; + + + +/*************************************************************************** + PROTOTYPES +***************************************************************************/ + +static void astring_destructor(void *object, size_t size); +static void bitmap_destructor(void *object, size_t size); +static memory_block_overlap pool_contains_block(object_pool *pool, void *ptr, size_t size, void **found_block, size_t *found_block_size); + + + +/*************************************************************************** + CORE IMPLEMENTATION +***************************************************************************/ + +/*------------------------------------------------- + malloc_or_die_file_line - allocate memory or die + trying +-------------------------------------------------*/ + +void *malloc_or_die_file_line(size_t size, const char *file, int line) +{ + void *result; + + /* fail on attempted allocations of 0 */ + if (size == 0) + fatalerror("Attempted to malloc zero bytes (%s:%d)", file, line); + + /* allocate and return if we succeeded */ +#ifdef MALLOC_DEBUG + result = malloc_file_line(size, file, line); +#else + result = malloc(size); +#endif + if (result != NULL) + { +#ifdef MAME_DEBUG + rand_memory(result, size); +#endif + return result; + } + + /* otherwise, die horribly */ + fatalerror("Failed to allocate %d bytes (%s:%d)", (int)size, file, line); +} + + +/*------------------------------------------------- + init_resource_tracking - initialize the + resource tracking system +-------------------------------------------------*/ + +void init_resource_tracking(void) +{ + resource_tracking_tag = 0; +} + + +/*------------------------------------------------- + exit_resource_tracking - tear down the + resource tracking system +-------------------------------------------------*/ + +void exit_resource_tracking(void) +{ + while (resource_tracking_tag != 0) + end_resource_tracking(); +} + + +/*------------------------------------------------- + memory_error - report a memory error +-------------------------------------------------*/ + +static void memory_error(const char *message) +{ + fatalerror("%s", message); +} + + +/*------------------------------------------------- + begin_resource_tracking - start tracking + resources +-------------------------------------------------*/ + +void begin_resource_tracking(void) +{ + object_pool *new_pool; + + /* sanity check */ + assert_always(resource_tracking_tag < ARRAY_LENGTH(pools), "Too many memory pools"); + + /* create a new pool */ + new_pool = pool_alloc(memory_error); + if (!new_pool) + fatalerror("Failed to allocate new memory pool"); + pools[resource_tracking_tag] = new_pool; + + /* add resource types */ + pool_type_register(new_pool, OBJTYPE_ASTRING, "String", astring_destructor); + pool_type_register(new_pool, OBJTYPE_BITMAP, "Bitmap", bitmap_destructor); + pool_type_register(new_pool, OBJTYPE_TIMER, "Timer", timer_destructor); + pool_type_register(new_pool, OBJTYPE_STATEREG, "Save State Registration", state_destructor); + + /* increment the tag counter */ + resource_tracking_tag++; +} + + +/*------------------------------------------------- + end_resource_tracking - stop tracking + resources +-------------------------------------------------*/ + +void end_resource_tracking(void) +{ + /* decrement the tag counter */ + resource_tracking_tag--; + + /* free the memory pool */ + pool_free(pools[resource_tracking_tag]); + pools[resource_tracking_tag] = NULL; +} + + +/*------------------------------------------------- + current_pool - identifies the current memory + pool +-------------------------------------------------*/ + +static object_pool *current_pool(void) +{ + object_pool *pool; + assert_always((resource_tracking_tag > 0) && (resource_tracking_tag <= ARRAY_LENGTH(pools)), "Invalid resource_tracking_tag"); + pool = pools[resource_tracking_tag - 1]; + assert_always(pool != NULL, "current_pool() is NULL"); + return pool; +} + + +/*------------------------------------------------- + restrack_register_object - registers an + object with the current pool +-------------------------------------------------*/ + +void *restrack_register_object(object_type type, void *ptr, size_t size, const char *file, int line) +{ + return pool_object_add_file_line(current_pool(), type, ptr, size, file, line); +} + + +/*------------------------------------------------- + auto_malloc_file_line - allocate auto- + freeing memory +-------------------------------------------------*/ + +void *auto_malloc_file_line(size_t size, const char *file, int line) +{ + return pool_malloc_file_line(current_pool(), size, file, line); +} + + +/*------------------------------------------------- + auto_realloc_file_line - reallocate auto- + freeing memory +-------------------------------------------------*/ + +void *auto_realloc_file_line(void *ptr, size_t size, const char *file, int line) +{ + object_pool *pool = current_pool(); + if (ptr != NULL) + { + int tag = resource_tracking_tag; + for (; tag > 0; tag--) + { + pool = pools[tag - 1]; + if (pool_object_exists(pool, OBJTYPE_MEMORY, ptr)) + break; + } + assert_always(tag > 0, "Failed to find alloc in pool"); + } + + return pool_realloc_file_line(pool, ptr, size, file, line); +} + + +/*------------------------------------------------- + auto_strdup_file_line - allocate auto-freeing + string +-------------------------------------------------*/ + +char *auto_strdup_file_line(const char *str, const char *file, int line) +{ + return pool_strdup_file_line(current_pool(), str, file, line); +} + + +/*------------------------------------------------- + auto_strdup_allow_null_file_line - allocate + auto-freeing string if str is null +-------------------------------------------------*/ + +char *auto_strdup_allow_null_file_line(const char *str, const char *file, int line) +{ + return (str != NULL) ? auto_strdup_file_line(str, file, line) : NULL; +} + + +/*------------------------------------------------- + auto_astring_alloc_file_line - allocate + auto-freeing astring +-------------------------------------------------*/ + +astring *auto_astring_alloc_file_line(const char *file, int line) +{ + return restrack_register_object(OBJTYPE_ASTRING, astring_alloc(), 0, file, line); +} + + +/*------------------------------------------------- + auto_bitmap_alloc_file_line - allocate + auto-freeing bitmap +-------------------------------------------------*/ + +bitmap_t *auto_bitmap_alloc_file_line(int width, int height, bitmap_format format, const char *file, int line) +{ + return restrack_register_object(OBJTYPE_BITMAP, bitmap_alloc(width, height, format), width * height, file, line); +} + + +/*------------------------------------------------- + validate_auto_malloc_memory - validate that a + block of memory has been allocated by auto_malloc() +-------------------------------------------------*/ + +void validate_auto_malloc_memory(void *memory, size_t memory_size) +{ + memory_block_overlap overlap = OVERLAP_NONE; + void *block_base = NULL; + size_t block_size = 0; + int i; + + /* scan all pools for an overlapping block */ + for (i = 0; overlap == OVERLAP_NONE && i < resource_tracking_tag; i++) + overlap = pool_contains_block(pools[i], memory, memory_size, &block_base, &block_size); + + /* fatal error if not a full overlap */ + switch (overlap) + { + case OVERLAP_NONE: + fatalerror("Memory block [0x%p-0x%p] not found", memory, (UINT8 *)memory + memory_size - 1); + break; + + case OVERLAP_PARTIAL: + fatalerror("Memory block [0x%p-0x%p] partially overlaps with allocated block [0x%p-0x%p]", memory, (UINT8 *)memory + memory_size - 1, block_base, (UINT8 *)block_base + block_size - 1); + break; + + case OVERLAP_FULL: + /* expected outcome */ + break; + } +} + + +/*------------------------------------------------- + astring_destructor - destructor for astring + objects +-------------------------------------------------*/ + +static void astring_destructor(void *object, size_t size) +{ + astring_free(object); +} + + +/*------------------------------------------------- + bitmap_destructor - destructor for bitmap + objects +-------------------------------------------------*/ + +static void bitmap_destructor(void *object, size_t size) +{ + bitmap_free(object); +} + + +/*------------------------------------------------- + pool_contains_block - determines if a pool + contains a memory block +-------------------------------------------------*/ + +static memory_block_overlap pool_contains_block(object_pool *pool, void *ptr, size_t size, void **found_block, size_t *found_block_size) +{ + memory_block_overlap overlap = OVERLAP_NONE; + object_pool_iterator *iter; + UINT8 *ptrstart = ptr; + UINT8 *ptrend = ptrstart + size - 1; + void *blockptr = NULL; + size_t blocksize = 0; + + /* iterate over memory objects in the pool */ + for (iter = pool_iterate_begin(pool, OBJTYPE_MEMORY); iter != NULL && pool_iterate_next(iter, &blockptr, &blocksize, NULL); ) + { + int startwithin = (ptrstart >= (UINT8 *)blockptr && ptrstart < (UINT8 *)blockptr + blocksize); + int endwithin = (ptrend >= (UINT8 *)blockptr && ptrend < (UINT8 *)blockptr + blocksize); + + /* if the start of the incoming pointer lies within the block... */ + if (startwithin || endwithin) + { + overlap = (startwithin && endwithin) ? OVERLAP_FULL : OVERLAP_PARTIAL; + break; + } + } + pool_iterate_end(iter); + + /* store the results */ + if (overlap != OVERLAP_NONE) + { + if (found_block != NULL) + *found_block = blockptr; + if (found_block_size != NULL) + *found_block_size = blocksize; + } + return overlap; +} |