diff options
author | Martin Willi <martin@revosec.ch> | 2011-04-29 14:53:24 +0200 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2011-05-16 15:22:21 +0200 |
commit | fce3b5c3ba366f2a39ed22dab11f44497d10dedb (patch) | |
tree | 6b91919b119e694507330ad5aad5d6370cec6f60 | |
parent | f37e8252a358e33e3a11701c99e5e63d20ce784f (diff) | |
download | strongswan-fce3b5c3ba366f2a39ed22dab11f44497d10dedb.tar.bz2 strongswan-fce3b5c3ba366f2a39ed22dab11f44497d10dedb.tar.xz |
Added a leak detective method to report current memory usage with backtraces
-rw-r--r-- | src/libstrongswan/utils/leak_detective.c | 94 | ||||
-rw-r--r-- | src/libstrongswan/utils/leak_detective.h | 7 |
2 files changed, 101 insertions, 0 deletions
diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c index e770e1224..b1b58ccba 100644 --- a/src/libstrongswan/utils/leak_detective.c +++ b/src/libstrongswan/utils/leak_detective.c @@ -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; @@ -311,6 +312,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, ¶ms); + 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() */ void *malloc_hook(size_t bytes, const void *caller) @@ -510,6 +603,7 @@ leak_detective_t *leak_detective_create() INIT(this, .public = { .report = _report, + .usage = _usage, .destroy = _destroy, }, ); diff --git a/src/libstrongswan/utils/leak_detective.h b/src/libstrongswan/utils/leak_detective.h index fa45a6076..8c80d2532 100644 --- a/src/libstrongswan/utils/leak_detective.h +++ b/src/libstrongswan/utils/leak_detective.h @@ -43,6 +43,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. */ void (*destroy)(leak_detective_t *this); |