suricata
util-profiling-locks.c
Go to the documentation of this file.
1/* Copyright (C) 2007-2012 Open Information Security Foundation
2 *
3 * You can copy, redistribute or modify this Program under the terms of
4 * the GNU General Public License version 2 as published by the Free
5 * Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * version 2 along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15 * 02110-1301, USA.
16 */
17
18/**
19 * \file
20 *
21 * \author Victor Julien <victor@inliniac.net>
22 *
23 * An API for profiling locks.
24 *
25 */
26
27#include "suricata-common.h"
29
30#ifdef PROFILING
31#ifdef PROFILE_LOCKING
32#include "threads.h"
33#include "util-hashlist.h"
34#include "util-debug.h"
35
37thread_local int locks_idx = 0;
38thread_local int record_locks = 0;
39
42char *profiling_locks_file_name = NULL;
43const char *profiling_locks_file_mode = "a";
44
45typedef struct LockRecord_ {
46 char *file; // hash
47
48 char *func; // info
49 int type; // info
50
51 int line; // hash
52
53 uint32_t cont;
54 uint32_t ticks_cnt;
55 uint64_t ticks_total;
56 uint64_t ticks_max;
57} LockRecord;
58
59HashListTable *lock_records;
60pthread_mutex_t lock_records_mutex;
61
62static uint32_t LockRecordHash(HashListTable *ht, void *buf, uint16_t buflen)
63{
64 LockRecord *fn = (LockRecord *)buf;
65 uint32_t hash = strlen(fn->file) + fn->line;
66 uint16_t u;
67
68 for (u = 0; u < strlen(fn->file); u++) {
69 hash += fn->file[u];
70 }
71
72 return hash % ht->array_size;
73}
74
75static char LockRecordCompare(void *buf1, uint16_t len1, void *buf2, uint16_t len2)
76{
77 LockRecord *fn1 = (LockRecord *)buf1;
78 LockRecord *fn2 = (LockRecord *)buf2;
79
80 if (fn1->line != fn2->line)
81 return 0;
82
83 if (fn1->file == fn2->file)
84 return 1;
85
86 return 0;
87}
88
89static void LockRecordFree(void *data)
90{
91 LockRecord *fn = (LockRecord *)data;
92
93 if (fn == NULL)
94 return;
95 SCFree(fn);
96}
97
98int LockRecordInitHash(void)
99{
100 pthread_mutex_init(&lock_records_mutex, NULL);
101 pthread_mutex_lock(&lock_records_mutex);
102
103 lock_records = HashListTableInit(512, LockRecordHash, LockRecordCompare, LockRecordFree);
104 BUG_ON(lock_records == NULL);
105
106 pthread_mutex_unlock(&lock_records_mutex);
107
108 return 0;
109}
110
111static void LockRecordAdd(ProfilingLock *l)
112{
113 LockRecord fn = { NULL, NULL, 0,0,0,0,0,0}, *ptr = &fn;
114 fn.file = l->file;
115 fn.line = l->line;
116
117 LockRecord *lookup_fn = (LockRecord *)HashListTableLookup(lock_records, (void *)ptr, 0);
118 if (lookup_fn == NULL) {
119 LockRecord *new = SCMalloc(sizeof(LockRecord));
120 BUG_ON(new == NULL);
121
122 new->file = l->file;
123 new->line = l->line;
124 new->type = l->type;
125 new->cont = l->cont;
126 new->func = l->func;
127 new->ticks_max = l->ticks;
128 new->ticks_total = l->ticks;
129 new->ticks_cnt = 1;
130
131 HashListTableAdd(lock_records, (void *)new, 0);
132 } else {
133 lookup_fn->ticks_total += l->ticks;
134 if (l->ticks > lookup_fn->ticks_max)
135 lookup_fn->ticks_max = l->ticks;
136 lookup_fn->ticks_cnt++;
137 lookup_fn->cont += l->cont;
138 }
139}
140
141/** \param p void ptr to Packet struct */
142void SCProfilingAddPacketLocks(void *p)
143{
144 int i;
145
147 return;
148
149 for (i = 0; i < locks_idx; i++) {
150 pthread_mutex_lock(&lock_records_mutex);
151 LockRecordAdd(&locks[i]);
152 pthread_mutex_unlock(&lock_records_mutex);
153 }
154}
155
156static void SCProfilingListLocks(void)
157{
158 FILE *fp = NULL;
159
162
163 if (fp == NULL) {
164 SCLogError("failed to open %s: %s", profiling_locks_file_name, strerror(errno));
165 return;
166 }
167 } else {
168 fp = stdout;
169 }
170
171 fprintf(fp, "\n\nLock Cnt Avg ticks Max ticks Total ticks Cont Func\n");
172 fprintf(fp, "------------------ ---------- --------- ------------ ------------ ------- ---------\n");
173
174 uint64_t total = 0;
175 uint32_t cont = 0;
176 uint64_t cnt = 0;
177
179 while (b) {
180 LockRecord *r = HashListTableGetListData(b);
181
182 const char *lock;
183 switch (r->type) {
184 case LOCK_MUTEX:
185 lock = "mtx";
186 break;
187 case LOCK_SPIN:
188 lock = "spn";
189 break;
190 case LOCK_RWW:
191 lock = "rww";
192 break;
193 case LOCK_RWR:
194 lock = "rwr";
195 break;
196 default:
197 lock = "bug";
198 break;
199 }
200
201 char str[128] = "";
202 snprintf(str, sizeof(str), "(%s) %s:%d", lock,r->file, r->line);
203
204 fprintf(fp, "%-50s %-10u %-9"PRIu64" %-12"PRIu64" %-12"PRIu64" %-7u %-s\n",
205 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);
206
207 total += r->ticks_total;
208 cnt += r->ticks_cnt;
209 cont += r->cont;
210
212 }
213
214 fprintf(fp, "\nOverall: locks %"PRIu64", average cost %"PRIu64", contentions %"PRIu32", total ticks %"PRIu64"\n",
215 cnt, (uint64_t)((uint64_t)total/(uint64_t)cnt), cont, total);
216
217 fclose(fp);
218}
219
220void LockRecordFreeHash(void)
221{
223 return;
224
225 pthread_mutex_lock(&lock_records_mutex);
226
227 SCProfilingListLocks();
228
229 if (lock_records != NULL) {
230 HashListTableFree(lock_records);
231 lock_records = NULL;
232 }
233 pthread_mutex_unlock(&lock_records_mutex);
234
235 pthread_mutex_destroy(&lock_records_mutex);
236}
237
238#endif
239#endif
uint16_t type
HRLOCK_TYPE lock
Definition host.h:0
uint32_t array_size
#define BUG_ON(x)
#define str(s)
@ LOCK_SPIN
@ LOCK_RWR
@ LOCK_RWW
@ LOCK_MUTEX
#define PROFILING_MAX_LOCKS
thread_local ProfilingLock locks[PROFILING_MAX_LOCKS]
thread_local int record_locks
thread_local int locks_idx
uint32_t cnt
#define SCLogError(...)
Macro used to log ERROR messages.
Definition util-debug.h:267
void * HashListTableLookup(HashListTable *ht, void *data, uint16_t datalen)
int HashListTableAdd(HashListTable *ht, void *data, uint16_t datalen)
HashListTableBucket * HashListTableGetListHead(HashListTable *ht)
HashListTable * HashListTableInit(uint32_t size, uint32_t(*Hash)(struct HashListTable_ *, void *, uint16_t), char(*Compare)(void *, uint16_t, void *, uint16_t), void(*Free)(void *))
void HashListTableFree(HashListTable *ht)
#define HashListTableGetListData(hb)
#define HashListTableGetListNext(hb)
#define SCMalloc(sz)
Definition util-mem.h:47
#define SCFree(p)
Definition util-mem.h:61
void LockRecordFreeHash(void)
void SCProfilingAddPacketLocks(void *)
int LockRecordInitHash(void)
int profiling_locks_output_to_file
const char * profiling_locks_file_mode
char * profiling_locks_file_name
int profiling_locks_enabled