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 Endace Technology Limited. 22 * \author Victor Julien <victor@inliniac.net> 23 */ 24 25 #ifndef __UTIL_PROFILE_H__ 26 #define __UTIL_PROFILE_H__ 27 28 #ifdef PROFILING 29 30 #include "util-profiling-locks.h" 31 #include "util-cpu.h" 32 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; 37 38 void SCProfilingPrintPacketProfile(Packet *); 39 void SCProfilingAddPacket(Packet *); 40 int SCProfileRuleStart(Packet *p); 41 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."); \ 48 exit(1); \ 49 } \ 50 profiling_rules_entered++; \ 51 profile_rule_start_ = UtilCpuGetTicks(); \ 52 } 53 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--; \ 60 } 61 62 extern int profiling_keyword_enabled; 63 extern thread_local int profiling_keyword_entered; 64 65 #define KEYWORD_PROFILING_SET_LIST(ctx, list) { \ 66 (ctx)->keyword_perf_list = (list); \ 67 } 68 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."); \ 75 abort(); \ 76 } \ 77 profiling_keyword_entered++; \ 78 profile_keyword_start_ = UtilCpuGetTicks(); \ 79 } 80 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--; \ 88 } 89 90 PktProfiling *SCProfilePacketStart(void); 91 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(); \ 97 } 98 99 #define PACKET_PROFILING_RESTART(p) \ 100 if (profiling_packets_enabled) { \ 101 if ((p)->profile != NULL) \ 102 (p)->profile->ticks_start = UtilCpuGetTicks(); \ 103 } 104 105 #define PACKET_PROFILING_END(p) \ 106 if (profiling_packets_enabled && (p)->profile != NULL) { \ 107 (p)->profile->ticks_end = UtilCpuGetTicks(); \ 108 SCProfilingAddPacket((p)); \ 109 } 110 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; \ 116 spin_lock_cnt = 0; \ 117 spin_lock_wait_ticks = 0; \ 118 spin_lock_contention = 0; \ 119 rww_lock_cnt = 0; \ 120 rww_lock_wait_ticks = 0; \ 121 rww_lock_contention = 0; \ 122 rwr_lock_cnt = 0; \ 123 rwr_lock_wait_ticks = 0; \ 124 rwr_lock_contention = 0; \ 125 locks_idx = 0; \ 126 record_locks = 1;\ 127 } while (0) 128 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; \ 142 record_locks = 0; \ 143 SCProfilingAddPacketLocks((p)); \ 144 } while(0) 145 #else 146 #define PACKET_PROFILING_RESET_LOCKS 147 #define PACKET_PROFILING_COPY_LOCKS(p, id) 148 #endif 149 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; \ 155 } \ 156 } 157 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(); \ 163 } \ 164 } 165 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();\ 170 } \ 171 } 172 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(); \ 177 } \ 178 } 179 180 #define PACKET_PROFILING_RESET(p) \ 181 if (profiling_packets_enabled && (p)->profile != NULL) { \ 182 SCFree((p)->profile); \ 183 (p)->profile = NULL; \ 184 } 185 186 #define PACKET_PROFILING_APP_START(dp, id) \ 187 if (profiling_packets_enabled) { \ 188 (dp)->ticks_start = UtilCpuGetTicks(); \ 189 (dp)->alproto = (id); \ 190 } 191 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); \ 198 } \ 199 } 200 201 #define PACKET_PROFILING_APP_PD_START(dp) \ 202 if (profiling_packets_enabled) { \ 203 (dp)->proto_detect_ticks_start = UtilCpuGetTicks(); \ 204 } 205 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); \ 212 } \ 213 } 214 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; \ 220 (dp)->alproto = 0; \ 221 (dp)->proto_detect_ticks_start = 0; \ 222 (dp)->proto_detect_ticks_end = 0; \ 223 (dp)->proto_detect_ticks_spent = 0; \ 224 } 225 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; \ 231 } \ 232 } 233 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(); \ 238 } \ 239 } 240 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); \ 249 } \ 250 } \ 251 } 252 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(); \ 257 } \ 258 } 259 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); \ 268 } \ 269 } \ 270 } 271 272 #define SGH_PROFILING_RECORD(det_ctx, sgh) \ 273 if (profiling_sghs_enabled) { \ 274 SCProfilingSghUpdateCounter((det_ctx), (sgh)); \ 275 } 276 277 extern int profiling_prefilter_enabled; 278 extern thread_local int profiling_prefilter_entered; 279 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."); \ 286 abort(); \ 287 } \ 288 profiling_prefilter_entered++; \ 289 profile_prefilter_start_ = UtilCpuGetTicks(); \ 290 } 291 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--; \ 300 } 301 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 *); 308 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 *); 315 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 *); 323 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 *); 330 331 void SCProfilingInit(void); 332 void SCProfilingDestroy(void); 333 void SCProfilingRegisterTests(void); 334 void SCProfilingDump(void); 335 336 #else 337 338 #define RULE_PROFILING_START(p) 339 #define RULE_PROFILING_END(a,b,c,p) 340 341 #define KEYWORD_PROFILING_SET_LIST(a,b) 342 #define KEYWORD_PROFILING_START 343 #define KEYWORD_PROFILING_END(a,b,c) 344 345 #define PACKET_PROFILING_START(p) 346 #define PACKET_PROFILING_RESTART(p) 347 #define PACKET_PROFILING_END(p) 348 349 #define PACKET_PROFILING_TMM_START(p, id) 350 #define PACKET_PROFILING_TMM_END(p, id) 351 352 #define PACKET_PROFILING_RESET(p) 353 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) 358 359 #define PACKET_PROFILING_APP_PD_START(dp) 360 #define PACKET_PROFILING_APP_PD_END(dp) 361 362 #define PACKET_PROFILING_DETECT_START(p, id) 363 #define PACKET_PROFILING_DETECT_END(p, id) 364 365 #define PACKET_PROFILING_LOGGER_START(p, id) 366 #define PACKET_PROFILING_LOGGER_END(p, id) 367 368 #define SGH_PROFILING_RECORD(det_ctx, sgh) 369 370 #define FLOWWORKER_PROFILING_START(p, id) 371 #define FLOWWORKER_PROFILING_END(p, id) 372 373 #define PREFILTER_PROFILING_START 374 #define PREFILTER_PROFILING_END(ctx, profile_id) 375 376 #endif /* PROFILING */ 377 378 #endif /* ! __UTIL_PROFILE_H__ */ 379