Added a leak detective method to report current memory usage with backtraces

This commit is contained in:
Martin Willi 2011-04-29 14:53:24 +02:00
parent f37e8252a3
commit fce3b5c3ba
2 changed files with 101 additions and 0 deletions

View File

@ -34,6 +34,7 @@
#include <library.h>
#include <debug.h>
#include <utils/backtrace.h>
#include <utils/hashtable.h>
typedef struct private_leak_detective_t private_leak_detective_t;
@ -310,6 +311,98 @@ static void uninstall_hooks()
}
}
/**
* Hashtable hash function
*/
static u_int hash(backtrace_t *key)
{
enumerator_t *enumerator;
void *addr;
u_int hash = 0;
enumerator = key->create_frame_enumerator(key);
while (enumerator->enumerate(enumerator, &addr))
{
hash = chunk_hash_inc(chunk_from_thing(addr), hash);
}
enumerator->destroy(enumerator);
return hash;
}
/**
* Hashtable equals function
*/
static bool equals(backtrace_t *a, backtrace_t *b)
{
return a->equals(a, b);
}
METHOD(leak_detective_t, usage, void,
private_leak_detective_t *this, FILE *out)
{
int oldpolicy, thresh;
pthread_t thread_id = pthread_self();
struct sched_param oldparams, params;
memory_header_t *hdr;
enumerator_t *enumerator;
hashtable_t *entries;
struct {
/** associated backtrace */
backtrace_t *backtrace;
/** total size of all allocations */
size_t bytes;
/** number of allocations */
u_int count;
} *entry;
thresh = lib->settings->get_int(lib->settings,
"libstrongswan.leak_detective.usage_threshold", 10240);
pthread_getschedparam(thread_id, &oldpolicy, &oldparams);
params.__sched_priority = sched_get_priority_max(SCHED_FIFO);
pthread_setschedparam(thread_id, SCHED_FIFO, &params);
uninstall_hooks();
entries = hashtable_create((hashtable_hash_t)hash,
(hashtable_equals_t)equals, 1024);
for (hdr = first_header.next; hdr != NULL; hdr = hdr->next)
{
entry = entries->get(entries, hdr->backtrace);
if (entry)
{
entry->bytes += hdr->bytes;
entry->count++;
}
else
{
INIT(entry,
.backtrace = hdr->backtrace,
.bytes = hdr->bytes,
.count = 1,
);
entries->put(entries, hdr->backtrace, entry);
}
}
enumerator = entries->create_enumerator(entries);
while (enumerator->enumerate(enumerator, NULL, &entry))
{
if (entry->bytes >= thresh)
{
fprintf(out, "%d bytes total, %d allocations, %d bytes average:\n",
entry->bytes, entry->count, entry->bytes / entry->count);
entry->backtrace->log(entry->backtrace, out, TRUE);
}
free(entry);
}
enumerator->destroy(enumerator);
entries->destroy(entries);
install_hooks();
pthread_setschedparam(thread_id, oldpolicy, &oldparams);
}
/**
* Hook function for malloc()
*/
@ -510,6 +603,7 @@ leak_detective_t *leak_detective_create()
INIT(this,
.public = {
.report = _report,
.usage = _usage,
.destroy = _destroy,
},
);

View File

@ -42,6 +42,13 @@ struct leak_detective_t {
*/
void (*report)(leak_detective_t *this, bool detailed);
/**
* Report current memory usage to out.
*
* @param out target to write usage report to
*/
void (*usage)(leak_detective_t *this, FILE *out);
/**
* Destroy a leak_detective instance.
*/