diff --git a/src/memuse.c b/src/memuse.c index 10fd349c0cc4de26b94878b45fd78da19e140f12..39f55ec914ff61c49f5c12ce2b8699f0525540a8 100644 --- a/src/memuse.c +++ b/src/memuse.c @@ -33,6 +33,7 @@ #include <unistd.h> /* Local defines. */ +#include "c_hashmap/hashmap.h" #include "memuse.h" /* Local includes. */ @@ -70,6 +71,9 @@ struct memuse_log_entry { /* Label associated with the memory. */ char label[MEMUSE_MAXLAB + 1]; + + /* Key for hashmap. Formatted address of memory. */ + char key[MEMUSE_MAXLAB + 1]; }; /* The log of allocations and frees. */ @@ -78,6 +82,12 @@ static volatile size_t memuse_log_size = 0; static volatile size_t memuse_log_count = 0; static volatile size_t memuse_log_done = 0; +/* Hashmap for matching frees to allocations. */ +static map_t memuse_hashmap; + +/* Current sum of memory in use. Only used in dumping. */ +static size_t memuse_sum = 0; + #define MEMUSE_INITLOG 1000000 static void memuse_log_reallocate(size_t ind) { @@ -88,6 +98,9 @@ static void memuse_log_reallocate(size_t ind) { sizeof(struct memuse_log_entry) * MEMUSE_INITLOG)) == NULL) error("Failed to allocate memuse log."); + /* Create the hashmap. */ + memuse_hashmap = hashmap_new(); + /* Last action. */ memuse_log_size = MEMUSE_INITLOG; @@ -162,15 +175,61 @@ void memuse_log_dump(const char *filename) { /* Write a header. */ fprintf(fd, "# Current use: %s\n", memuse_process(1)); fprintf(fd, "# cpufreq: %lld\n", clocks_get_cpufreq()); - fprintf(fd, "# dtic adr rank step allocated label size\n"); + fprintf(fd, "# dtic rank step label size sum\n"); for (size_t k = 0; k < memuse_log_count; k++) { - fprintf(fd, "%lld %p %d %d %d %s %zd\n", memuse_log[k].dtic, - memuse_log[k].ptr, memuse_log[k].rank, memuse_log[k].step, - memuse_log[k].allocated, memuse_log[k].label, memuse_log[k].size); + + /* Check if this address has already been used. */ + struct memuse_log_entry *stored_log; + sprintf(memuse_log[k].key, "%p", memuse_log[k].ptr); + + int error = hashmap_get(memuse_hashmap, memuse_log[k].key, + (void **)(&stored_log)); + if (error == MAP_OK) { + + /* Found the allocation, this should be the free. */ + if (memuse_log[k].allocated) { + + /* Allocated twice, this is an error, but we cannot abort as that will + * attempt another memory dump, so just complain. */ +#if SWIFT_DEBUG_CHECKS + message("Allocated the same address twice (%s: %zd)\n", + memuse_log[k].key, memuse_log[k].size); +#endif + continue; + } + + /* Free, so we can update the size to remove the allocation. */ + memuse_log[k].size = -stored_log->size; + + /* And remove this key. */ + hashmap_remove(memuse_hashmap, memuse_log[k].key); + + } else if (memuse_log[k].allocated) { + + /* Not found, so new allocation which we store. */ + hashmap_put(memuse_hashmap, memuse_log[k].key, &memuse_log[k]); + + } else if (!memuse_log[k].allocated) { + + /* Unmatched free, OK if NULL. */ +#if SWIFT_DEBUG_CHECKS + if (memuse_log[k].ptr != NULL) + fprintf(stderr, "Unmatched non-NULL free: %s\n", memuse_log[k].label); +#endif + continue; + } + + memuse_sum += memuse_log[k].size; + + /* And output. */ + fprintf(fd, "%lld %d %d %s %zd %zd\n", memuse_log[k].dtic, + memuse_log[k].rank, memuse_log[k].step, memuse_log[k].label, + memuse_log[k].size, memuse_sum); } - /* Clear the log. */ + /* Clear the log. OK as records are dumped, but note active memory is still + * in the hashmap. */ memuse_log_count = 0; /* Close the file. */