aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/suricata/src/util-profiling-locks.c
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/suricata/src/util-profiling-locks.c')
-rw-r--r--framework/src/suricata/src/util-profiling-locks.c241
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
+