summaryrefslogtreecommitdiff
path: root/src/common/malloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/malloc.c')
-rw-r--r--src/common/malloc.c152
1 files changed, 117 insertions, 35 deletions
diff --git a/src/common/malloc.c b/src/common/malloc.c
index 4874aa0f4..d629aa63f 100644
--- a/src/common/malloc.c
+++ b/src/common/malloc.c
@@ -200,6 +200,8 @@ static struct unit_head_large *unit_head_large_first = NULL;
static struct block* block_malloc(unsigned short hash);
static void block_free(struct block* p);
static size_t memmgr_usage_bytes;
+static size_t memmgr_usage_bytes_t;
+
#define block2unit(p, n) ((struct unit_head*)(&(p)->data[ p->unit_size * (n) ]))
#define memmgr_assert(v) do { if(!(v)) { ShowError("Memory manager: assertion '" #v "' failed!\n"); } } while(0)
@@ -245,12 +247,13 @@ void* _mmalloc(size_t size, const char *file, int line, const char *func )
/* At that time, the distinction by assigning NULL to unit_head.block */
if(hash2size(size_hash) > BLOCK_DATA_SIZE - sizeof(struct unit_head)) {
struct unit_head_large* p = (struct unit_head_large*)MALLOC(sizeof(struct unit_head_large)+size,file,line,func);
+ memmgr_usage_bytes_t += size+sizeof(struct unit_head_large);
if(p != NULL) {
p->size = size;
p->unit_head.block = NULL;
p->unit_head.size = 0;
p->unit_head.file = file;
- p->unit_head.line = line;
+ p->unit_head.line = (unsigned short)line;
p->prev = NULL;
if (unit_head_large_first == NULL)
p->next = NULL;
@@ -324,7 +327,7 @@ void* _mmalloc(size_t size, const char *file, int line, const char *func )
head->block = block;
head->file = file;
- head->line = line;
+ head->line = (unsigned short)line;
head->size = (unsigned short)size;
*(long*)((char*)head + sizeof(struct unit_head) - sizeof(long) + size) = 0xdeadbeaf;
return (char *)head + sizeof(struct unit_head) - sizeof(long);
@@ -332,7 +335,7 @@ void* _mmalloc(size_t size, const char *file, int line, const char *func )
void* _mcalloc(size_t num, size_t size, const char *file, int line, const char *func )
{
- void *p = malloclib->malloc(num * size,file,line,func);
+ void *p = iMalloc->malloc(num * size,file,line,func);
memset(p,0,num * size);
return p;
}
@@ -341,7 +344,7 @@ void* _mrealloc(void *memblock, size_t size, const char *file, int line, const c
{
size_t old_size;
if(memblock == NULL) {
- return malloclib->malloc(size,file,line,func);
+ return iMalloc->malloc(size,file,line,func);
}
old_size = ((struct unit_head *)((char *)memblock - sizeof(struct unit_head) + sizeof(long)))->size;
@@ -353,11 +356,11 @@ void* _mrealloc(void *memblock, size_t size, const char *file, int line, const c
return memblock;
} else {
// Size Large
- void *p = malloclib->malloc(size,file,line,func);
+ void *p = iMalloc->malloc(size,file,line,func);
if(p != NULL) {
memcpy(p,memblock,old_size);
}
- malloclib->free(memblock,file,line,func);
+ iMalloc->free(memblock,file,line,func);
return p;
}
}
@@ -368,7 +371,7 @@ char* _mstrdup(const char *p, const char *file, int line, const char *func )
return NULL;
} else {
size_t len = strlen(p);
- char *string = (char *)malloclib->malloc(len + 1,file,line,func);
+ char *string = (char *)iMalloc->malloc(len + 1,file,line,func);
memcpy(string,p,len+1);
return string;
}
@@ -401,6 +404,7 @@ void _mfree(void *ptr, const char *file, int line, const char *func )
head_large->next->prev = head_large->prev;
}
memmgr_usage_bytes -= head_large->size;
+ memmgr_usage_bytes_t -= head_large->size + sizeof(struct unit_head_large);
#ifdef DEBUG_MEMMGR
// set freed memory to 0xfd
memset(ptr, 0xfd, head_large->size);
@@ -422,7 +426,7 @@ void _mfree(void *ptr, const char *file, int line, const char *func )
#ifdef DEBUG_MEMMGR
memset(ptr, 0xfd, block->unit_size - sizeof(struct unit_head) + sizeof(long) );
head->file = file;
- head->line = line;
+ head->line = (unsigned short)line;
#endif
memmgr_assert( block->unit_used > 0 );
if(--block->unit_used == 0) {
@@ -457,6 +461,7 @@ static struct block* block_malloc(unsigned short hash)
} else {
/* Newly allocated space for the block */
p = (struct block*)MALLOC(sizeof(struct block) * (BLOCK_ALLOC), __FILE__, __LINE__, __func__ );
+ memmgr_usage_bytes_t += sizeof(struct block) * (BLOCK_ALLOC);
if(p == NULL) {
ShowFatalError("Memory manager::block_alloc failed.\n");
exit(EXIT_FAILURE);
@@ -621,7 +626,7 @@ static void memmgr_final (void)
memmgr_log (buf);
#endif /* LOG_MEMMGR */
// get block pointer and free it [celest]
- malloclib->free(ptr, ALC_MARK);
+ iMalloc->free(ptr, ALC_MARK);
}
}
}
@@ -650,6 +655,86 @@ static void memmgr_final (void)
}
#endif /* LOG_MEMMGR */
}
+/* [Ind/Hercules] */
+void memmgr_report (int extra) {
+ struct block *block = block_first;
+ struct unit_head_large *large = unit_head_large_first;
+ unsigned int count = 0, size = 0;
+ int j;
+ unsigned short msize = 1024;
+ struct {
+ const char *file;
+ unsigned short line;
+ unsigned int size;
+ unsigned int count;
+ } data[100];
+ memset(&data, 0, sizeof(data));
+
+ if( extra != 0 )
+ msize = extra;
+
+ while (block) {
+ if (block->unit_used) {
+ int i;
+ for (i = 0; i < block->unit_maxused; i++) {
+ struct unit_head *head = block2unit(block, i);
+ if( head->block != NULL && head->size > msize ) {
+ for( j = 0; j < 100; j++ ) {
+ if( data[j].file == head->file && data[j].line == head->line ) {
+ data[j].size += head->size;
+ data[j].count += 1;
+ break;
+ } else if( data[j].size == 0 ) {
+ data[j].file = head->file;
+ data[j].line = head->line;
+ data[j].size = head->size;
+ data[j].count += 1;
+ break;
+ }
+ }
+ size += (unsigned int)head->size;
+ count++;
+ }
+ }
+ }
+ block = block->block_next;
+ }
+
+ while(large) {
+ if( large->size > msize ) {
+ for( j = 0; j < 100; j++ ) {
+ if( data[j].file == large->unit_head.file && data[j].line == large->unit_head.line ) {
+ data[j].size += large->size;
+ data[j].count += 1;
+ break;
+ } else if( data[j].size == 0 ) {
+ data[j].file = large->unit_head.file;
+ data[j].line = large->unit_head.line;
+ data[j].size = large->size;
+ data[j].count += 1;
+ break;
+ }
+ }
+ size += (unsigned int)large->size;
+ count++;
+ }
+ large = large->next;
+ }
+ for( j = 0; j < 100; j++ ) {
+ if( data[j].size != 0 ) {
+ ShowMessage("[malloc] : "CL_WHITE"%s"CL_RESET":"CL_WHITE"%d"CL_RESET" %d instances => %.2f MB\n",data[j].file,data[j].line,data[j].count,(double)((data[j].size)/1024)/1024);
+ }
+ }
+ ShowMessage("[malloc] : reporting %u instances | %.2f MB\n",count,(double)((size)/1024)/1024);
+ ShowMessage("[malloc] : internal usage %.2f MB | %.2f MB\n",(double)((memmgr_usage_bytes_t-memmgr_usage_bytes)/1024)/1024,(double)((memmgr_usage_bytes_t)/1024)/1024);
+
+ if( extra ) {
+ ShowMessage("[malloc] : unit_head_large: %d bytes\n",sizeof(struct unit_head_large));
+ ShowMessage("[malloc] : unit_head: %d bytes\n",sizeof(struct unit_head));
+ ShowMessage("[malloc] : block: %d bytes\n",sizeof(struct block));
+ }
+
+}
static void memmgr_init (void)
{
@@ -677,8 +762,7 @@ void malloc_memory_check(void)
/// Returns true if a pointer is valid.
/// The check is best-effort, false positives are possible.
-bool malloc_verify_ptr(void* ptr)
-{
+bool malloc_verify_ptr(void* ptr) {
#ifdef USE_MEMMGR
return memmgr_verify(ptr) && MEMORY_VERIFY(ptr);
#else
@@ -687,8 +771,7 @@ bool malloc_verify_ptr(void* ptr)
}
-size_t malloc_usage (void)
-{
+size_t malloc_usage (void) {
#ifdef USE_MEMMGR
return memmgr_usage ();
#else
@@ -696,16 +779,16 @@ size_t malloc_usage (void)
#endif
}
-void malloc_final (void)
-{
+void malloc_final (void) {
#ifdef USE_MEMMGR
memmgr_final ();
#endif
MEMORY_CHECK();
}
-void malloc_init (void)
-{
+void malloc_init (void) {
+ memmgr_usage_bytes_t = 0;
+ memmgr_usage_bytes = 0;
#if defined(DMALLOC) && defined(CYGWIN)
// http://dmalloc.com/docs/latest/online/dmalloc_19.html
dmalloc_debug_setup(getenv("DMALLOC_OPTIONS"));
@@ -720,27 +803,26 @@ void malloc_init (void)
#endif
}
-void malloc_defaults()
-{
- malloclib = &malloclib_s;
- malloclib->init = malloc_init;
- malloclib->final = malloc_final;
- malloclib->memory_check = malloc_memory_check;
- malloclib->usage = malloc_usage;
- malloclib->verify_ptr = malloc_verify_ptr;
+void malloc_defaults(void) {
+ iMalloc = &iMalloc_s;
+ iMalloc->init = malloc_init;
+ iMalloc->final = malloc_final;
+ iMalloc->memory_check = malloc_memory_check;
+ iMalloc->usage = malloc_usage;
+ iMalloc->verify_ptr = malloc_verify_ptr;
// Athena's built-in Memory Manager
#ifdef USE_MEMMGR
- malloclib->malloc = _mmalloc;
- malloclib->calloc = _mcalloc;
- malloclib->realloc = _mrealloc;
- malloclib->astrdup = _mstrdup;
- malloclib->free = _mfree;
+ iMalloc->malloc = _mmalloc;
+ iMalloc->calloc = _mcalloc;
+ iMalloc->realloc = _mrealloc;
+ iMalloc->astrdup = _mstrdup;
+ iMalloc->free = _mfree;
#else
- malloclib->malloc = aMalloc_;
- malloclib->calloc = aCalloc_;
- malloclib->realloc = aRealloc_;
- malloclib->astrdup = aStrdup_;
- malloclib->free = aFree_;
+ iMalloc->malloc = aMalloc_;
+ iMalloc->calloc = aCalloc_;
+ iMalloc->realloc = aRealloc_;
+ iMalloc->astrdup = aStrdup_;
+ iMalloc->free = aFree_;
#endif
}