summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/util/corealloc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/util/corealloc.cpp')
-rw-r--r--src/lib/util/corealloc.cpp432
1 files changed, 0 insertions, 432 deletions
diff --git a/src/lib/util/corealloc.cpp b/src/lib/util/corealloc.cpp
deleted file mode 100644
index 38f21846f96..00000000000
--- a/src/lib/util/corealloc.cpp
+++ /dev/null
@@ -1,432 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Aaron Giles
-/***************************************************************************
-
- corealloc.c
-
- Memory allocation helpers for the helper library.
-
-***************************************************************************/
-
-#include "corealloc.h"
-#include "osdcore.h"
-
-
-//**************************************************************************
-// DEBUGGING
-//**************************************************************************
-
-#define LOG_ALLOCS (0)
-#define DEBUG_MISMATCHED_ALLOCS (0)
-
-// define this to initialize allocated memory to a fixed non-0 value
-#ifdef MAME_DEBUG
-#define INITIALIZE_ALLOCATED_MEMORY
-#endif
-
-// define this to zap memory to a fixed non-0 value before freeing
-//#define OVERWRITE_FREED_MEMORY
-
-// compatibility with non-clang compilers
-#ifndef __has_feature
- #define __has_feature(x) 0
-#endif
-
-
-//**************************************************************************
-// CONSTANTS
-//**************************************************************************
-
-// number of memory_entries to allocate in a block
-const int memory_block_alloc_chunk = 256;
-
-
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-// this struct is allocated in pools to track memory allocations
-// it must be a POD type!!
-class memory_entry
-{
-public:
- // internal state
- 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
- bool m_array; // array?
-
- // hashing prime number
- static const int k_hash_prime = 6151;
-
- // global state
- 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 helpers
- static memory_entry *allocate(size_t size, void *base, const char *file, int line, bool array);
- static memory_entry *find(void *ptr);
- static void release(memory_entry *entry, const char *file, int line);
- static void report_unfreed(UINT64 start);
-
-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 = nullptr;
-bool memory_entry::s_lock_alloc = false;
-bool memory_entry::s_tracking = false;
-memory_entry *memory_entry::s_hash[memory_entry::k_hash_prime] = { nullptr };
-memory_entry *memory_entry::s_freehead = nullptr;
-
-//**************************************************************************
-// OPERATOR REPLACEMENTS
-//**************************************************************************
-
-#ifndef NO_MEM_TRACKING
-
-// standard new/delete operators (try to avoid using)
-void *operator new(std::size_t size) throw (std::bad_alloc) { return malloc_file_line(size, nullptr, 0, false, true, false); }
-void *operator new[](std::size_t size) throw (std::bad_alloc) { return malloc_file_line(size, nullptr, 0, true, true, false); }
-void operator delete(void *ptr) throw() { if (ptr != nullptr) free_file_line(ptr, nullptr, 0, false); }
-void operator delete[](void *ptr) throw() { if (ptr != nullptr) free_file_line(ptr, nullptr, 0, true); }
-
-void* operator new(std::size_t size,const std::nothrow_t&) throw() { return malloc_file_line(size, nullptr, 0, false, false, false); }
-void* operator new[](std::size_t size, const std::nothrow_t&) throw() { return malloc_file_line(size, nullptr, 0, true, false, false); }
-void operator delete(void* ptr, const std::nothrow_t&) throw() { if (ptr != nullptr) free_file_line(ptr, nullptr, 0, false); }
-void operator delete[](void* ptr, const std::nothrow_t&) throw() { if (ptr != nullptr) free_file_line(ptr, nullptr, 0, true); }
-
-#endif
-
-//**************************************************************************
-// OPERATOR OVERLOADS - DEFINITIONS
-//**************************************************************************
-
-// file/line new/delete operators
-void *operator new(std::size_t size, const char *file, int line) throw (std::bad_alloc) { return malloc_file_line(size, file, line, false, true, false); }
-void *operator new[](std::size_t size, const char *file, int line) throw (std::bad_alloc) { return malloc_file_line(size, file, line, true, true, false); }
-void operator delete(void *ptr, const char *file, int line) { if (ptr != nullptr) free_file_line(ptr, file, line, false); }
-void operator delete[](void *ptr, const char *file, int line) { if (ptr != nullptr) free_file_line(ptr, file, line, true); }
-
-// file/line new/delete operators with zeroing
-void *operator new(std::size_t size, const char *file, int line, const zeromem_t &) throw (std::bad_alloc) { return malloc_file_line(size, file, line, false, true, true); }
-void *operator new[](std::size_t size, const char *file, int line, const zeromem_t &) throw (std::bad_alloc) { return malloc_file_line(size, file, line, true, true, true); }
-void operator delete(void *ptr, const char *file, int line, const zeromem_t &) { if (ptr != nullptr) free_file_line(ptr, file, line, false); }
-void operator delete[](void *ptr, const char *file, int line, const zeromem_t &) { if (ptr != nullptr) free_file_line(ptr, file, line, true); }
-
-
-
-//**************************************************************************
-// 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, bool array, bool throw_on_fail, bool clear)
-{
- // allocate the memory and fail if we can't
- void *result = array ? osd_malloc_array(size) : osd_malloc(size);
- if (result == nullptr)
- {
- fprintf(stderr, "Failed to allocate %d bytes (%s:%d)\n", UINT32(size), file, line);
- osd_break_into_debugger("Failed to allocate RAM");
- if (throw_on_fail)
- throw std::bad_alloc();
- return nullptr;
- }
-
- // zap the memory if requested
- if (clear)
- memset(result, 0, size);
- else
- {
-#if !__has_feature(memory_sanitizer) && defined(INITIALIZE_ALLOCATED_MEMORY) && !defined(MAME_DEBUG_FAST)
- memset(result, 0xdd, size);
-#endif
- }
-
- // add a new entry
- memory_entry::allocate(size, result, file, line, array);
-
- return result;
-}
-
-
-//-------------------------------------------------
-// free_file_line - free memory with file
-// and line number information
-//-------------------------------------------------
-
-void free_file_line(void *memory, const char *file, int line, bool array)
-{
- // find the memory entry
- memory_entry *entry = memory_entry::find(memory);
-
- // warn about untracked frees
- if (entry == nullptr)
- {
- fprintf(stderr, "Error: attempt to free untracked memory %p in %s(%d)!\n", memory, file, line);
- osd_break_into_debugger("Error: attempt to free untracked memory");
- return;
- }
-
- // warn about mismatched arrays
- if (!array && entry->m_array)
- {
- fprintf(stderr, "Warning: attempt to free array %p with global_free in %s(%d)!\n", memory, file, line);
- if (DEBUG_MISMATCHED_ALLOCS) {
- osd_break_into_debugger("Error: attempt to free array with global_free");
- }
- }
- if (array && !entry->m_array)
- {
-#ifndef __INTEL_COMPILER // todo: fix this properly, it appears some optimization the compiler applies breaks our logic here
- fprintf(stderr, "Warning: attempt to free single object %p with global_free_array in %s(%d)!\n", memory, file, line);
- if (DEBUG_MISMATCHED_ALLOCS) {
- osd_break_into_debugger("Error: attempt to free single object with global_free_array");
- }
-#endif
- }
-
-#ifdef OVERWRITE_FREED_MEMORY
- // clear memory to a bogus value
- memset(memory, 0xfc, entry->m_size);
-#endif
-
- // free the entry and the memory
- memory_entry::release(entry, file, line);
- osd_free(memory);
-}
-
-
-//-------------------------------------------------
-// track_memory - enables or disables the memory
-// tracking
-//-------------------------------------------------
-
-void track_memory(bool track)
-{
- memory_entry::s_tracking = track;
-}
-
-
-//-------------------------------------------------
-// next_memory_id - return the ID of the next
-// allocated block
-//-------------------------------------------------
-
-UINT64 next_memory_id()
-{
- return memory_entry::s_curid;
-}
-
-
-//-------------------------------------------------
-// dump_unfreed_mem - called from the exit path
-// of any code that wants to check for unfreed
-// memory
-//-------------------------------------------------
-
-void dump_unfreed_mem(UINT64 start)
-{
- memory_entry::report_unfreed(start);
-}
-
-
-
-//**************************************************************************
-// 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 == nullptr)
- {
- 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, bool array)
-{
- acquire_lock();
-
- // if we're out of free entries, allocate a new chunk
- if (s_freehead == nullptr)
- {
- // 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 == nullptr)
- {
- release_lock();
- return nullptr;
- }
-
- // 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 : nullptr;
- entry->m_line = s_tracking ? line : 0;
- entry->m_id = s_curid++;
- entry->m_array = array;
- 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 != nullptr)
- entry->m_next->m_prev = entry;
- entry->m_prev = nullptr;
- 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 == nullptr)
- return nullptr;
-
- // 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 != nullptr; 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, const char *file, int line)
-{
- acquire_lock();
-
- if (LOG_ALLOCS)
- fprintf(stderr, "#%06d, release %d bytes (%s:%d)\n", (UINT32)entry->m_id, static_cast<UINT32>(entry->m_size), file, line);
-
- // remove ourselves from the alloc list
- int hashval = reinterpret_cast<FPTR>(entry->m_base) % k_hash_prime;
- if (entry->m_prev != nullptr)
- entry->m_prev->m_next = entry->m_next;
- else
- s_hash[hashval] = entry->m_next;
- if (entry->m_next != nullptr)
- entry->m_next->m_prev = entry->m_prev;
-
- // add ourself to the free list
- entry->m_next = s_freehead;
- s_freehead = entry;
-
- release_lock();
-}
-
-/**
- * @fn void memory_entry::report_unfreed(UINT64 start)
- *
- * @brief -------------------------------------------------
- * report_unfreed - print a list of unfreed memory to the target file
- * -------------------------------------------------.
- *
- * @param start The start.
- */
-
-void memory_entry::report_unfreed(UINT64 start)
-{
- acquire_lock();
-
- // check for leaked memory
- UINT32 total = 0;
-
- for (auto entry : s_hash)
- for (; entry != nullptr; entry = entry->m_next)
- if (entry->m_file != nullptr && entry->m_id >= start)
- {
- 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);
-}