diff options
author | Ashlee Young <ashlee@onosfw.com> | 2015-09-09 22:21:41 -0700 |
---|---|---|
committer | Ashlee Young <ashlee@onosfw.com> | 2015-09-09 22:21:41 -0700 |
commit | 8879b125d26e8db1a5633de5a9c692eb2d1c4f83 (patch) | |
tree | c7259d85a991b83dfa85ab2e339360669fc1f58e /framework/src/suricata/src/util-profiling-locks.c | |
parent | 13d05bc8458758ee39cb829098241e89616717ee (diff) |
suricata checkin based on commit id a4bce14770beee46a537eda3c3f6e8e8565d5d0a
Change-Id: I9a214fa0ee95e58fc640e50bd604dac7f42db48f
Diffstat (limited to 'framework/src/suricata/src/util-profiling-locks.c')
-rw-r--r-- | framework/src/suricata/src/util-profiling-locks.c | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/framework/src/suricata/src/util-profiling-locks.c b/framework/src/suricata/src/util-profiling-locks.c new file mode 100644 index 00000000..97cc3e0d --- /dev/null +++ b/framework/src/suricata/src/util-profiling-locks.c @@ -0,0 +1,241 @@ +/* Copyright (C) 2007-2012 Open Information Security Foundation + * + * You can copy, redistribute or modify this Program under the terms of + * the GNU General Public License version 2 as published by the Free + * Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * version 2 along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +/** + * \file + * + * \author Victor Julien <victor@inliniac.net> + * + * An API for profiling locks. + * + */ + +#ifdef PROFILING +#ifdef PROFILE_LOCKING + +#include "suricata-common.h" +#include "util-profiling-locks.h" +#include "util-hashlist.h" + +__thread ProfilingLock locks[PROFILING_MAX_LOCKS]; +__thread int locks_idx = 0; +__thread int record_locks = 0; + +int profiling_locks_enabled = 0; +int profiling_locks_output_to_file = 0; +char *profiling_locks_file_name = NULL; +char *profiling_locks_file_mode = "a"; + +typedef struct LockRecord_ { + char *file; // hash + + char *func; // info + int type; // info + + int line; // hash + + uint32_t cont; + uint32_t ticks_cnt; + uint64_t ticks_total; + uint64_t ticks_max; +} LockRecord; + +HashListTable *lock_records; +pthread_mutex_t lock_records_mutex; + +static uint32_t LockRecordHash(HashListTable *ht, void *buf, uint16_t buflen) +{ + LockRecord *fn = (LockRecord *)buf; + uint32_t hash = strlen(fn->file) + fn->line; + uint16_t u; + + for (u = 0; u < strlen(fn->file); u++) { + hash += fn->file[u]; + } + + return hash % ht->array_size; +} + +static char LockRecordCompare(void *buf1, uint16_t len1, void *buf2, uint16_t len2) +{ + LockRecord *fn1 = (LockRecord *)buf1; + LockRecord *fn2 = (LockRecord *)buf2; + + if (fn1->line != fn2->line) + return 0; + + if (fn1->file == fn2->file) + return 1; + + return 0; +} + +static void LockRecordFree(void *data) +{ + LockRecord *fn = (LockRecord *)data; + + if (fn == NULL) + return; + SCFree(fn); +} + +int LockRecordInitHash() +{ + pthread_mutex_init(&lock_records_mutex, NULL); + pthread_mutex_lock(&lock_records_mutex); + + lock_records = HashListTableInit(512, LockRecordHash, LockRecordCompare, LockRecordFree); + BUG_ON(lock_records == NULL); + + pthread_mutex_unlock(&lock_records_mutex); + + return 0; +} + +void LockRecordAdd(ProfilingLock *l) +{ + LockRecord fn = { NULL, NULL, 0,0,0,0,0,0}, *ptr = &fn; + fn.file = l->file; + fn.line = l->line; + + LockRecord *lookup_fn = (LockRecord *)HashListTableLookup(lock_records, (void *)ptr, 0); + if (lookup_fn == NULL) { + LockRecord *new = SCMalloc(sizeof(LockRecord)); + BUG_ON(new == NULL); + + new->file = l->file; + new->line = l->line; + new->type = l->type; + new->cont = l->cont; + new->func = l->func; + new->ticks_max = l->ticks; + new->ticks_total = l->ticks; + new->ticks_cnt = 1; + + HashListTableAdd(lock_records, (void *)new, 0); + } else { + lookup_fn->ticks_total += l->ticks; + if (l->ticks > lookup_fn->ticks_max) + lookup_fn->ticks_max = l->ticks; + lookup_fn->ticks_cnt++; + lookup_fn->cont += l->cont; + } + + return; +} + +/** \param p void ptr to Packet struct */ +void SCProfilingAddPacketLocks(void *p) +{ + int i; + + if (profiling_locks_enabled == 0) + return; + + for (i = 0; i < locks_idx; i++) { + pthread_mutex_lock(&lock_records_mutex); + LockRecordAdd(&locks[i]); + pthread_mutex_unlock(&lock_records_mutex); + } +} + +void SCProfilingListLocks(void) +{ + FILE *fp = NULL; + + if (profiling_locks_output_to_file == 1) { + fp = fopen(profiling_locks_file_name, profiling_locks_file_mode); + + if (fp == NULL) { + SCLogError(SC_ERR_FOPEN, "failed to open %s: %s", + profiling_locks_file_name, strerror(errno)); + return; + } + } else { + fp = stdout; + } + + fprintf(fp, "\n\nLock Cnt Avg ticks Max ticks Total ticks Cont Func\n"); + fprintf(fp, "------------------ ---------- --------- ------------ ------------ ------- ---------\n"); + + uint64_t total = 0; + uint32_t cont = 0; + uint64_t cnt = 0; + + HashListTableBucket *b = HashListTableGetListHead(lock_records); + while (b) { + LockRecord *r = HashListTableGetListData(b); + + char *lock; + switch (r->type) { + case LOCK_MUTEX: + lock = "mtx"; + break; + case LOCK_SPIN: + lock = "spn"; + break; + case LOCK_RWW: + lock = "rww"; + break; + case LOCK_RWR: + lock = "rwr"; + break; + default: + lock = "bug"; + break; + } + + char str[128] = ""; + snprintf(str, sizeof(str), "(%s) %s:%d", lock,r->file, r->line); + + fprintf(fp, "%-50s %-10u %-9"PRIu64" %-12"PRIu64" %-12"PRIu64" %-7u %-s\n", + str, r->ticks_cnt, (uint64_t)((uint64_t)r->ticks_total/(uint64_t)r->ticks_cnt), r->ticks_max, r->ticks_total, r->cont, r->func); + + total += r->ticks_total; + cnt += r->ticks_cnt; + cont += r->cont; + + b = HashListTableGetListNext(b); + } + + fprintf(fp, "\nOverall: locks %"PRIu64", average cost %"PRIu64", contentions %"PRIu32", total ticks %"PRIu64"\n", + cnt, (uint64_t)((uint64_t)total/(uint64_t)cnt), cont, total); + + fclose(fp); +} + +void LockRecordFreeHash() +{ + if (profiling_locks_enabled == 0) + return; + + pthread_mutex_lock(&lock_records_mutex); + + SCProfilingListLocks(); + + if (lock_records != NULL) { + HashListTableFree(lock_records); + lock_records = NULL; + } + pthread_mutex_unlock(&lock_records_mutex); + + pthread_mutex_destroy(&lock_records_mutex); +} + +#endif +#endif + |