summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/restrack.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/restrack.c')
-rw-r--r--src/emu/restrack.c368
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;
+}