Non-debug builds need to free those memory_entries. Fixes enormous

memory consumption when iterating through all drivers like -romident
does.

Also moved softlist scanning into the main loop so that machine_configs
are only constructed once.
This commit is contained in:
Aaron Giles 2011-03-10 07:06:21 +00:00
parent d49ead22c9
commit 46550a475b
3 changed files with 219 additions and 217 deletions

View File

@ -1068,13 +1068,8 @@ static void info_listsoftware(emu_options &options, const char *gamename)
softlist_match_roms - scan for a matching softlist_match_roms - scan for a matching
software ROM by hash software ROM by hash
-------------------------------------------------*/ -------------------------------------------------*/
static void softlist_match_roms(emu_options &options, const hash_collection &hashes, int length, int *found) void softlist_match_roms(machine_config &config, emu_options &options, const hash_collection &hashes, int length, int *found)
{ {
/* iterate over drivers */
for (int drvindex = 0; drivers[drvindex] != NULL; drvindex++)
{
machine_config config(*drivers[drvindex]);
for (const device_config *dev = config.m_devicelist.first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext()) for (const device_config *dev = config.m_devicelist.first(SOFTWARE_LIST); dev != NULL; dev = dev->typenext())
{ {
software_list_config *swlist = (software_list_config *)downcast<const legacy_device_config_base *>(dev)->inline_config(); software_list_config *swlist = (software_list_config *)downcast<const legacy_device_config_base *>(dev)->inline_config();
@ -1113,7 +1108,6 @@ static void softlist_match_roms(emu_options &options, const hash_collection &has
} }
} }
} }
}
} }
/*------------------------------------------------- /*-------------------------------------------------
@ -1507,7 +1501,6 @@ static void identify_data(emu_options &options, const char *name, const UINT8 *d
status->matches++; status->matches++;
/* free any temporary JED data */ /* free any temporary JED data */
if (tempjed != NULL)
global_free(tempjed); global_free(tempjed);
} }
@ -1518,19 +1511,15 @@ static void identify_data(emu_options &options, const char *name, const UINT8 *d
static void match_roms(emu_options &options, const hash_collection &hashes, int length, int *found) static void match_roms(emu_options &options, const hash_collection &hashes, int length, int *found)
{ {
int drvindex;
/* iterate over drivers */ /* iterate over drivers */
for (drvindex = 0; drivers[drvindex] != NULL; drvindex++) for (int drvindex = 0; drivers[drvindex] != NULL; drvindex++)
{ {
machine_config config(*drivers[drvindex]); machine_config config(*drivers[drvindex]);
const rom_entry *region, *rom;
const rom_source *source;
/* iterate over sources, regions and files within the region */ /* iterate over sources, regions and files within the region */
for (source = rom_first_source(config); source != NULL; source = rom_next_source(*source)) for (const rom_source *source = rom_first_source(config); source != NULL; source = rom_next_source(*source))
for (region = rom_first_region(*source); region; region = rom_next_region(region)) for (const rom_entry *region = rom_first_region(*source); region; region = rom_next_region(region))
for (rom = rom_first_file(region); rom; rom = rom_next_file(rom)) for (const rom_entry *rom = rom_first_file(region); rom; rom = rom_next_file(rom))
{ {
hash_collection romhashes(ROM_GETHASHDATA(rom)); hash_collection romhashes(ROM_GETHASHDATA(rom));
if (!romhashes.flag(hash_collection::FLAG_NO_DUMP) && hashes == romhashes) if (!romhashes.flag(hash_collection::FLAG_NO_DUMP) && hashes == romhashes)
@ -1544,7 +1533,8 @@ static void match_roms(emu_options &options, const hash_collection &hashes, int
(*found)++; (*found)++;
} }
} }
}
softlist_match_roms( options, hashes, length, found ); // also check any softlists
softlist_match_roms( config, options, hashes, length, found );
}
} }

View File

@ -41,6 +41,14 @@
#include "coreutil.h" #include "coreutil.h"
//**************************************************************************
// DEBUGGING
//**************************************************************************
#define LOG_ALLOCS (0)
//************************************************************************** //**************************************************************************
// CONSTANTS // CONSTANTS
//************************************************************************** //**************************************************************************
@ -122,10 +130,10 @@ memory_entry *memory_entry::s_freehead = NULL;
// GLOBAL HELPERS // GLOBAL HELPERS
//************************************************************************** //**************************************************************************
/*------------------------------------------------- //-------------------------------------------------
malloc_file_line - allocate memory with file // malloc_file_line - allocate memory with file
and line number information // and line number information
-------------------------------------------------*/ //-------------------------------------------------
void *malloc_file_line(size_t size, const char *file, int line) void *malloc_file_line(size_t size, const char *file, int line)
{ {
@ -146,10 +154,10 @@ void *malloc_file_line(size_t size, const char *file, int line)
} }
/*------------------------------------------------- //-------------------------------------------------
free_file_line - free memory with file // free_file_line - free memory with file
and line number information // and line number information
-------------------------------------------------*/ //-------------------------------------------------
void free_file_line(void *memory, const char *file, int line) void free_file_line(void *memory, const char *file, int line)
{ {
@ -167,21 +175,19 @@ void free_file_line(void *memory, const char *file, int line)
#ifdef MAME_DEBUG #ifdef MAME_DEBUG
// clear memory to a bogus value // clear memory to a bogus value
memset(memory, 0xfc, entry->m_size); memset(memory, 0xfc, entry->m_size);
// free the entry and the memory
if (entry != NULL)
memory_entry::release(entry);
#endif #endif
// free the entry and the memory
memory_entry::release(entry);
osd_free(memory); osd_free(memory);
} }
/*------------------------------------------------- //-------------------------------------------------
dump_unfreed_mem - called from the exit path // dump_unfreed_mem - called from the exit path
of any code that wants to check for unfreed // of any code that wants to check for unfreed
memory // memory
-------------------------------------------------*/ //-------------------------------------------------
void dump_unfreed_mem(void) void dump_unfreed_mem(void)
{ {
@ -196,10 +202,10 @@ void dump_unfreed_mem(void)
// RESOURCE POOL // RESOURCE POOL
//************************************************************************** //**************************************************************************
/*------------------------------------------------- //-------------------------------------------------
resource_pool - constructor for a new resource // resource_pool - constructor for a new resource
pool // pool
-------------------------------------------------*/ //-------------------------------------------------
resource_pool::resource_pool() resource_pool::resource_pool()
: m_listlock(osd_lock_alloc()), : m_listlock(osd_lock_alloc()),
@ -210,11 +216,11 @@ resource_pool::resource_pool()
} }
/*------------------------------------------------- //-------------------------------------------------
~resource_pool - destructor for a resource // ~resource_pool - destructor for a resource
pool; make sure all tracked objects are // pool; make sure all tracked objects are
deleted // deleted
-------------------------------------------------*/ //-------------------------------------------------
resource_pool::~resource_pool() resource_pool::~resource_pool()
{ {
@ -224,9 +230,9 @@ resource_pool::~resource_pool()
} }
/*------------------------------------------------- //-------------------------------------------------
add - add a new item to the 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)
{ {
@ -244,6 +250,8 @@ void resource_pool::add(resource_pool_item &item)
entry = memory_entry::find(reinterpret_cast<UINT8 *>(item.m_ptr) - sizeof(size_t)); entry = memory_entry::find(reinterpret_cast<UINT8 *>(item.m_ptr) - sizeof(size_t));
assert(entry != NULL); assert(entry != NULL);
item.m_id = entry->m_id; item.m_id = entry->m_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);
// find the entry to insert after // find the entry to insert after
resource_pool_item *insert_after; resource_pool_item *insert_after;
@ -277,10 +285,10 @@ void resource_pool::add(resource_pool_item &item)
} }
/*------------------------------------------------- //-------------------------------------------------
remove - remove a specific item from the // remove - remove a specific item from the
resource pool // resource pool
-------------------------------------------------*/ //-------------------------------------------------
void resource_pool::remove(void *ptr) void resource_pool::remove(void *ptr)
{ {
@ -312,6 +320,8 @@ void resource_pool::remove(void *ptr)
m_ordered_tail = deleteme->m_ordered_prev; m_ordered_tail = deleteme->m_ordered_prev;
// delete the object and break // 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; delete deleteme;
break; break;
} }
@ -320,10 +330,10 @@ void resource_pool::remove(void *ptr)
} }
/*------------------------------------------------- //-------------------------------------------------
find - find a specific item in the resource // find - find a specific item in the resource
pool // pool
-------------------------------------------------*/ //-------------------------------------------------
resource_pool_item *resource_pool::find(void *ptr) resource_pool_item *resource_pool::find(void *ptr)
{ {
@ -342,10 +352,10 @@ resource_pool_item *resource_pool::find(void *ptr)
} }
/*------------------------------------------------- //-------------------------------------------------
contains - return true if given ptr is // contains - return true if given ptr is
contained by one of the objects in the pool // contained by one of the objects in the pool
-------------------------------------------------*/ //-------------------------------------------------
bool resource_pool::contains(void *_ptrstart, void *_ptrend) bool resource_pool::contains(void *_ptrstart, void *_ptrend)
{ {
@ -371,9 +381,9 @@ found:
} }
/*------------------------------------------------- //-------------------------------------------------
clear - remove all items from a resource pool // clear - remove all items from a resource pool
-------------------------------------------------*/ //-------------------------------------------------
void resource_pool::clear() void resource_pool::clear()
{ {
@ -393,10 +403,10 @@ void resource_pool::clear()
// MEMORY ENTRY // MEMORY ENTRY
//************************************************************************** //**************************************************************************
/*------------------------------------------------- //-------------------------------------------------
acquire_lock - acquire the memory entry lock, // acquire_lock - acquire the memory entry lock,
creating a new one if needed // creating a new one if needed
-------------------------------------------------*/ //-------------------------------------------------
void memory_entry::acquire_lock() void memory_entry::acquire_lock()
{ {
@ -414,9 +424,9 @@ void memory_entry::acquire_lock()
} }
/*------------------------------------------------- //-------------------------------------------------
release_lock - release the memory entry lock // release_lock - release the memory entry lock
-------------------------------------------------*/ //-------------------------------------------------
void memory_entry::release_lock() void memory_entry::release_lock()
{ {
@ -424,9 +434,9 @@ void memory_entry::release_lock()
} }
/*------------------------------------------------- //-------------------------------------------------
allocate - allocate a new memory entry // allocate - allocate a new memory entry
-------------------------------------------------*/ //-------------------------------------------------
memory_entry *memory_entry::allocate(size_t size, void *base, const char *file, int line) memory_entry *memory_entry::allocate(size_t size, void *base, const char *file, int line)
{ {
@ -461,6 +471,8 @@ memory_entry *memory_entry::allocate(size_t size, void *base, const char *file,
entry->m_file = file; entry->m_file = file;
entry->m_line = line; entry->m_line = line;
entry->m_id = s_curid++; 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 // add it to the alloc list
int hashval = reinterpret_cast<FPTR>(base) % k_hash_prime; int hashval = reinterpret_cast<FPTR>(base) % k_hash_prime;
@ -475,9 +487,9 @@ memory_entry *memory_entry::allocate(size_t size, void *base, const char *file,
} }
/*------------------------------------------------- //-------------------------------------------------
find - find a memory entry // find - find a memory entry
-------------------------------------------------*/ //-------------------------------------------------
memory_entry *memory_entry::find(void *ptr) memory_entry *memory_entry::find(void *ptr)
{ {
@ -499,9 +511,9 @@ memory_entry *memory_entry::find(void *ptr)
} }
/*------------------------------------------------- //-------------------------------------------------
release - release a memory entry // release - release a memory entry
-------------------------------------------------*/ //-------------------------------------------------
void memory_entry::release(memory_entry *entry) void memory_entry::release(memory_entry *entry)
{ {
@ -524,10 +536,10 @@ void memory_entry::release(memory_entry *entry)
} }
/*------------------------------------------------- //-------------------------------------------------
report_unfreed - print a list of unfreed // report_unfreed - print a list of unfreed
memory to the target file // memory to the target file
-------------------------------------------------*/ //-------------------------------------------------
void memory_entry::report_unfreed() void memory_entry::report_unfreed()
{ {
@ -543,7 +555,7 @@ void memory_entry::report_unfreed()
if (total == 0) if (total == 0)
fprintf(stderr, "--- memory leak warning ---\n"); fprintf(stderr, "--- memory leak warning ---\n");
total += entry->m_size; total += entry->m_size;
fprintf(stderr, "allocation #%06d, %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, 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(); release_lock();

View File

@ -67,13 +67,125 @@
//************************************************************************** //**************************************************************************
// TYPE DEFINITIONS // FUNCTION PROTOTYPES
//**************************************************************************
// allocate memory with file and line number information
void *malloc_file_line(size_t size, const char *file, int line);
// free memory with file and line number information
void free_file_line(void *memory, const char *file, int line);
// called from the exit path of any code that wants to check for unfreed memory
void dump_unfreed_mem();
//**************************************************************************
// INLINE FUNCTIONS
//************************************************************************** //**************************************************************************
// zeromem_t is a dummy class used to tell new to zero memory after allocation // zeromem_t is a dummy class used to tell new to zero memory after allocation
class zeromem_t { }; class zeromem_t { };
// standard new/delete operators (try to avoid using)
ATTR_FORCE_INLINE inline void *operator new(std::size_t size) throw (std::bad_alloc)
{
void *result = malloc_file_line(size, NULL, 0);
if (result == NULL)
throw std::bad_alloc();
return result;
}
ATTR_FORCE_INLINE inline void *operator new[](std::size_t size) throw (std::bad_alloc)
{
void *result = malloc_file_line(size, NULL, 0);
if (result == NULL)
throw std::bad_alloc();
return result;
}
ATTR_FORCE_INLINE inline void operator delete(void *ptr) throw()
{
if (ptr != NULL)
free_file_line(ptr, NULL, 0);
}
ATTR_FORCE_INLINE inline void operator delete[](void *ptr) throw()
{
if (ptr != NULL)
free_file_line(ptr, NULL, 0);
}
// file/line new/delete operators
ATTR_FORCE_INLINE inline void *operator new(std::size_t size, const char *file, int line) throw (std::bad_alloc)
{
void *result = malloc_file_line(size, file, line);
if (result == NULL)
throw std::bad_alloc();
return result;
}
ATTR_FORCE_INLINE inline void *operator new[](std::size_t size, const char *file, int line) throw (std::bad_alloc)
{
void *result = malloc_file_line(size, file, line);
if (result == NULL)
throw std::bad_alloc();
return result;
}
ATTR_FORCE_INLINE inline void operator delete(void *ptr, const char *file, int line)
{
if (ptr != NULL)
free_file_line(ptr, file, line);
}
ATTR_FORCE_INLINE inline void operator delete[](void *ptr, const char *file, int line)
{
if (ptr != NULL)
free_file_line(ptr, file, line);
}
// file/line new/delete operators with zeroing
ATTR_FORCE_INLINE inline void *operator new(std::size_t size, const char *file, int line, const zeromem_t &) throw (std::bad_alloc)
{
void *result = malloc_file_line(size, file, line);
if (result == NULL)
throw std::bad_alloc();
memset(result, 0, size);
return result;
}
ATTR_FORCE_INLINE inline void *operator new[](std::size_t size, const char *file, int line, const zeromem_t &) throw (std::bad_alloc)
{
void *result = malloc_file_line(size, file, line);
if (result == NULL)
throw std::bad_alloc();
memset(result, 0, size);
return result;
}
ATTR_FORCE_INLINE inline void operator delete(void *ptr, const char *file, int line, const zeromem_t &)
{
if (ptr != NULL)
free_file_line(ptr, file, line);
}
ATTR_FORCE_INLINE inline void operator delete[](void *ptr, const char *file, int line, const zeromem_t &)
{
if (ptr != NULL)
free_file_line(ptr, file, line);
}
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// resource_pool_item is a base class for items that are tracked by a resource pool // resource_pool_item is a base class for items that are tracked by a resource pool
class resource_pool_item class resource_pool_item
{ {
@ -184,118 +296,6 @@ extern const zeromem_t zeromem;
//**************************************************************************
// FUNCTION PROTOTYPES
//**************************************************************************
// allocate memory with file and line number information
void *malloc_file_line(size_t size, const char *file, int line);
// free memory with file and line number information
void free_file_line(void *memory, const char *file, int line);
// called from the exit path of any code that wants to check for unfreed memory
void dump_unfreed_mem();
//**************************************************************************
// INLINE FUNCTIONS
//**************************************************************************
// standard new/delete operators (try to avoid using)
ATTR_FORCE_INLINE inline void *operator new(std::size_t size) throw (std::bad_alloc)
{
void *result = malloc_file_line(size, NULL, 0);
if (result == NULL)
throw std::bad_alloc();
return result;
}
ATTR_FORCE_INLINE inline void *operator new[](std::size_t size) throw (std::bad_alloc)
{
void *result = malloc_file_line(size, NULL, 0);
if (result == NULL)
throw std::bad_alloc();
return result;
}
ATTR_FORCE_INLINE inline void operator delete(void *ptr) throw()
{
if (ptr != NULL)
free_file_line(ptr, NULL, 0);
}
ATTR_FORCE_INLINE inline void operator delete[](void *ptr) throw()
{
if (ptr != NULL)
free_file_line(ptr, NULL, 0);
}
// file/line new/delete operators
ATTR_FORCE_INLINE inline void *operator new(std::size_t size, const char *file, int line) throw (std::bad_alloc)
{
void *result = malloc_file_line(size, file, line);
if (result == NULL)
throw std::bad_alloc();
return result;
}
ATTR_FORCE_INLINE inline void *operator new[](std::size_t size, const char *file, int line) throw (std::bad_alloc)
{
void *result = malloc_file_line(size, file, line);
if (result == NULL)
throw std::bad_alloc();
return result;
}
ATTR_FORCE_INLINE inline void operator delete(void *ptr, const char *file, int line)
{
if (ptr != NULL)
free_file_line(ptr, file, line);
}
ATTR_FORCE_INLINE inline void operator delete[](void *ptr, const char *file, int line)
{
if (ptr != NULL)
free_file_line(ptr, file, line);
}
// file/line new/delete operators with zeroing
ATTR_FORCE_INLINE inline void *operator new(std::size_t size, const char *file, int line, const zeromem_t &) throw (std::bad_alloc)
{
void *result = malloc_file_line(size, file, line);
if (result == NULL)
throw std::bad_alloc();
memset(result, 0, size);
return result;
}
ATTR_FORCE_INLINE inline void *operator new[](std::size_t size, const char *file, int line, const zeromem_t &) throw (std::bad_alloc)
{
void *result = malloc_file_line(size, file, line);
if (result == NULL)
throw std::bad_alloc();
memset(result, 0, size);
return result;
}
ATTR_FORCE_INLINE inline void operator delete(void *ptr, const char *file, int line, const zeromem_t &)
{
if (ptr != NULL)
free_file_line(ptr, file, line);
}
ATTR_FORCE_INLINE inline void operator delete[](void *ptr, const char *file, int line, const zeromem_t &)
{
if (ptr != NULL)
free_file_line(ptr, file, line);
}
//************************************************************************** //**************************************************************************
// ADDDITIONAL MACROS // ADDDITIONAL MACROS
//************************************************************************** //**************************************************************************