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"
28 #include "util-profiling-locks.h"
29 
30 #ifdef PROFILING
31 #ifdef PROFILE_LOCKING
32 #include "threads.h"
33 #include "util-hashlist.h"
34 #include "util-debug.h"
35 
37 thread_local int locks_idx = 0;
38 thread_local int record_locks = 0;
39 
42 char *profiling_locks_file_name = NULL;
43 const char *profiling_locks_file_mode = "a";
44 
45 typedef 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 
59 HashListTable *lock_records;
60 pthread_mutex_t lock_records_mutex;
61 
62 static 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 
75 static 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 
89 static void LockRecordFree(void *data)
90 {
91  LockRecord *fn = (LockRecord *)data;
92 
93  if (fn == NULL)
94  return;
95  SCFree(fn);
96 }
97 
98 int 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 
111 static 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 */
142 void SCProfilingAddPacketLocks(void *p)
143 {
144  int i;
145 
146  if (profiling_locks_enabled == 0)
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 
156 static 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 
220 void LockRecordFreeHash(void)
221 {
222  if (profiling_locks_enabled == 0)
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
HashListTableGetListData
#define HashListTableGetListData(hb)
Definition: util-hashlist.h:56
record_locks
thread_local int record_locks
LOCK_RWW
@ LOCK_RWW
Definition: threads-profile.h:39
util-hashlist.h
ProfilingLock_::cont
uint32_t cont
Definition: threads-profile.h:48
LockRecordInitHash
int LockRecordInitHash(void)
profiling_locks_file_mode
const char * profiling_locks_file_mode
LOCK_SPIN
@ LOCK_SPIN
Definition: threads-profile.h:38
threads.h
HashListTableGetListHead
HashListTableBucket * HashListTableGetListHead(HashListTable *ht)
Definition: util-hashlist.c:287
ProfilingLock_::func
char * func
Definition: threads-profile.h:45
locks
thread_local ProfilingLock locks[PROFILING_MAX_LOCKS]
HashListTableLookup
void * HashListTableLookup(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:245
profiling_locks_output_to_file
int profiling_locks_output_to_file
ProfilingLock_::file
char * file
Definition: threads-profile.h:44
HashListTableAdd
int HashListTableAdd(HashListTable *ht, void *data, uint16_t datalen)
Definition: util-hashlist.c:114
HashListTable_::array_size
uint32_t array_size
Definition: util-hashlist.h:41
lock
HRLOCK_TYPE lock
Definition: host.h:0
HashListTableGetListNext
#define HashListTableGetListNext(hb)
Definition: util-hashlist.h:55
ProfilingLock_
Definition: threads-profile.h:43
ProfilingLock_::ticks
uint64_t ticks
Definition: threads-profile.h:49
HashListTableInit
HashListTable * HashListTableInit(uint32_t size, uint32_t(*Hash)(struct HashListTable_ *, void *, uint16_t), char(*Compare)(void *, uint16_t, void *, uint16_t), void(*Free)(void *))
Definition: util-hashlist.c:35
util-debug.h
locks_idx
thread_local int locks_idx
BUG_ON
#define BUG_ON(x)
Definition: suricata-common.h:300
type
uint16_t type
Definition: decode-vlan.c:107
HashListTable_
Definition: util-hashlist.h:37
PROFILING_MAX_LOCKS
#define PROFILING_MAX_LOCKS
Definition: threads-profile.h:32
LOCK_MUTEX
@ LOCK_MUTEX
Definition: threads-profile.h:37
cnt
uint32_t cnt
Definition: tmqh-packetpool.h:7
suricata-common.h
HashListTableFree
void HashListTableFree(HashListTable *ht)
Definition: util-hashlist.c:88
ProfilingLock_::type
int type
Definition: threads-profile.h:47
SCProfilingAddPacketLocks
void SCProfilingAddPacketLocks(void *)
SCMalloc
#define SCMalloc(sz)
Definition: util-mem.h:47
str
#define str(s)
Definition: suricata-common.h:291
SCLogError
#define SCLogError(...)
Macro used to log ERROR messages.
Definition: util-debug.h:261
SCFree
#define SCFree(p)
Definition: util-mem.h:61
HashListTableBucket_
Definition: util-hashlist.h:28
profiling_locks_file_name
char * profiling_locks_file_name
LockRecordFreeHash
void LockRecordFreeHash(void)
LOCK_RWR
@ LOCK_RWR
Definition: threads-profile.h:40
util-profiling-locks.h
ProfilingLock_::line
int line
Definition: threads-profile.h:46
profiling_locks_enabled
int profiling_locks_enabled