X-Git-Url: https://git.xonotic.org/?p=xonotic%2Fgmqcc.git;a=blobdiff_plain;f=util.c;h=92f8e5e4405c0698d29171826826bf07910fe7ee;hp=0ac4df3993de087c3568f664163d963328332898;hb=f2b21158d801e96b5f8d7c9491186267dc75a4dc;hpb=d201cfe6b49f95ba8bcaa0eebb3a6fb7e1a16913 diff --git a/util.c b/util.c index 0ac4df3..92f8e5e 100644 --- a/util.c +++ b/util.c @@ -30,6 +30,8 @@ uint64_t mem_ab = 0; uint64_t mem_db = 0; uint64_t mem_at = 0; uint64_t mem_dt = 0; +uint64_t mem_pk = 0; +uint64_t mem_hw = 0; struct memblock_t { const char *file; @@ -39,6 +41,12 @@ struct memblock_t { struct memblock_t *prev; }; +#define PEAK_MEM \ + do { \ + if (mem_hw > mem_pk) \ + mem_pk = mem_hw; \ + } while (0) + static struct memblock_t *mem_start = NULL; void *util_memory_a(size_t byte, unsigned int line, const char *file) { @@ -56,6 +64,9 @@ void *util_memory_a(size_t byte, unsigned int line, const char *file) { mem_at++; mem_ab += info->byte; + mem_hw += info->byte; + + PEAK_MEM; return data; } @@ -67,6 +78,7 @@ void util_memory_d(void *ptrn) { info = ((struct memblock_t*)ptrn - 1); mem_db += info->byte; + mem_hw -= info->byte; mem_dt++; if (info->prev) @@ -122,51 +134,92 @@ void *util_memory_r(void *ptrn, size_t byte, unsigned int line, const char *file mem_start = newinfo; mem_ab -= oldinfo->byte; + mem_hw -= oldinfo->byte; mem_ab += newinfo->byte; + mem_hw += newinfo->byte; + + PEAK_MEM; free(oldinfo); return newinfo+1; } +static void util_dumpmem(struct memblock_t *memory, uint16_t cols) { + uint32_t i, j; + for (i = 0; i < memory->byte + ((memory->byte % cols) ? (cols - memory->byte % cols) : 0); i++) { + if (i % cols == 0) con_out(" 0x%06X: ", i); + if (i < memory->byte) con_out("%02X " , 0xFF & ((char*)(memory + 1))[i]); + else con_out(" "); + + if ((uint16_t)(i % cols) == (cols - 1)) { + for (j = i - (cols - 1); j <= i; j++) { + con_out("%c", + (j >= memory->byte) + ? ' ' + : (isprint(((char*)(memory + 1))[j])) + ? 0xFF & ((char*)(memory + 1)) [j] + : '.' + ); + } + con_out("\n"); + } + } +} + void util_meminfo() { struct memblock_t *info; - if (!OPTION_VALUE_BOOL(OPTION_MEMCHK)) - return; - for (info = mem_start; info; info = info->next) { - util_debug("MEM", "lost: % 8u (bytes) at %s:%u\n", - info->byte, - info->file, - info->line); + if (OPTS_OPTION_BOOL(OPTION_DEBUG)) { + for (info = mem_start; info; info = info->next) { + con_out("lost: %u (bytes) at %s:%u\n", + info->byte, + info->file, + info->line); + + util_dumpmem(info, OPTS_OPTION_U16(OPTION_MEMDUMPCOLS)); + } } - util_debug("MEM", "Memory information:\n\ - Total allocations: %llu\n\ - Total deallocations: %llu\n\ - Total allocated: %llu (bytes)\n\ - Total deallocated: %llu (bytes)\n\ - Leaks found: lost %llu (bytes) in %d allocations\n", - mem_at, mem_dt, - mem_ab, mem_db, - (mem_ab - mem_db), - (mem_at - mem_dt) - ); + if (OPTS_OPTION_BOOL(OPTION_DEBUG) || + OPTS_OPTION_BOOL(OPTION_MEMCHK)) { + con_out("Memory information:\n\ + Total allocations: %llu\n\ + Total deallocations: %llu\n\ + Total allocated: %f (MB)\n\ + Total deallocated: %f (MB)\n\ + Total peak memory: %f (MB)\n\ + Total leaked memory: %f (MB) in %llu allocations\n", + mem_at, + (float)(mem_dt) / 1048576.0f, + mem_ab, + (float)(mem_db) / 1048576.0f, + (float)(mem_pk) / 1048576.0f, + (float)(mem_ab - mem_db) / 1048576.0f, + + /* could be more clever */ + (mem_at - mem_dt) + ); + } } /* * Some string utility functions, because strdup uses malloc, and we want * to track all memory (without replacing malloc). */ -char *util_strdup(const char *s) { +char *_util_Estrdup(const char *s, const char *file, size_t line) { size_t len = 0; char *ptr = NULL; + /* in case of -DNOTRACK */ + (void)file; + (void)line; + if (!s) return NULL; - if ((len = strlen(s)) && (ptr = (char*)mem_a(len+1))) { + if ((len = strlen(s)) && (ptr = (char*)mem_af(len+1, line, file))) { memcpy(ptr, s, len); ptr[len] = '\0'; } @@ -175,10 +228,10 @@ char *util_strdup(const char *s) { void util_debug(const char *area, const char *ms, ...) { va_list va; - if (!OPTION_VALUE_BOOL(OPTION_DEBUG)) + if (!OPTS_OPTION_BOOL(OPTION_DEBUG)) return; - if (!strcmp(area, "MEM") && !OPTION_VALUE_BOOL(OPTION_MEMCHK)) + if (!strcmp(area, "MEM") && !OPTS_OPTION_BOOL(OPTION_MEMCHK)) return; va_start(va, ms); @@ -253,7 +306,7 @@ void util_endianswap(void *_data, size_t length, unsigned int typesize) { util_swap64((uint32_t*)_data, length>>3); return; - default: abort(); /* please blow the fuck up! */ + default: exit(EXIT_FAILURE); /* please blow the fuck up! */ } # endif #endif @@ -616,7 +669,7 @@ static void util_hsupdate(hash_set_t *set) { set->bits ++; set->capacity = (size_t)(1 << set->bits); set->mask = set->capacity - 1; - set->items = mem_a(set->capacity * sizeof(size_t)); + set->items = (size_t*)mem_a(set->capacity * sizeof(size_t)); set->total = 0; /*assert(set->items);*/ @@ -680,14 +733,14 @@ int util_hshas(hash_set_t *set, void *item) { hash_set_t *util_hsnew(void) { hash_set_t *set; - if (!(set = mem_a(sizeof(hash_set_t)))) + if (!(set = (hash_set_t*)mem_a(sizeof(hash_set_t)))) return NULL; set->bits = 3; set->total = 0; set->capacity = (size_t)(1 << set->bits); set->mask = set->capacity - 1; - set->items = mem_a(set->capacity * sizeof(size_t)); + set->items = (size_t*)mem_a(set->capacity * sizeof(size_t)); if (!set->items) { util_hsdel(set); @@ -760,7 +813,7 @@ int util_vasprintf(char **dat, const char *fmt, va_list args) { } /* not large enough ... */ - tmp = mem_a(len + 1); + tmp = (char*)mem_a(len + 1); if ((ret = vsnprintf(tmp, len + 1, fmt, args)) != len) { mem_d(tmp); *dat = NULL;