1 /* Copyright (C) 2007-2012 Open Information Security Foundation
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
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.
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
21 * \author Endace Technology Limited.
22 * \author Victor Julien <victor@inliniac.net>
25 #ifndef __UTIL_PROFILE_H__
26 #define __UTIL_PROFILE_H__
30 #include "util-profiling-locks.h"
33 extern int profiling_rules_enabled
;
34 extern int profiling_packets_enabled
;
35 extern int profiling_sghs_enabled
;
36 extern thread_local
int profiling_rules_entered
;
38 void SCProfilingPrintPacketProfile(Packet
*);
39 void SCProfilingAddPacket(Packet
*);
40 int SCProfileRuleStart(Packet
*p
);
42 #define RULE_PROFILING_START(p) \
43 uint64_t profile_rule_start_ = 0; \
44 uint64_t profile_rule_end_ = 0; \
45 if (profiling_rules_enabled && SCProfileRuleStart((p))) { \
46 if (profiling_rules_entered > 0) { \
47 SCLogError(SC_ERR_FATAL, "Re-entered profiling, exiting."); \
50 profiling_rules_entered++; \
51 profile_rule_start_ = UtilCpuGetTicks(); \
54 #define RULE_PROFILING_END(ctx, r, m, p) \
55 if (profiling_rules_enabled && ((p)->flags & PKT_PROFILE)) { \
56 profile_rule_end_ = UtilCpuGetTicks(); \
57 SCProfilingRuleUpdateCounter(ctx, r->profiling_id, \
58 profile_rule_end_ - profile_rule_start_, m); \
59 profiling_rules_entered--; \
62 extern int profiling_keyword_enabled
;
63 extern thread_local
int profiling_keyword_entered
;
65 #define KEYWORD_PROFILING_SET_LIST(ctx, list) { \
66 (ctx)->keyword_perf_list = (list); \
69 #define KEYWORD_PROFILING_START \
70 uint64_t profile_keyword_start_ = 0; \
71 uint64_t profile_keyword_end_ = 0; \
72 if (profiling_keyword_enabled) { \
73 if (profiling_keyword_entered > 0) { \
74 SCLogError(SC_ERR_FATAL, "Re-entered profiling, exiting."); \
77 profiling_keyword_entered++; \
78 profile_keyword_start_ = UtilCpuGetTicks(); \
81 /* we allow this macro to be called if profiling_keyword_entered == 0,
82 * so that we don't have to refactor some of the detection code. */
83 #define KEYWORD_PROFILING_END(ctx, type, m) \
84 if (profiling_keyword_enabled && profiling_keyword_entered) { \
85 profile_keyword_end_ = UtilCpuGetTicks(); \
86 SCProfilingKeywordUpdateCounter((ctx),(type),(profile_keyword_end_ - profile_keyword_start_),(m)); \
87 profiling_keyword_entered--; \
90 PktProfiling
*SCProfilePacketStart(void);
92 #define PACKET_PROFILING_START(p) \
93 if (profiling_packets_enabled) { \
94 (p)->profile = SCProfilePacketStart(); \
95 if ((p)->profile != NULL) \
96 (p)->profile->ticks_start = UtilCpuGetTicks(); \
99 #define PACKET_PROFILING_RESTART(p) \
100 if (profiling_packets_enabled) { \
101 if ((p)->profile != NULL) \
102 (p)->profile->ticks_start = UtilCpuGetTicks(); \
105 #define PACKET_PROFILING_END(p) \
106 if (profiling_packets_enabled && (p)->profile != NULL) { \
107 (p)->profile->ticks_end = UtilCpuGetTicks(); \
108 SCProfilingAddPacket((p)); \
111 #ifdef PROFILE_LOCKING
112 #define PACKET_PROFILING_RESET_LOCKS do { \
113 mutex_lock_cnt = 0; \
114 mutex_lock_wait_ticks = 0; \
115 mutex_lock_contention = 0; \
117 spin_lock_wait_ticks = 0; \
118 spin_lock_contention = 0; \
120 rww_lock_wait_ticks = 0; \
121 rww_lock_contention = 0; \
123 rwr_lock_wait_ticks = 0; \
124 rwr_lock_contention = 0; \
129 #define PACKET_PROFILING_COPY_LOCKS(p, id) do { \
130 (p)->profile->tmm[(id)].mutex_lock_cnt = mutex_lock_cnt; \
131 (p)->profile->tmm[(id)].mutex_lock_wait_ticks = mutex_lock_wait_ticks; \
132 (p)->profile->tmm[(id)].mutex_lock_contention = mutex_lock_contention; \
133 (p)->profile->tmm[(id)].spin_lock_cnt = spin_lock_cnt; \
134 (p)->profile->tmm[(id)].spin_lock_wait_ticks = spin_lock_wait_ticks; \
135 (p)->profile->tmm[(id)].spin_lock_contention = spin_lock_contention; \
136 (p)->profile->tmm[(id)].rww_lock_cnt = rww_lock_cnt; \
137 (p)->profile->tmm[(id)].rww_lock_wait_ticks = rww_lock_wait_ticks; \
138 (p)->profile->tmm[(id)].rww_lock_contention = rww_lock_contention; \
139 (p)->profile->tmm[(id)].rwr_lock_cnt = rwr_lock_cnt; \
140 (p)->profile->tmm[(id)].rwr_lock_wait_ticks = rwr_lock_wait_ticks; \
141 (p)->profile->tmm[(id)].rwr_lock_contention = rwr_lock_contention; \
143 SCProfilingAddPacketLocks((p)); \
146 #define PACKET_PROFILING_RESET_LOCKS
147 #define PACKET_PROFILING_COPY_LOCKS(p, id)
150 #define PACKET_PROFILING_TMM_START(p, id) \
151 if (profiling_packets_enabled && (p)->profile != NULL) { \
152 if ((id) < TMM_SIZE) { \
153 (p)->profile->tmm[(id)].ticks_start = UtilCpuGetTicks();\
154 PACKET_PROFILING_RESET_LOCKS; \
158 #define PACKET_PROFILING_TMM_END(p, id) \
159 if (profiling_packets_enabled && (p)->profile != NULL) { \
160 if ((id) < TMM_SIZE) { \
161 PACKET_PROFILING_COPY_LOCKS((p), (id)); \
162 (p)->profile->tmm[(id)].ticks_end = UtilCpuGetTicks(); \
166 #define FLOWWORKER_PROFILING_START(p, id) \
167 if (profiling_packets_enabled && (p)->profile != NULL) { \
168 if ((id) < PROFILE_FLOWWORKER_SIZE) { \
169 (p)->profile->flowworker[(id)].ticks_start = UtilCpuGetTicks();\
173 #define FLOWWORKER_PROFILING_END(p, id) \
174 if (profiling_packets_enabled && (p)->profile != NULL) { \
175 if ((id) < PROFILE_FLOWWORKER_SIZE) { \
176 (p)->profile->flowworker[(id)].ticks_end = UtilCpuGetTicks(); \
180 #define PACKET_PROFILING_RESET(p) \
181 if (profiling_packets_enabled && (p)->profile != NULL) { \
182 SCFree((p)->profile); \
183 (p)->profile = NULL; \
186 #define PACKET_PROFILING_APP_START(dp, id) \
187 if (profiling_packets_enabled) { \
188 (dp)->ticks_start = UtilCpuGetTicks(); \
189 (dp)->alproto = (id); \
192 #define PACKET_PROFILING_APP_END(dp, id) \
193 if (profiling_packets_enabled) { \
194 BUG_ON((id) != (dp)->alproto); \
195 (dp)->ticks_end = UtilCpuGetTicks(); \
196 if ((dp)->ticks_start != 0 && (dp)->ticks_start < ((dp)->ticks_end)) { \
197 (dp)->ticks_spent = ((dp)->ticks_end - (dp)->ticks_start); \
201 #define PACKET_PROFILING_APP_PD_START(dp) \
202 if (profiling_packets_enabled) { \
203 (dp)->proto_detect_ticks_start = UtilCpuGetTicks(); \
206 #define PACKET_PROFILING_APP_PD_END(dp) \
207 if (profiling_packets_enabled) { \
208 (dp)->proto_detect_ticks_end = UtilCpuGetTicks(); \
209 if ((dp)->proto_detect_ticks_start != 0 && (dp)->proto_detect_ticks_start < ((dp)->proto_detect_ticks_end)) { \
210 (dp)->proto_detect_ticks_spent = \
211 ((dp)->proto_detect_ticks_end - (dp)->proto_detect_ticks_start); \
215 #define PACKET_PROFILING_APP_RESET(dp) \
216 if (profiling_packets_enabled) { \
217 (dp)->ticks_start = 0; \
218 (dp)->ticks_end = 0; \
219 (dp)->ticks_spent = 0; \
221 (dp)->proto_detect_ticks_start = 0; \
222 (dp)->proto_detect_ticks_end = 0; \
223 (dp)->proto_detect_ticks_spent = 0; \
226 #define PACKET_PROFILING_APP_STORE(dp, p) \
227 if (profiling_packets_enabled && (p)->profile != NULL) { \
228 if ((dp)->alproto < ALPROTO_MAX) { \
229 (p)->profile->app[(dp)->alproto].ticks_spent += (dp)->ticks_spent; \
230 (p)->profile->proto_detect += (dp)->proto_detect_ticks_spent; \
234 #define PACKET_PROFILING_DETECT_START(p, id) \
235 if (profiling_packets_enabled && (p)->profile != NULL) { \
236 if ((id) < PROF_DETECT_SIZE) { \
237 (p)->profile->detect[(id)].ticks_start = UtilCpuGetTicks(); \
241 #define PACKET_PROFILING_DETECT_END(p, id) \
242 if (profiling_packets_enabled && (p)->profile != NULL) { \
243 if ((id) < PROF_DETECT_SIZE) { \
244 (p)->profile->detect[(id)].ticks_end = UtilCpuGetTicks();\
245 if ((p)->profile->detect[(id)].ticks_start != 0 && \
246 (p)->profile->detect[(id)].ticks_start < (p)->profile->detect[(id)].ticks_end) { \
247 (p)->profile->detect[(id)].ticks_spent += \
248 ((p)->profile->detect[(id)].ticks_end - (p)->profile->detect[(id)].ticks_start); \
253 #define PACKET_PROFILING_LOGGER_START(p, id) \
254 if (profiling_packets_enabled && (p)->profile != NULL) { \
255 if ((id) < LOGGER_SIZE) { \
256 (p)->profile->logger[(id)].ticks_start = UtilCpuGetTicks(); \
260 #define PACKET_PROFILING_LOGGER_END(p, id) \
261 if (profiling_packets_enabled && (p)->profile != NULL) { \
262 if ((id) < LOGGER_SIZE) { \
263 (p)->profile->logger[(id)].ticks_end = UtilCpuGetTicks();\
264 if ((p)->profile->logger[(id)].ticks_start != 0 && \
265 (p)->profile->logger[(id)].ticks_start < (p)->profile->logger[(id)].ticks_end) { \
266 (p)->profile->logger[(id)].ticks_spent += \
267 ((p)->profile->logger[(id)].ticks_end - (p)->profile->logger[(id)].ticks_start); \
272 #define SGH_PROFILING_RECORD(det_ctx, sgh) \
273 if (profiling_sghs_enabled) { \
274 SCProfilingSghUpdateCounter((det_ctx), (sgh)); \
277 extern int profiling_prefilter_enabled
;
278 extern thread_local
int profiling_prefilter_entered
;
280 #define PREFILTER_PROFILING_START \
281 uint64_t profile_prefilter_start_ = 0; \
282 uint64_t profile_prefilter_end_ = 0; \
283 if (profiling_prefilter_enabled) { \
284 if (profiling_prefilter_entered > 0) { \
285 SCLogError(SC_ERR_FATAL, "Re-entered profiling, exiting."); \
288 profiling_prefilter_entered++; \
289 profile_prefilter_start_ = UtilCpuGetTicks(); \
292 /* we allow this macro to be called if profiling_prefilter_entered == 0,
293 * so that we don't have to refactor some of the detection code. */
294 #define PREFILTER_PROFILING_END(ctx, profile_id) \
295 if (profiling_prefilter_enabled && profiling_prefilter_entered) { \
296 profile_prefilter_end_ = UtilCpuGetTicks(); \
297 if (profile_prefilter_end_ > profile_prefilter_start_) \
298 SCProfilingPrefilterUpdateCounter((ctx),(profile_id),(profile_prefilter_end_ - profile_prefilter_start_)); \
299 profiling_prefilter_entered--; \
302 void SCProfilingRulesGlobalInit(void);
303 void SCProfilingRuleDestroyCtx(struct SCProfileDetectCtx_
*);
304 void SCProfilingRuleInitCounters(DetectEngineCtx
*);
305 void SCProfilingRuleUpdateCounter(DetectEngineThreadCtx
*, uint16_t, uint64_t, int);
306 void SCProfilingRuleThreadSetup(struct SCProfileDetectCtx_
*, DetectEngineThreadCtx
*);
307 void SCProfilingRuleThreadCleanup(DetectEngineThreadCtx
*);
309 void SCProfilingKeywordsGlobalInit(void);
310 void SCProfilingKeywordDestroyCtx(DetectEngineCtx
*);//struct SCProfileKeywordDetectCtx_ *);
311 void SCProfilingKeywordInitCounters(DetectEngineCtx
*);
312 void SCProfilingKeywordUpdateCounter(DetectEngineThreadCtx
*det_ctx
, int id
, uint64_t ticks
, int match
);
313 void SCProfilingKeywordThreadSetup(struct SCProfileKeywordDetectCtx_
*, DetectEngineThreadCtx
*);
314 void SCProfilingKeywordThreadCleanup(DetectEngineThreadCtx
*);
316 struct SCProfilePrefilterDetectCtx_
;
317 void SCProfilingPrefilterGlobalInit(void);
318 void SCProfilingPrefilterDestroyCtx(DetectEngineCtx
*);
319 void SCProfilingPrefilterInitCounters(DetectEngineCtx
*);
320 void SCProfilingPrefilterUpdateCounter(DetectEngineThreadCtx
*det_ctx
, int id
, uint64_t ticks
);
321 void SCProfilingPrefilterThreadSetup(struct SCProfilePrefilterDetectCtx_
*, DetectEngineThreadCtx
*);
322 void SCProfilingPrefilterThreadCleanup(DetectEngineThreadCtx
*);
324 void SCProfilingSghsGlobalInit(void);
325 void SCProfilingSghDestroyCtx(DetectEngineCtx
*);
326 void SCProfilingSghInitCounters(DetectEngineCtx
*);
327 void SCProfilingSghUpdateCounter(DetectEngineThreadCtx
*det_ctx
, const SigGroupHead
*sgh
);
328 void SCProfilingSghThreadSetup(struct SCProfileSghDetectCtx_
*, DetectEngineThreadCtx
*);
329 void SCProfilingSghThreadCleanup(DetectEngineThreadCtx
*);
331 void SCProfilingInit(void);
332 void SCProfilingDestroy(void);
333 void SCProfilingRegisterTests(void);
334 void SCProfilingDump(void);
338 #define RULE_PROFILING_START(p)
339 #define RULE_PROFILING_END(a,b,c,p)
341 #define KEYWORD_PROFILING_SET_LIST(a,b)
342 #define KEYWORD_PROFILING_START
343 #define KEYWORD_PROFILING_END(a,b,c)
345 #define PACKET_PROFILING_START(p)
346 #define PACKET_PROFILING_RESTART(p)
347 #define PACKET_PROFILING_END(p)
349 #define PACKET_PROFILING_TMM_START(p, id)
350 #define PACKET_PROFILING_TMM_END(p, id)
352 #define PACKET_PROFILING_RESET(p)
354 #define PACKET_PROFILING_APP_START(dp, id)
355 #define PACKET_PROFILING_APP_END(dp, id)
356 #define PACKET_PROFILING_APP_RESET(dp)
357 #define PACKET_PROFILING_APP_STORE(dp, p)
359 #define PACKET_PROFILING_APP_PD_START(dp)
360 #define PACKET_PROFILING_APP_PD_END(dp)
362 #define PACKET_PROFILING_DETECT_START(p, id)
363 #define PACKET_PROFILING_DETECT_END(p, id)
365 #define PACKET_PROFILING_LOGGER_START(p, id)
366 #define PACKET_PROFILING_LOGGER_END(p, id)
368 #define SGH_PROFILING_RECORD(det_ctx, sgh)
370 #define FLOWWORKER_PROFILING_START(p, id)
371 #define FLOWWORKER_PROFILING_END(p, id)
373 #define PREFILTER_PROFILING_START
374 #define PREFILTER_PROFILING_END(ctx, profile_id)
376 #endif /* PROFILING */
378 #endif /* ! __UTIL_PROFILE_H__ */