summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/emualloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/emualloc.c')
-rw-r--r--src/emu/emualloc.c370
1 files changed, 6 insertions, 364 deletions
diff --git a/src/emu/emualloc.c b/src/emu/emualloc.c
index 22c0e044fed..adf6cd21419 100644
--- a/src/emu/emualloc.c
+++ b/src/emu/emualloc.c
@@ -21,195 +21,10 @@
//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-// align all allocated memory to this size
-//const int memory_align = 16;
-
-// number of memory_entries to allocate in a block
-const int memory_block_alloc_chunk = 256;
-
-
-
-//**************************************************************************
-// MACROS
-//**************************************************************************
-
-// enable deletion
-#undef delete
-
-
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// this struct is allocated in pools to track memory allocations
-// it must be a POD type!!
-class memory_entry
-{
-public:
- memory_entry * m_next; // link to the next entry
- memory_entry * m_prev; // link to the previous entry
- size_t m_size; // size of the allocation (not including this header)
- void * m_base; // base of the allocation
- const char * m_file; // file the allocation was made from
- int m_line; // line number within that file
- UINT64 m_id; // unique id
-
- static const int k_hash_prime = 6151;
-
- static UINT64 s_curid; // current ID
- static osd_lock * s_lock; // lock for managing the list
- static bool s_lock_alloc; // set to true temporarily during lock allocation
- static bool s_tracking; // set to true when tracking is live
- static memory_entry *s_hash[k_hash_prime];// hash table based on pointer
- static memory_entry *s_freehead; // pointer to the head of the free list
-
- static memory_entry *allocate(size_t size, void *base, const char *file, int line);
- static memory_entry *find(void *ptr);
- static void release(memory_entry *entry);
- static void report_unfreed();
-
-private:
- static void acquire_lock();
- static void release_lock();
-};
-
-
-
-//**************************************************************************
// GLOBALS
//**************************************************************************
-// dummy zeromem object
-const zeromem_t zeromem = { };
-
-// globals for memory_entry
-UINT64 memory_entry::s_curid = 1;
-osd_lock *memory_entry::s_lock = NULL;
-bool memory_entry::s_lock_alloc = false;
-bool memory_entry::s_tracking = false;
-memory_entry *memory_entry::s_hash[memory_entry::k_hash_prime] = { NULL };
-memory_entry *memory_entry::s_freehead = NULL;
-
-// wrapper for the global resource pool to help ensure construction order
-resource_pool &global_resource_pool()
-{
- static resource_pool s_pool(6151);
- return s_pool;
-};
-
-
-//**************************************************************************
-// GLOBAL HELPERS
-//**************************************************************************
-
-//-------------------------------------------------
-// malloc_file_line - allocate memory with file
-// and line number information
-//-------------------------------------------------
-
-void *malloc_file_line(size_t size, const char *file, int line)
-{
- // allocate the memory and fail if we can't
- void *result = osd_malloc(size);
- if (result == NULL)
- return NULL;
-
- // add a new entry
- memory_entry::allocate(size, result, file, line);
-
-#if !__has_feature(memory_sanitizer) && defined(MAME_DEBUG)
- memset(result, 0xdd, size);
-#endif
-
- return result;
-}
-
-
-//-------------------------------------------------
-// malloc_array_file_line - allocate memory with
-// file and line number information, and a hint
-// that this object is an array
-//-------------------------------------------------
-
-void *malloc_array_file_line(size_t size, const char *file, int line)
-{
- // allocate the memory and fail if we can't
- void *result = osd_malloc_array(size);
- if (result == NULL)
- return NULL;
-
- // add a new entry
- memory_entry::allocate(size, result, file, line);
-
-#if !__has_feature(memory_sanitizer) && defined(MAME_DEBUG)
- memset(result, 0xdd, size);
-#endif
-
- return result;
-}
-
-
-//-------------------------------------------------
-// free_file_line - free memory with file
-// and line number information
-//-------------------------------------------------
-
-void free_file_line(void *memory, const char *file, int line)
-{
- // ignore NULL frees/deletes
- if (memory == NULL)
- return;
-
- // find the memory entry
- memory_entry *entry = memory_entry::find(memory);
-
- // warn about untracked frees
- if (entry == NULL)
- {
- fprintf(stderr, "Error: attempt to free untracked memory in %s(%d)!\n", file, line);
- osd_break_into_debugger("Error: attempt to free untracked memory");
- return;
- }
-
-#ifdef MAME_DEBUG
- // clear memory to a bogus value
- memset(memory, 0xfc, entry->m_size);
-#endif
-
- // free the entry and the memory
- memory_entry::release(entry);
- osd_free(memory);
-}
-
-
-//-------------------------------------------------
-// dump_unfreed_mem - called from the exit path
-// of any code that wants to check for unfreed
-// memory
-//-------------------------------------------------
-
-void track_memory(bool track)
-{
- memory_entry::s_tracking = track;
-}
-
-
-//-------------------------------------------------
-// dump_unfreed_mem - called from the exit path
-// of any code that wants to check for unfreed
-// memory
-//-------------------------------------------------
-
-void dump_unfreed_mem()
-{
-#ifdef MAME_DEBUG
- memory_entry::report_unfreed();
-#endif
-}
+UINT64 resource_pool::s_id = 0;
@@ -225,11 +40,10 @@ void dump_unfreed_mem()
resource_pool::resource_pool(int hash_size)
: m_hash_size(hash_size),
m_listlock(osd_lock_alloc()),
- m_hash(new resource_pool_item *[hash_size]),
+ m_hash(hash_size, 0),
m_ordered_head(NULL),
m_ordered_tail(NULL)
{
- memset(m_hash, 0, hash_size * sizeof(m_hash[0]));
}
@@ -244,7 +58,6 @@ resource_pool::~resource_pool()
clear();
if (m_listlock != NULL)
osd_lock_free(m_listlock);
- delete[] m_hash;
}
@@ -252,7 +65,7 @@ resource_pool::~resource_pool()
// add - add a new item to the resource pool
//-------------------------------------------------
-void resource_pool::add(resource_pool_item &item)
+void resource_pool::add(resource_pool_item &item, size_t size, const char *type)
{
osd_lock_acquire(m_listlock);
@@ -263,13 +76,9 @@ void resource_pool::add(resource_pool_item &item)
// fetch the ID of this item's pointer; some implementations put hidden data
// before, so if we don't find it, check 4 bytes ahead
- memory_entry *entry = memory_entry::find(item.m_ptr);
- if (entry == NULL)
- entry = memory_entry::find(reinterpret_cast<UINT8 *>(item.m_ptr) - sizeof(size_t));
- assert(entry != NULL);
- item.m_id = entry->m_id;
+ item.m_id = ++s_id;
if (LOG_ALLOCS)
- fprintf(stderr, "#%06d, add %d bytes (%s:%d)\n", (UINT32)entry->m_id, static_cast<UINT32>(entry->m_size), entry->m_file, (int)entry->m_line);
+ fprintf(stderr, "#%06d, add %s, %d bytes\n", (UINT32)item.m_id, type, size);
// find the entry to insert after
resource_pool_item *insert_after;
@@ -340,7 +149,7 @@ void resource_pool::remove(void *ptr)
// delete the object and break
if (LOG_ALLOCS)
fprintf(stderr, "#%06d, delete %d bytes\n", (UINT32)deleteme->m_id, static_cast<UINT32>(deleteme->m_size));
- delete deleteme;
+ global_free(deleteme);
break;
}
@@ -414,170 +223,3 @@ void resource_pool::clear()
osd_lock_release(m_listlock);
}
-
-
-
-//**************************************************************************
-// MEMORY ENTRY
-//**************************************************************************
-
-//-------------------------------------------------
-// acquire_lock - acquire the memory entry lock,
-// creating a new one if needed
-//-------------------------------------------------
-
-void memory_entry::acquire_lock()
-{
- // allocate a lock on first usage
- // note that osd_lock_alloc() may re-enter this path, so protect against recursion!
- if (s_lock == NULL)
- {
- if (s_lock_alloc)
- return;
- s_lock_alloc = true;
- s_lock = osd_lock_alloc();
- s_lock_alloc = false;
- }
- osd_lock_acquire(s_lock);
-}
-
-
-//-------------------------------------------------
-// release_lock - release the memory entry lock
-//-------------------------------------------------
-
-void memory_entry::release_lock()
-{
- osd_lock_release(s_lock);
-}
-
-
-//-------------------------------------------------
-// allocate - allocate a new memory entry
-//-------------------------------------------------
-
-memory_entry *memory_entry::allocate(size_t size, void *base, const char *file, int line)
-{
- acquire_lock();
-
- // if we're out of free entries, allocate a new chunk
- if (s_freehead == NULL)
- {
- // create a new chunk, and fail if we can't
- memory_entry *entry = reinterpret_cast<memory_entry *>(osd_malloc_array(memory_block_alloc_chunk * sizeof(memory_entry)));
- if (entry == NULL)
- {
- release_lock();
- return NULL;
- }
-
- // add all the entries to the list
- for (int entrynum = 0; entrynum < memory_block_alloc_chunk; entrynum++)
- {
- entry->m_next = s_freehead;
- s_freehead = entry++;
- }
- }
-
- // grab a free entry
- memory_entry *entry = s_freehead;
- s_freehead = entry->m_next;
-
- // populate it
- entry->m_size = size;
- entry->m_base = base;
- entry->m_file = s_tracking ? file : NULL;
- entry->m_line = s_tracking ? line : 0;
- entry->m_id = s_curid++;
- if (LOG_ALLOCS)
- fprintf(stderr, "#%06d, alloc %d bytes (%s:%d)\n", (UINT32)entry->m_id, static_cast<UINT32>(entry->m_size), entry->m_file, (int)entry->m_line);
-
- // add it to the alloc list
- int hashval = reinterpret_cast<FPTR>(base) % k_hash_prime;
- entry->m_next = s_hash[hashval];
- if (entry->m_next != NULL)
- entry->m_next->m_prev = entry;
- entry->m_prev = NULL;
- s_hash[hashval] = entry;
-
- release_lock();
- return entry;
-}
-
-
-//-------------------------------------------------
-// find - find a memory entry
-//-------------------------------------------------
-
-memory_entry *memory_entry::find(void *ptr)
-{
- // NULL maps to nothing
- if (ptr == NULL)
- return NULL;
-
- // scan the list under the lock
- acquire_lock();
-
- int hashval = reinterpret_cast<FPTR>(ptr) % k_hash_prime;
- memory_entry *entry;
- for (entry = s_hash[hashval]; entry != NULL; entry = entry->m_next)
- if (entry->m_base == ptr)
- break;
-
- release_lock();
- return entry;
-}
-
-
-//-------------------------------------------------
-// release - release a memory entry
-//-------------------------------------------------
-
-void memory_entry::release(memory_entry *entry)
-{
- acquire_lock();
-
- // remove ourselves from the alloc list
- int hashval = reinterpret_cast<FPTR>(entry->m_base) % k_hash_prime;
- if (entry->m_prev != NULL)
- entry->m_prev->m_next = entry->m_next;
- else
- s_hash[hashval] = entry->m_next;
- if (entry->m_next != NULL)
- entry->m_next->m_prev = entry->m_prev;
-
- // add ourself to the free list
- entry->m_next = s_freehead;
- s_freehead = entry;
-
- release_lock();
-}
-
-
-//-------------------------------------------------
-// report_unfreed - print a list of unfreed
-// memory to the target file
-//-------------------------------------------------
-
-void memory_entry::report_unfreed()
-{
- acquire_lock();
-
- // check for leaked memory
- UINT32 total = 0;
-
- for (int hashnum = 0; hashnum < k_hash_prime; hashnum++)
- for (memory_entry *entry = s_hash[hashnum]; entry != NULL; entry = entry->m_next)
- if (entry->m_file != NULL)
- {
- if (total == 0)
- fprintf(stderr, "--- memory leak warning ---\n");
- total += entry->m_size;
- fprintf(stderr, "#%06d, nofree %d bytes (%s:%d)\n", (UINT32)entry->m_id, static_cast<UINT32>(entry->m_size), entry->m_file, (int)entry->m_line);
- }
-
- release_lock();
-
- if (total > 0)
- fprintf(stderr, "a total of %u bytes were not freed\n", total);
-}