/* ** Copyright (C) 2005 Sourcefire, Inc. ** Author: Steven Sturges ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License Version 2 as ** published by the Free Software Foundation. You may not use, modify or ** distribute this program under any other version of the GNU General ** Public License. ** ** 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 ** along with this program; if not, write to the Free Software ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* $Id$ */ #ifndef __PROFILER_H__ #define __PROFILER_H__ #ifdef PERF_PROFILING #ifndef UINT64 #define UINT64 unsigned long long #endif /* Assembly to find clock ticks. Intel only */ #ifdef WIN32 #define get_clockticks(val) \ QueryPerformanceCounter((PLARGE_INTEGER)&val) #else #if (defined(__i386) || defined(__ia64) || defined(__amd64) ) #define get_clockticks(val) \ { \ u_int32_t a, d; \ __asm__ __volatile__ ("rdtsc" : "=a" (a), "=d" (d)); \ val = ((UINT64)a) | (((UINT64)d) << 32); \ } #else #if (defined(__GNUC__) && (defined(__powerpc__) || (defined(__ppc__)))) #define get_clockticks(val) \ { \ u_int32_t tbu0, tbu1, tbl; \ do \ { \ __asm__ __volatile__ ("mftbu %0" : "=r"(tbu0)); \ __asm__ __volatile__ ("mftb %0" : "=r"(tbl)); \ __asm__ __volatile__ ("mftbu %0" : "=r"(tbu1)); \ } while (tbu0 != tbu1); \ val = ((UINT64)tbl) | (((UINT64)tbu0) << 32); \ } #else #define get_clockticks(val) #endif /* POWERPC || PPC */ #endif /* I386 || IA64 || AMD64 */ #endif /* WIN32 */ /* Sort preferences for rule profiling */ #define PROFILE_SORT_CHECKS 1 #define PROFILE_SORT_MATCHES 2 #define PROFILE_SORT_NOMATCHES 3 #define PROFILE_SORT_AVG_TICKS 4 #define PROFILE_SORT_AVG_TICKS_PER_MATCH 5 #define PROFILE_SORT_AVG_TICKS_PER_NOMATCH 6 #define PROFILE_SORT_TOTAL_TICKS 7 /* MACROS that handle profiling of rules and preprocessors */ #define PROFILE_VARS UINT64 ticks_start = 0, ticks_end = 0, ticks_delta #define PROFILE_START \ get_clockticks(ticks_start); #define PROFILE_END \ get_clockticks(ticks_end); \ ticks_delta = ticks_end - ticks_start; #ifndef PROFILING_RULES #define PROFILING_RULES pv.profile_rules_flag #endif #define OTN_PROFILE_START(otn) \ if (PROFILING_RULES) { \ otn->checks++; \ PROFILE_START; \ } #define OTN_PROFILE_END_MATCH(otn) \ if (PROFILING_RULES) { \ PROFILE_END; \ otn->ticks += ticks_delta; \ otn->ticks_match += ticks_delta; \ otn->matches++; \ } #define OTN_PROFILE_NOALERT(otn) \ if (PROFILING_RULES) { \ otn->noalerts=1; \ } #define OTN_PROFILE_END_NOMATCH(otn) \ if (PROFILING_RULES) { \ PROFILE_END; \ otn->ticks += ticks_delta; \ otn->ticks_no_match += ticks_delta; \ } #define OTN_PROFILE_ALERT(otn) otn->alerts++; #ifndef PROFILING_PREPROCS #define PROFILING_PREPROCS pv.profile_preprocs_flag #endif #define PREPROC_PROFILE_START(ppstat) \ if (PROFILING_PREPROCS) { \ ppstat.checks++; \ PROFILE_START; \ ppstat.ticks_start = ticks_start; \ } #define PREPROC_PROFILE_REENTER_START(ppstat) \ if (PROFILING_PREPROCS) { \ PROFILE_START; \ ppstat.ticks_start = ticks_start; \ } #define PREPROC_PROFILE_TMPSTART(ppstat) \ if (PROFILING_PREPROCS) { \ PROFILE_START; \ ppstat.ticks_start = ticks_start; \ } #define PREPROC_PROFILE_END(ppstat) \ if (PROFILING_PREPROCS) { \ PROFILE_END; \ ppstat.exits++; \ ppstat.ticks += ticks_end - ppstat.ticks_start; \ } #define PREPROC_PROFILE_REENTER_END(ppstat) \ if (PROFILING_PREPROCS) { \ PROFILE_END; \ ppstat.ticks += ticks_end - ppstat.ticks_start; \ } #define PREPROC_PROFILE_TMPEND(ppstat) \ if (PROFILING_PREPROCS) { \ PROFILE_END; \ ppstat.ticks += ticks_end - ppstat.ticks_start; \ } /************** Profiling API ******************/ void ShowRuleProfiles(); /* Preprocessor stats info */ typedef struct _PreprocStats { UINT64 ticks, ticks_start; UINT64 checks; UINT64 exits; } PreprocStats; typedef struct _PreprocStatsNode { PreprocStats *stats; char *name; int layer; PreprocStats *parent; struct _PreprocStatsNode *next; } PreprocStatsNode; void RegisterPreprocessorProfile(char *keyword, PreprocStats *stats, int layer, PreprocStats *parent); void ShowPreprocProfiles(); extern PreprocStats totalPerfStats; #else #define PROFILE_VARS #define OTN_PROFILE_START(otn) #define OTN_PROFILE_END_MATCH(otn) #define OTN_PROFILE_END_NOMATCH(otn) #define OTN_PROFILE_NOALERT(otn) #define OTN_PROFILE_ALERT(otn) #define PREPROC_PROFILE_START(ppstat) #define PREPROC_PROFILE_REENTER_START(ppstat) #define PREPROC_PROFILE_TMPSTART(ppstat) #define PREPROC_PROFILE_END(ppstat) #define PREPROC_PROFILE_REENTER_END(ppstat) #define PREPROC_PROFILE_TMPEND(ppstat) #endif #endif /* __PROFILER_H__ */