| # Gaudi Framework, version v23r1 |

Home |  | Generated: Wed Feb 29 2012

# PerfMonAuditor.cpp

Go to the documentation of this file.

    00001 // $Id: PerfMonAuditor.cpp,v 0.1 2009/10/28 Daniele Francesco Kruse $
    00002 // ============================================================================
    00003 // CVS tag $Name:  $, version $Revision: 0.1 $
    00004 // ============================================================================
    00005
    00006 #include "GaudiKernel/Auditor.h"
    00007 #include "GaudiKernel/IToolSvc.h"
    00008 #include "GaudiKernel/IIncidentListener.h"
    00009 #include "GaudiKernel/IIncidentSvc.h"
    00010 #include "GaudiKernel/IToolSvc.h"
    00011 #include "GaudiKernel/VectorMap.h"
    00012 #include "GaudiKernel/HashMap.h"
    00013 #include "GaudiKernel/AudFactory.h"
    00014 #include "GaudiKernel/MsgStream.h"
    00015
    00016 /*BEGIN: perfmon*/
    00017 #include <iostream>
    00018 #include <string>
    00019 #include <cstring>
    00020 #include <fstream>
    00021 #include <perfmon/pfmlib.h>
    00022 #include <perfmon/pfmlib_core.h>
    00023 #include <perfmon/pfmlib_intel_nhm.h>
    00024 #include <vector>
    00025 #include <map>
    00026 #include <utility>
    00027 #include <sstream>
    00028
    00029 #include <perfmon/perfmon.h>
    00030 #include <perfmon/perfmon_dfl_smpl.h>
    00031
    00033
    00035
    00036
    00037
    00038 #include <sys/types.h>
    00039 #include <stdio.h>
    00040 #include <stdlib.h>
    00041 #include <stdarg.h>
    00042 #include <errno.h>
    00043 #include <unistd.h>
    00044 #include <string.h>
    00045 #include <signal.h>
    00046 #include <stdarg.h>
    00047 #include <stdint.h>
    00048 #include <getopt.h>
    00049 #include <time.h>
    00050 #include <sys/ptrace.h>
    00051 #include <sys/wait.h>
    00052 #include <sys/mman.h>
    00053 #include <sys/time.h>
    00054 #include <sys/resource.h>
    00055 #include <unistd.h>
    00056 #include <fcntl.h>
    00057 #include <zlib.h>
    00058
    00059 #include <algorithm>
    00060 #include <list>
    00061 #include <stack>
    00062 #include <cmath>
    00063 #include <sys/stat.h>
    00064 #include "IgHook_IgHookTrace.h"
    00065
    00066 // dlopen (link with -ldl)
    00067 #include <dlfcn.h>
    00068
    00069
    00070 #define MAX_EVT_NAME_LEN 256
    00071 #define NUM_PMCS PFMLIB_MAX_PMCS
    00072 #define NUM_PMDS PFMLIB_MAX_PMDS
    00073 #define FMT_NAME PFM_DFL_SMPL_NAME
    00074 #define BPL (sizeof(uint64_t)<<3)
    00075 #define LBPL 6
    00076
    00077 #define SYM_NAME_MAX_LENGTH 10000
    00078 #define MAX_OUTPUT_FILENAME_LENGTH 1024
    00079 #define MAX_EVENT_NAME_LENGTH 500
    00080 #define MAX_PREFIX_NAME_LENGTH 1024
    00081 #define FILENAME_MAX_LENGTH 1024
    00082
    00083 #define MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS 4
    00084
    00085 #define cpuid(func,ax,bx,cx,dx) __asm__ __volatile__ ("cpuid": "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) : "a" (func));
    00086
    00087
    00088 static pfarg_pmd_t pd_smpl[NUM_PMDS];
    00089 static uint64_t collected_samples, collected_partial;
    00090 static int ctx_fd;
    00091 static pfm_dfl_smpl_hdr_t *hdr;
    00092 static uint64_t ovfl_count;
    00093 static size_t entry_size;
    00094 static unsigned int num_smpl_pmds;
    00095 static std::vector<std::map<std::string, std::map<unsigned long, unsigned int> > > samples(MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS); //a map of modules each containing numbers of samples of their addresses
    00096 static std::vector<std::map<std::string, std::vector<unsigned long int> > > results(MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS); //a map of modules and their result values across multiple events
    00097 static uint64_t last_overflow;
    00098 static uint64_t last_count;
    00099 static int sp[MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS];
    00100
    00101 static std::stack<std::pair<INamedInterface *, std::vector<unsigned long int> > > alg_stack;
    00102 /*END: perfmon*/
    00103
    00104
    00105
    00106 namespace {
    00107   class PFMon {
    00108   public:
    00109     bool loaded;
    00110     typedef void (*pfm_stop_t)(int);
    00111     pfm_stop_t pfm_stop;
    00112     typedef void (*pfm_self_stop_t)(int);
    00113     pfm_self_stop_t pfm_self_stop;
    00114     typedef os_err_t (*pfm_restart_t)(int);
    00115     pfm_restart_t pfm_restart;
    00116     typedef int (*pfm_read_pmds_t)(int, pfarg_pmd_t*, int);
    00117     pfm_read_pmds_t pfm_read_pmds;
    00118     typedef pfm_err_t (*pfm_initialize_t)();
    00119     pfm_initialize_t pfm_initialize;
    00120     typedef pfm_err_t (*pfm_find_full_event_t)(const char *, pfmlib_event_t *);
    00121     pfm_find_full_event_t pfm_find_full_event;
    00122     typedef pfm_err_t (*pfm_dispatch_events_t)(pfmlib_input_param_t *, void *, pfmlib_output_param_t *, void *);
    00123     pfm_dispatch_events_t pfm_dispatch_events;
    00124     typedef os_err_t (*pfm_create_context_t)(pfarg_ctx_t *, char *, void *, size_t);
    00125     pfm_create_context_t pfm_create_context;
    00126     typedef os_err_t (*pfm_write_pmcs_t)(int, pfarg_pmc_t *, int);
    00127     pfm_write_pmcs_t pfm_write_pmcs;
    00128     typedef os_err_t (*pfm_write_pmds_t)(int, pfarg_pmd_t *, int);
    00129     pfm_write_pmds_t pfm_write_pmds;
    00130     typedef os_err_t (*pfm_load_context_t)(int, pfarg_load_t *);
    00131     pfm_load_context_t pfm_load_context;
    00132     typedef os_err_t (*pfm_start_t)(int fd, pfarg_start_t *);
    00133     pfm_start_t pfm_start;
    00134     typedef char* (*pfm_strerror_t)(int);
    00135     pfm_strerror_t pfm_strerror;
    00136     typedef pfm_err_t (*pfm_set_options_t)(pfmlib_options_t *);
    00137     pfm_set_options_t pfm_set_options;
    00138     typedef pfm_err_t (*pfm_get_num_counters_t)(unsigned int *);
    00139     pfm_get_num_counters_t pfm_get_num_counters;
    00140     static PFMon &instance() {
    00141       return s_instance;
    00142     }
    00143   private:
    00144     // static void failure() { throw 1; }
    00145
    00146     void* handle;
    00147
    00148     PFMon() {
    00149       handle = dlopen("libpfm.so", RTLD_NOW);
    00150       if (handle) { loaded = true; } else { loaded = false; }
    00151       if (loaded) {
    00152         pfm_start = (pfm_start_t) dlsym(handle, "pfm_start");
    00153         pfm_stop = (pfm_stop_t) dlsym(handle, "pfm_stop");
    00154         pfm_self_stop = (pfm_self_stop_t) dlsym(handle, "pfm_stop"); //it's the same
    00155         pfm_restart = (pfm_restart_t) dlsym(handle, "pfm_restart");
    00156         pfm_read_pmds = (pfm_read_pmds_t) dlsym(handle, "pfm_read_pmds");
    00157         pfm_initialize = (pfm_initialize_t) dlsym(handle, "pfm_initialize");
    00158         pfm_find_full_event = (pfm_find_full_event_t) dlsym(handle, "pfm_find_full_event");
    00159         pfm_dispatch_events = (pfm_dispatch_events_t) dlsym(handle, "pfm_dispatch_events");
    00160         pfm_create_context = (pfm_create_context_t) dlsym(handle, "pfm_create_context");
    00161         pfm_write_pmcs = (pfm_write_pmcs_t) dlsym(handle, "pfm_write_pmcs");
    00162         pfm_write_pmds = (pfm_write_pmds_t) dlsym(handle, "pfm_write_pmds");
    00163         pfm_load_context = (pfm_load_context_t) dlsym(handle, "pfm_load_context");
    00164         pfm_strerror = (pfm_strerror_t) dlsym(handle, "pfm_strerror");
    00165         pfm_set_options = (pfm_set_options_t) dlsym(handle, "pfm_set_options");
    00166         pfm_get_num_counters = (pfm_get_num_counters_t) dlsym(handle, "pfm_get_num_counters");
    00167       } else {
    00168         // pfm_start = pfm_stop = pfm_self_stop = pfm_restart = pfm_read_pmds = pfm_initialize = pfm_find_full_event = pfm_dispatch_events = pfm_create_context = pfm_write_pmcs = pfm_write_pmds = pfm_load_context = pfm_strerror = pfm_set_options = pfm_get_num_counters = failure;
    00169       }
    00170     }
    00171     ~PFMon() {
    00172       if (handle) dlclose(handle);
    00173     }
    00174
    00175     static PFMon s_instance;
    00176   };
    00177
    00178   PFMon PFMon::s_instance;
    00179 }
    00180
    00181
    00182
    00183 // ============================================================================
    00184 // GaudiAlg
    00185 // ============================================================================
    00186 // ============================================================================
    00196 class PerfMonAuditor: virtual public Auditor
    00197 {
    00198  public:
    00199   virtual void before(StandardEventType evt, INamedInterface* alg);
    00200   virtual void after(StandardEventType evt, INamedInterface* alg, const StatusCode &sc);
    00201   using Auditor::before;
    00202   using Auditor::after;
    00203
    00204  private:
    00205   void i_beforeInitialize(INamedInterface* alg);
    00206   void i_afterInitialize(INamedInterface* alg);
    00207   void i_beforeExecute(INamedInterface* alg);
    00208   void i_afterExecute(INamedInterface* alg);
    00209
    00210  public:
    00211   virtual StatusCode initialize();
    00212   virtual StatusCode finalize();
    00213   int is_nehalem() {
    00214 #ifdef __ICC
    00215 // Disable ICC remark #593: variable "x" was set but never used
    00216 #pragma warning(push)
    00217 #pragma warning(disable:593)
    00218 #endif
    00219     int a,b,c,d;
    00220     cpuid(1,a,b,c,d);
    00221     int sse4_2_mask = 1 << 20;
    00222     if(c & sse4_2_mask) return 1; else return 0;
    00223 #ifdef __ICC
    00224 #pragma warning(pop)
    00225 #endif
    00226   }
    00227
    00228  private:
    00229   PFMon &m_pfm;
    00230 /*
    00231   typedef void (*pfm_stop_t)(int);
    00232   pfm_stop_t pfm_stop;
    00233   typedef void (*pfm_self_stop_t)(int);
    00234   pfm_self_stop_t pfm_self_stop;
    00235
    00236   typedef os_err_t (*pfm_restart_t)(int);
    00237   pfm_restart_t pfm_restart;
    00238
    00239   //typedef int (*pfm_read_pmds_t)(int, pfarg_pmd_t*, int);
    00240   //pfm_read_pmds_t pfm_read_pmds;
    00241
    00242   typedef pfm_err_t (*pfm_initialize_t)();
    00243   pfm_initialize_t pfm_initialize;
    00244   typedef pfm_err_t (*pfm_find_full_event_t)(const char *, pfmlib_event_t *);
    00245   pfm_find_full_event_t pfm_find_full_event;
    00246   typedef pfm_err_t (*pfm_dispatch_events_t)(pfmlib_input_param_t *, void *, pfmlib_output_param_t *, void *);
    00247   pfm_dispatch_events_t pfm_dispatch_events;
    00248   typedef os_err_t (*pfm_create_context_t)(pfarg_ctx_t *, char *, void *, size_t);
    00249   pfm_create_context_t pfm_create_context;
    00250   typedef os_err_t (*pfm_write_pmcs_t)(int, pfarg_pmc_t *, int);
    00251   pfm_write_pmcs_t pfm_write_pmcs;
    00252   typedef os_err_t (*pfm_write_pmds_t)(int, pfarg_pmd_t *, int);
    00253   pfm_write_pmds_t pfm_write_pmds;
    00254   typedef os_err_t (*pfm_load_context_t)(int, pfarg_load_t *);
    00255   pfm_load_context_t pfm_load_context;
    00256   typedef os_err_t (*pfm_start_t)(int fd, pfarg_start_t *);
    00257   pfm_start_t pfm_start;
    00258   typedef char* (*pfm_strerror_t)(int);
    00259   pfm_strerror_t pfm_strerror;
    00260   typedef pfm_err_t (*pfm_set_options_t)(pfmlib_options_t *);
    00261   pfm_set_options_t pfm_set_options;
    00262   typedef pfm_err_t (*pfm_get_num_counters_t)(unsigned int *);
    00263   pfm_get_num_counters_t pfm_get_num_counters;
    00264 */
    00265
    00266
    00267  public:
    00268   PerfMonAuditor(const std::string& name, ISvcLocator* pSvc):     // standard constructor
    00269    Auditor(name, pSvc),
    00270    m_pfm(PFMon::instance()),
    00271    m_map(),
    00272    m_indent(0),
    00273    m_inEvent(false)
    00274   {
    00275 is_nehalem_ret = is_nehalem();
    00276 declareProperty("EVENT0", event_str[0]);
    00277 declareProperty("EVENT1", event_str[1]);
    00278 declareProperty("EVENT2", event_str[2]);
    00279 declareProperty("EVENT3", event_str[3]);
    00280 declareProperty("FAMILY", family);
    00281 declareProperty("PREFIX", prefix);
    00282 declareProperty("INV0", inv[0]);
    00283 declareProperty("INV1", inv[1]);
    00284 declareProperty("INV2", inv[2]);
    00285 declareProperty("INV3", inv[3]);
    00286 declareProperty("CMASK0", cmask[0]);
    00287 declareProperty("CMASK1", cmask[1]);
    00288 declareProperty("CMASK2", cmask[2]);
    00289 declareProperty("CMASK3", cmask[3]);
    00290 declareProperty("SP0", sp[0]);
    00291 declareProperty("SP1", sp[1]);
    00292 declareProperty("SP2", sp[2]);
    00293 declareProperty("SP3", sp[3]);
    00294 declareProperty("SAMPLE", sampling);
    00295 declareProperty("START_AT_EVENT", start_at_event);
    00296 declareProperty("IS_NEHALEM", is_nehalem_ret);
    00297
    00298 // MsgStream log(msgSvc(), name());
    00299
    00301 /*
    00302 // loading functions from PFM library
    00303   void* handle = dlopen("libpfm.so", RTLD_NOW);
    00304     if (!handle) {
    00305 //      log << MSG::ERROR << "Cannot open library: " << dlerror() << endmsg;
    00306     }
    00307   typedef void (*hello_t)();
    00308     hello_t hello = (hello_t) dlsym(handle, "hello");
    00309     if (!hello) {
    00310 //        log << MSG::ERROR << "Cannot load symbol 'hello': " << dlerror() << endmsg;
    00311         dlclose(handle);
    00312     }
    00313
    00314     pfm_start = (pfm_start_t) dlsym(handle, "pfm_start");
    00315     pfm_stop = (pfm_stop_t) dlsym(handle, "pfm_stop");
    00316     pfm_self_stop = (pfm_self_stop_t) dlsym(handle, "pfm_stop"); //it's the same
    00317     pfm_restart = (pfm_restart_t) dlsym(handle, "pfm_restart");
    00318     //pfm_read_pmds = (pfm_read_pmds_t) dlsym(handle, "pfm_read_pmds");
    00319     pfm_initialize = (pfm_initialize_t) dlsym(handle, "pfm_initialize");
    00320     pfm_find_full_event = (pfm_find_full_event_t) dlsym(handle, "pfm_find_full_event");
    00321     pfm_dispatch_events = (pfm_dispatch_events_t) dlsym(handle, "pfm_dispatch_events");
    00322     pfm_create_context = (pfm_create_context_t) dlsym(handle, "pfm_create_context");
    00323     pfm_write_pmcs = (pfm_write_pmcs_t) dlsym(handle, "pfm_write_pmcs");
    00324     pfm_write_pmds = (pfm_write_pmds_t) dlsym(handle, "pfm_write_pmds");
    00325     pfm_load_context = (pfm_load_context_t) dlsym(handle, "pfm_load_context");
    00326     pfm_strerror = (pfm_strerror_t) dlsym(handle, "pfm_strerror");
    00327     pfm_set_options = (pfm_set_options_t) dlsym(handle, "pfm_set_options");
    00328     pfm_get_num_counters = (pfm_get_num_counters_t) dlsym(handle, "pfm_get_num_counters");
    00329     // use it to do the calculation
    00330 //    log << MSG::INFO << "Calling hello..." << endmsg;
    00331 //    hello();
    00332
    00333     // close the library
    00334 //    log << MSG::INFO << "Closing library..." << endmsg;
    00335     dlclose(handle);
    00336 */
    00337
    00339
    00340   }
    00341
    00342   virtual ~PerfMonAuditor() {}                                    // virtual destructor
    00343
    00344  private:
    00345   PerfMonAuditor();                                               // the default constructor is disabled
    00346   PerfMonAuditor(const PerfMonAuditor&);                          // copy constructor is disabled
    00347   PerfMonAuditor& operator=(const PerfMonAuditor&);               // assignement operator is disabled
    00348
    00349  private:
    00350   typedef GaudiUtils::VectorMap<const INamedInterface*,int> Map;
    00351   Map m_map;
    00352   int m_indent;                                                   // indentation level
    00353   bool m_inEvent;                                                 // "In event" flag
    00354
    00355  private:
    00356     int is_nehalem_ret;
    00357
    00358     pfmlib_input_param_t inp;
    00359     pfmlib_output_param_t outp;
    00360     pfarg_ctx_t ctx;
    00361     pfarg_pmd_t pd[NUM_PMDS];
    00362     pfarg_pmc_t pc[NUM_PMCS];
    00363     pfarg_load_t load_arg;
    00364     int fd;
    00365     unsigned int i;
    00366     int ret;
    00367     void startpm();
    00368     void pausepm();
    00369     void stoppm();
    00370     void finalizepm();
    00371     std::string event_str[MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS];
    00372     std::string prefix;
    00373     std::string family;
    00374     char event_cstr[MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS][MAX_EVENT_NAME_LENGTH];
    00375     char prefix_cstr[MAX_PREFIX_NAME_LENGTH];
    00376     unsigned int ph_ev_count;
    00377     bool inv[MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS];
    00378     unsigned int cmask[MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS];
    00379     unsigned int start_at_event;
    00380     pfmlib_core_input_param_t params;
    00381     pfmlib_nhm_input_param_t nhm_params;
    00382     int used_counters_number;
    00383     bool nehalem;
    00384     bool westmere;
    00385     bool core;
    00386
    00387     bool sampling;
    00388     int detect_unavail_pmu_regs(int fd, pfmlib_regmask_t *r_pmcs, pfmlib_regmask_t *r_pmds);
    00389     int detect_unavail_pmcs(int fd, pfmlib_regmask_t *r_pmcs){return detect_unavail_pmu_regs(fd, r_pmcs, NULL);}
    00390     void pfm_bv_set(uint64_t *bv, uint16_t rnum){bv[rnum>>LBPL] |= 1UL << (rnum&(BPL-1));}
    00391     int pfm_bv_isset(uint64_t *bv, uint16_t rnum){return bv[rnum>>LBPL] & (1UL <<(rnum&(BPL-1))) ? 1 : 0;}
    00392     void pfm_bv_copy(uint64_t *d, uint64_t *j, uint16_t n){if(n<=BPL) *d = *j; else {memcpy(d, j, (n>>LBPL)*sizeof(uint64_t));}}
    00393     static void process_smpl_buf(pfm_dfl_smpl_hdr_t *hdr, size_t entry_size);
    00394     static void sigio_handler(int, struct siginfo *, struct sigcontext *); // dlopen ==>
    00395     //void sigio_handler(int, struct siginfo *, struct sigcontext *);
    00396     void start_smpl();
    00397     void stop_smpl();
    00398     void finalize_smpl();
    00399     pfm_dfl_smpl_arg_t buf_arg;
    00400     pfarg_load_t load_args;
    00401     void *buf_addr;
    00402     unsigned num_counters;
    00403     unsigned int max_pmd;
    00404     pfmlib_options_t pfmlib_options;
    00405
    00406
    00407   int level;
    00408
    00409   bool first_alg;
    00410   std::string first_alg_name;
    00411   bool event_count_reached;
    00412
    00413
    00414 };
    00415
    00416 void PerfMonAuditor::startpm()
    00417 {
    00418    MsgStream log(msgSvc(), name());
    00419    memset(&ctx,0, sizeof(ctx));
    00420    memset(&inp,0, sizeof(inp));
    00421    memset(&outp,0, sizeof(outp));
    00422    memset(pd, 0, sizeof(pd));
    00423    memset(pc, 0, sizeof(pc));
    00424    memset(&load_arg, 0, sizeof(load_arg));
    00425    memset(&params, 0, sizeof(params));
    00426    memset(&nhm_params, 0, sizeof(nhm_params));
    00427
    00428    for(int i=0; i<used_counters_number; i++)
    00429    {
    00430     ret = m_pfm.pfm_find_full_event(event_cstr[i], &inp.pfp_events[i]);
    00431     if(ret != PFMLIB_SUCCESS)
    00432     {
    00433      log << MSG::ERROR << "ERROR: cannot find event: " << event_cstr[i] << ". Aborting..." << endmsg;
    00434     }
    00435    }
    00436    inp.pfp_dfl_plm = PFM_PLM3;
    00437    inp.pfp_event_count = 4;
    00438    for(int i=0; i<used_counters_number; i++)
    00439    {
    00440     if(inv[i])
    00441     {
    00442      (params.pfp_core_counters[i]).flags |= PFM_CORE_SEL_INV;
    00443      (nhm_params.pfp_nhm_counters[i]).flags |= PFM_NHM_SEL_INV;
    00444     }
    00445     if(cmask[i]>0)
    00446     {
    00447      (params.pfp_core_counters[i]).cnt_mask = cmask[i];
    00448      (nhm_params.pfp_nhm_counters[i]).cnt_mask = cmask[i];
    00449     }
    00450    }
    00451    if(nehalem || westmere)
    00452    {
    00453     ret = m_pfm.pfm_dispatch_events(&inp, &nhm_params, &outp, NULL);
    00454    }
    00455    else
    00456    {
    00457     ret = m_pfm.pfm_dispatch_events(&inp, &params, &outp, NULL);
    00458    }
    00459    if(ret != PFMLIB_SUCCESS)
    00460    {
    00461     log << MSG::ERROR << "ERROR: cannot dispatch events: " << m_pfm.pfm_strerror(ret) << ". Aborting..." << endmsg;
    00462    }
    00463    for(unsigned int i=0; i<outp.pfp_pmc_count; i++)
    00464    {
    00465     pc[i].reg_num = outp.pfp_pmcs[i].reg_num;
    00466     pc[i].reg_value = outp.pfp_pmcs[i].reg_value;
    00467    }
    00468    for(unsigned int i=0; i<outp.pfp_pmd_count; i++)
    00469    {
    00470     pd[i].reg_num = outp.pfp_pmds[i].reg_num;
    00471     pd[i].reg_value = 0;
    00472    }
    00473    fd = m_pfm.pfm_create_context(&ctx, NULL, 0, 0);
    00474    if(fd == -1)
    00475    {
    00476     log << MSG::ERROR << "ERROR: Context not created. Aborting..." << endmsg;
    00477    }
    00478    if(m_pfm.pfm_write_pmcs(fd, pc, outp.pfp_pmc_count) == -1)
    00479    {
    00480     log << MSG::ERROR << "ERROR: Could not write pmcs. Aborting..." << endmsg;
    00481    }
    00482    if(m_pfm.pfm_write_pmds(fd, pd, outp.pfp_pmd_count) == -1)
    00483    {
    00484     log << MSG::ERROR << "ERROR: Could not write pmds. Aborting..." << endmsg;
    00485    }
    00486    load_arg.load_pid = getpid();
    00487    if(m_pfm.pfm_load_context(fd, &load_arg) == -1)
    00488    {
    00489     log << MSG::ERROR << "ERROR: Could not load context. Aborting..." << endmsg;
    00490 //  MsgStream log(msgSvc(), name());
    00491 //  log << MSG::ERROR << "Could not read pmds" << endmsg;
    00492    }
    00493
    00494    m_pfm.pfm_start(fd, NULL);
    00495 }
    00496
    00497
    00498
    00499
    00500
    00501    // stoppm()
    00502    // const ModuleDescription& desc : description of the module that just finished its execution (we are only interested in its name)
    00503    // stops the counting calling pfm_stop() and stores the counting results into the "results" map
    00504 void PerfMonAuditor::stoppm()
    00505 {
    00506  MsgStream log(msgSvc(), name());
    00507  m_pfm.pfm_stop(fd);
    00508  if(m_pfm.pfm_read_pmds(fd, pd, inp.pfp_event_count) == -1)
    00509  {
    00510   log << MSG::ERROR << "Could not read pmds" << endmsg;
    00511  }
    00512    for(int i=0; i<used_counters_number; i++)
    00513    {
    00514  results[i][(alg_stack.top().first)->name()].push_back(alg_stack.top().second[i] + pd[i].reg_value);
    00515    }
    00516
    00517  close(fd);
    00518 }
    00519
    00520
    00521 void PerfMonAuditor::pausepm()
    00522 {
    00523  MsgStream log(msgSvc(), name());
    00524  m_pfm.pfm_stop(fd);
    00525  if(m_pfm.pfm_read_pmds(fd, pd, inp.pfp_event_count) == -1)
    00526  {
    00527   log << MSG::ERROR << "Could not read pmds" << endmsg;
    00528  }
    00529
    00530    for(int i=0; i<used_counters_number; i++)
    00531    {
    00532  alg_stack.top().second[i] += pd[i].reg_value;
    00533    }
    00534
    00535  close(fd);
    00536 }
    00537
    00538
    00539    // finalizepm()
    00540    // called when all the countings of the current event are finished, it dumps the results
    00541    // into the output file corresponding to the event being counted
    00542 void PerfMonAuditor::finalizepm()
    00543 {
    00544  MsgStream log(msgSvc(), name());
    00545    log << MSG::INFO << "start of finalizepm ucn:" << used_counters_number << endmsg;
    00546    char filename[MAX_OUTPUT_FILENAME_LENGTH];
    00547    char to_cat[50];
    00548    FILE *outfile;
    00549    for(int i=0; i<used_counters_number; i++)
    00550    {
    00551     bzero(filename, MAX_OUTPUT_FILENAME_LENGTH);
    00552     sprintf(filename, "%s_%s", prefix_cstr, event_cstr[i]);
    00553     for(int j=0; j<(int)strlen(filename); j++)
    00554     {
    00555      if(filename[j]==':')
    00556      {
    00557       filename[j]='-';
    00558      }
    00559     }
    00560     bzero(to_cat, 50);
    00561     if(inv[i])
    00562     {
    00563      strcpy(to_cat, "_INV_1");
    00564     }
    00565     if(cmask[i]>0)
    00566     {
    00567      sprintf(to_cat, "%s_CMASK_%d", to_cat, cmask[i]);
    00568     }
    00569     sprintf(filename, "%s%s.txt", filename, to_cat);
    00570     log << MSG::INFO << "Filename:" << filename << endmsg;
    00571     outfile = fopen(filename, "w");
    00572     if(nehalem)
    00573     {
    00574      fprintf(outfile, "NHM ");
    00575     }
    00576     else if(westmere)
    00577     {
    00578      fprintf(outfile, "WSM ");
    00579     }
    00580     else if(core)
    00581     {
    00582      fprintf(outfile, "CORE ");
    00583     }
    00584     fprintf(outfile, "%s %d %d %d\n", event_cstr[i], cmask[i], inv[i], sp[i]);
    00585     for(std::map<std::string, std::vector<unsigned long int> >::iterator it=(results[i]).begin(); it!=(results[i]).end(); it++)
    00586     {
    00587      fprintf(outfile, "%s\n", (it->first).c_str());
    00588      for(std::vector<unsigned long int>::iterator j=(it->second).begin(); j!=(it->second).end(); j++)
    00589      {
    00590       fprintf(outfile, "%lu\n", *j);
    00591      }
    00592     }
    00593     fclose(outfile);
    00594    }
    00595 }
    00596
    00597 StatusCode PerfMonAuditor::initialize()
    00598 {
    00599  MsgStream log(msgSvc(), name());
    00600
    00601  if (!m_pfm.loaded) {
    00602   log << MSG::ERROR << "pfm library could not be loaded" << endmsg;
    00603   return false;
    00604  }
    00605
    00606  log << MSG::INFO << "Initializing..." << endmsg;
    00607  StatusCode sc = Auditor::initialize() ;
    00608  if(sc.isFailure())
    00609  {
    00610   return sc;
    00611  }
    00612    used_counters_number = 0;
    00613    for(int i=0; i<MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS; i++)
    00614    {
    00615     if(event_str[i].length()>0) used_counters_number++;
    00616    }
    00617    for(int i=0; i<MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS; i++)
    00618    {
    00619     strcpy(event_cstr[i], event_str[i].c_str());
    00620    }
    00621    strcpy(prefix_cstr, prefix.c_str());
    00622
    00623  if(m_pfm.pfm_initialize() != PFMLIB_SUCCESS)
    00624  {
    00625  log << MSG::ERROR << "Cannot initialize perfmon!!" << endmsg;
    00626  }
    00627  ph_ev_count = 0;
    00628  first_alg = true;
    00629  event_count_reached = false;
    00630  nehalem = false;
    00631  core = false;
    00632  westmere = false;
    00633  if(family.compare("CORE")==0) core = true;
    00634  else if(family.compare("NEHALEM")==0) nehalem = true;
    00635  else if(family.compare("WESTMERE")==0) westmere = true;
    00636  else
    00637  {
    00638   log << MSG::ERROR << "ERROR: Unsupported processor family " << family  << ". aborting..." << endmsg;
    00639  }
    00640
    00641  log << MSG::INFO << "Initialized!" << endmsg;
    00642  return StatusCode::SUCCESS ;
    00643 }
    00644
    00645    // process_smpl_buf()
    00646    // pfm_dfl_smpl_hdr_t *hdr : pointer to header of the buffer containing addresses sampled during the sampling process
    00647    // size_t entry_size       : size of each entry, used to navigate through the various entries
    00648    // called when the sampling buffer is full, saves the samples into memory ("samples" map)
    00649 void PerfMonAuditor::process_smpl_buf(pfm_dfl_smpl_hdr_t *hdr, size_t entry_size)
    00650 {
    00652    pfm_dfl_smpl_entry_t *ent;
    00653    size_t pos, count;
    00654    uint64_t entry;
    00655    if(hdr->hdr_overflows == last_overflow && hdr->hdr_count == last_count)
    00656    {
    00657     printf("skipping identical set of samples...\n");
    00658     return;
    00659    }
    00660    count = hdr->hdr_count;
    00661    ent = (pfm_dfl_smpl_entry_t *)(hdr+1);
    00662    pos = (unsigned long)ent;
    00663    entry = collected_samples;
    00664    while(count--)
    00665    {
    00666     //if(ent->ovfl_pmd>=0 && ent->ovfl_pmd<=3)
    00667     if(ent->ovfl_pmd<=3)
    00668     {
    00669      ((samples[ent->ovfl_pmd])[(alg_stack.top().first)->name()])[(unsigned long)(ent->ip)]++;
    00670     }
    00671     pos += entry_size;
    00672     ent = (pfm_dfl_smpl_entry_t *)pos;
    00673     entry++;
    00674    }
    00675    collected_samples = entry;
    00676    last_overflow = hdr->hdr_overflows;
    00677    if (last_count != hdr->hdr_count && (last_count || last_overflow == 0))
    00678    {
    00679     collected_partial += hdr->hdr_count;
    00680    }
    00681    last_count = hdr->hdr_count;
    00682  return;
    00683 }
    00684
    00685    // sigio_handler()
    00686    // int n                 : signal number of the signal being delivered
    00687    // struct siginfo *info  : pointer to a siginfo_t structure containing info about the signal
    00688    // struct sigcontext *sc : context of the signal, NULL in our case
    00689    // signal handler used to catch sampling buffer overflows. When they occur it calls the process_smpl_buf() function
    00690 void PerfMonAuditor::sigio_handler(int /*n*/, struct siginfo */*info*/, struct sigcontext */*sc*/)
    00691 {
    00692    //MsgStream log(msgSvc(), name());
    00693    PFMon& pfm = PFMon::instance();
    00694    pfarg_msg_t msg;
    00695    int fd = ctx_fd;
    00696    int r;
    00697    if(fd != ctx_fd)
    00698    {
    00699     //log << MSG::ERROR << "ERROR: handler does not get valid file descriptor. Aborting..." << endmsg;
    00700    }
    00701    if(pfm.pfm_read_pmds(fd, pd_smpl+1, 1) == -1)
    00702    {
    00703     //log << MSG::ERROR << "ERROR: pfm_read_pmds: " << strerror(errno) << ". Aborting..." << endmsg;
    00704    }
    00705    while(true)
    00706    {
    00707     r = read(fd, &msg, sizeof(msg));
    00708     if(r!=sizeof(msg))
    00709     {
    00710      if(r==-1 && errno==EINTR)
    00711      {
    00712       printf("read interrupted, retrying\n");
    00713       continue;
    00714      }
    00715      //log << MSG::ERROR << "ERROR: cannot read overflow message: " << strerror(errno) << ". Aborting..." << endmsg;
    00716     }
    00717     break;
    00718    }
    00719    switch(msg.type)
    00720    {
    00721     case PFM_MSG_OVFL: // the sampling buffer is full
    00722      process_smpl_buf(hdr, entry_size);
    00723      ovfl_count++;
    00724      if(pfm.pfm_restart(fd))
    00725      {
    00726       if(errno!=EBUSY)
    00727       {
    00728        //log << MSG::ERROR << "ERROR: pfm_restart error errno " << errno << ". Aborting..." << endmsg;
    00729       }
    00730       else
    00731       {
    00732        printf("pfm_restart: task probably terminated \n");
    00733       }
    00734      }
    00735      break;
    00736     default:
    00737      //log << MSG::ERROR << "ERROR: unknown message type " << msg.type << ". Aborting..." << endmsg;
    00738      break;
    00739    }
    00740
    00741 }
    00742
    00743
    00744
    00745
    00746
    00747
    00748
    00749    // start_smpl()
    00750    // const ModuleDescription& desc : description of the module that is just starting its execution (we are only interested in its name)
    00751    // initializes all the necessary structures to start the sampling, calling pfm_self_start()
    00752 void PerfMonAuditor::start_smpl()
    00753 {
    00754    MsgStream log(msgSvc(), name());
    00755    ovfl_count = 0;
    00756    num_smpl_pmds = 0;
    00757    last_overflow = ~0;
    00758    max_pmd = 0;
    00759    memset(&pfmlib_options, 0, sizeof(pfmlib_options));
    00760    pfmlib_options.pfm_debug   = 0;
    00761    pfmlib_options.pfm_verbose = 0;
    00762    m_pfm.pfm_set_options(&pfmlib_options);
    00763    ret = m_pfm.pfm_initialize();
    00764    if(ret != PFMLIB_SUCCESS)
    00765    {
    00766     log << MSG::ERROR << "ERROR: Cannot initialize library: " << m_pfm.pfm_strerror(ret) << ". Aborting..." << endmsg;
    00767    }
    00768    struct sigaction act;
    00769    memset(&act, 0, sizeof(act));
    00770    act.sa_handler = (sig_t)sigio_handler; // dlopen() ==>
    00771    //act.sa_handler = (sig_t)&sigio_handler;
    00772    sigaction(SIGIO, &act, 0);
    00773    memset(&ctx, 0, sizeof(ctx));
    00774    memset(&buf_arg, 0, sizeof(buf_arg));
    00775    memset(&inp,0, sizeof(inp));
    00776    memset(&outp,0, sizeof(outp));
    00777    memset(pd_smpl, 0, sizeof(pd_smpl));
    00778    memset(pc, 0, sizeof(pc));
    00779    memset(&load_args, 0, sizeof(load_args));
    00780    m_pfm.pfm_get_num_counters(&num_counters);
    00781    memset(&params, 0, sizeof(params));
    00782    memset(&nhm_params, 0, sizeof(nhm_params));
    00783
    00784    for(int i=0; i<used_counters_number; i++)
    00785    {
    00786     ret = m_pfm.pfm_find_full_event(event_cstr[i], &inp.pfp_events[i]);
    00787     if(ret != PFMLIB_SUCCESS)
    00788     {
    00789      log << MSG::ERROR << "ERROR: cannot find event: " << event_cstr[i] << ". Aborting..." << endmsg;
    00790     }
    00791    }
    00792    inp.pfp_dfl_plm = PFM_PLM3;
    00793    inp.pfp_event_count = 4;
    00794    for(int i=0; i<used_counters_number; i++)
    00795    {
    00796     if(inv[i])
    00797     {
    00798      (params.pfp_core_counters[i]).flags |= PFM_CORE_SEL_INV;
    00799      (nhm_params.pfp_nhm_counters[i]).flags |= PFM_NHM_SEL_INV;
    00800     }
    00801     if(cmask[i]>0)
    00802     {
    00803      (params.pfp_core_counters[i]).cnt_mask = cmask[i];
    00804      (nhm_params.pfp_nhm_counters[i]).cnt_mask = cmask[i];
    00805     }
    00806    }
    00807    if(nehalem || westmere)
    00808    {
    00809     ret = m_pfm.pfm_dispatch_events(&inp, &nhm_params, &outp, NULL);
    00810    }
    00811    else
    00812    {
    00813     ret = m_pfm.pfm_dispatch_events(&inp, &params, &outp, NULL);
    00814    }
    00815    if(ret != PFMLIB_SUCCESS)
    00816    {
    00817     log << MSG::ERROR << "ERROR: cannot configure events: " << m_pfm.pfm_strerror(ret) << ". Aborting..." << endmsg;
    00818    }
    00819    for(unsigned int i=0; i<outp.pfp_pmc_count; i++)
    00820    {
    00821     pc[i].reg_num   = outp.pfp_pmcs[i].reg_num;
    00822     pc[i].reg_value = outp.pfp_pmcs[i].reg_value;
    00823    }
    00824    for(unsigned int i=0; i<outp.pfp_pmd_count; i++)
    00825    {
    00826     pd_smpl[i].reg_num = outp.pfp_pmds[i].reg_num;
    00827     if(i)
    00828     {
    00829      pfm_bv_set(pd_smpl[0].reg_smpl_pmds, pd_smpl[i].reg_num);
    00830      if(pd_smpl[i].reg_num>max_pmd)
    00831      {
    00832       max_pmd = pd_smpl[i].reg_num;
    00833      }
    00834      num_smpl_pmds++;
    00835     }
    00836    }
    00837    for(int i=0; i<used_counters_number; i++)
    00838    {
    00839     pd_smpl[i].reg_flags |= PFM_REGFL_OVFL_NOTIFY | PFM_REGFL_RANDOM;
    00840     pfm_bv_copy(pd_smpl[i].reg_reset_pmds, pd_smpl[i].reg_smpl_pmds, max_pmd);
    00841     pd_smpl[i].reg_value = (uint64_t)(sp[i] * -1);
    00842     pd_smpl[i].reg_short_reset = (uint64_t)(sp[i] * -1);
    00843     pd_smpl[i].reg_long_reset = (uint64_t)(sp[i] * -1);
    00844     pd_smpl[i].reg_random_seed = 5; //tocheck
    00845     pd_smpl[i].reg_random_mask = 0xff; //tocheck
    00846    }
    00847    entry_size = sizeof(pfm_dfl_smpl_entry_t)+(num_smpl_pmds<<3);
    00848    ctx.ctx_flags = 0;
    00849    buf_arg.buf_size = 3*getpagesize()+512;
    00850    ctx_fd = m_pfm.pfm_create_context(&ctx, (char *)FMT_NAME, &buf_arg, sizeof(buf_arg));
    00851    if(ctx_fd==-1)
    00852    {
    00853     if(errno==ENOSYS)
    00854     {
    00855      log << MSG::ERROR << "ERROR: Your kernel does not have performance monitoring support! Aborting..." << endmsg;
    00856     }
    00857     log << MSG::ERROR << "ERROR: Can't create PFM context " << strerror(errno) << ". Aborting..." << endmsg;
    00858    }
    00859    buf_addr = mmap(NULL, (size_t)buf_arg.buf_size, PROT_READ, MAP_PRIVATE, ctx_fd, 0);
    00860    if(buf_addr==MAP_FAILED)
    00861    {
    00862     log << MSG::ERROR << "ERROR: cannot mmap sampling buffer: " << strerror(errno) << ". Aborting..." << endmsg;
    00863    }
    00864    hdr = (pfm_dfl_smpl_hdr_t *)buf_addr;
    00865    if(PFM_VERSION_MAJOR(hdr->hdr_version)<1)
    00866    {
    00867     log << MSG::ERROR << "ERROR: invalid buffer format version. Aborting..." << endmsg;
    00868    }
    00869    if(m_pfm.pfm_write_pmcs(ctx_fd, pc, outp.pfp_pmc_count))
    00870    {
    00871     log << MSG::ERROR << "ERROR: pfm_write_pmcs error errno " << strerror(errno) << ". Aborting..." << endmsg;
    00872    }
    00873    if(m_pfm.pfm_write_pmds(ctx_fd, pd_smpl, outp.pfp_pmd_count))
    00874    {
    00875     log << MSG::ERROR << "ERROR: pfm_write_pmds error errno " << strerror(errno) << ". Aborting..." << endmsg;
    00876    }
    00877    load_args.load_pid = getpid();
    00878    if(m_pfm.pfm_load_context(ctx_fd, &load_args))
    00879    {
    00880     log << MSG::ERROR << "ERROR: pfm_load_context error errno " << strerror(errno) << ". Aborting..." << endmsg;
    00881    }
    00882    ret = fcntl(ctx_fd, F_SETFL, fcntl(ctx_fd, F_GETFL, 0) | O_ASYNC);
    00883    if(ret == -1)
    00884    {
    00885     log << MSG::ERROR << "ERROR: cannot set ASYNC: " << strerror(errno) << ". Aborting..." << endmsg;
    00886    }
    00887    ret = fcntl(ctx_fd, F_SETOWN, getpid());
    00888    if(ret == -1)
    00889    {
    00890     log << MSG::ERROR << "ERROR: cannot setown: " << strerror(errno) << ". Aborting..." << endmsg;
    00891    }
    00892    //pfm_self_start(ctx_fd); ==>
    00893    m_pfm.pfm_start(ctx_fd, NULL);
    00894   }
    00895
    00896
    00897    // stop_smpl()
    00898    // const ModuleDescription& desc : description of the module that just finished its execution (we are only interested in its name)
    00899    // stops the sampling and calls process_smpl_buf() one last time to process all the remaining samples
    00900 void PerfMonAuditor::stop_smpl()
    00901   {
    00902  MsgStream log(msgSvc(), name());
    00903    m_pfm.pfm_self_stop(ctx_fd);
    00904    process_smpl_buf(hdr, entry_size);
    00905    close(ctx_fd);
    00906    ret = munmap(hdr, (size_t)buf_arg.buf_size);
    00907    if(ret)
    00908    {
    00909   log << MSG::ERROR << "Cannot unmap buffer: %s" << strerror(errno) << endmsg;
    00910    }
    00911    return;
    00912   }
    00913
    00914
    00915
    00916    // finalize_smpl()
    00917    // processes the sampling results in order to find library and offset of each sampled address, using the symbol() and tosymbol() functions,
    00918    // and then dumps the new found information into gzipped output files, to be processed later
    00919 void PerfMonAuditor::finalize_smpl()
    00920 {
    00921    MsgStream log(msgSvc(), name());
    00922    char filename[MAX_OUTPUT_FILENAME_LENGTH];
    00923    bzero(filename, MAX_OUTPUT_FILENAME_LENGTH);
    00924    char to_cat[50];
    00925    gzFile outfile;
    00926    int err;
    00927    for(int i=0; i<used_counters_number; i++)
    00928    {
    00929     sprintf(filename, "%s_%s", prefix_cstr, event_cstr[i]);
    00930     for(int j=0; j<(int)strlen(filename); j++)
    00931     {
    00932      if(filename[j]==':')
    00933      {
    00934       filename[j]='-';
    00935      }
    00936     }
    00937     bzero(to_cat, 50);
    00938     if(inv[i])
    00939     {
    00940      strcpy(to_cat, "_INV_1");
    00941     }
    00942     if(cmask[i]>0)
    00943     {
    00944      sprintf(to_cat, "%s_CMASK_%d", to_cat, cmask[i]);
    00945     }
    00946     sprintf(filename, "%s%s.txt.gz", filename, to_cat);
    00947     outfile = gzopen(filename, "wb");
    00948     if(outfile!=NULL)
    00949     {
    00950      if(nehalem)
    00951      {
    00952       gzprintf(outfile, "NHM ");
    00953      }
    00954      else if(westmere)
    00955      {
    00956       gzprintf(outfile, "WSM ");
    00957      }
    00958      else if(core)
    00959      {
    00960       gzprintf(outfile, "CORE ");
    00961      }
    00962      if(gzprintf(outfile, "%s %d %d %d\n", event_cstr[i], cmask[i], inv[i], sp[i]) < (int)strlen(event_cstr[i]))
    00963      {
    00964       log << MSG::ERROR << "ERROR: gzputs err: " << gzerror(outfile, &err) << ". Aborting..." << endmsg;
    00965      }
    00966      for(std::map<std::string, std::map<unsigned long, unsigned int> >::iterator it=samples[i].begin(); it!=samples[i].end(); it++)
    00967      {
    00968       unsigned long long sum = 0;
    00969       for(std::map<unsigned long, unsigned int>::iterator jt=(it->second).begin(); jt!=(it->second).end(); jt++)
    00970       {
    00971        sum += jt->second;
    00972       }
    00973       if(gzprintf(outfile, "%s%%%llu\n", (it->first).c_str(), sum) < (int)((it->first).length()))
    00974       {
    00975        log << MSG::ERROR << "ERROR: gzputs err: " << gzerror(outfile, &err) << ". Aborting..." << endmsg;
    00976       }
    00977       for(std::map<unsigned long, unsigned int>::iterator jt=(it->second).begin(); jt!=(it->second).end(); jt++)
    00978       {
    00979        char sym_name[SYM_NAME_MAX_LENGTH];
    00980        bzero(sym_name, SYM_NAME_MAX_LENGTH);
    00981        const char *libName;
    00982        const char *symbolName;
    00983        int libOffset = 0;
    00984        int offset = 0;
    00985        void *sym_addr = IgHookTrace::tosymbol((void *)(jt->first));
    00986        if(sym_addr != NULL)
    00987        {
    00988         bool success = IgHookTrace::symbol(sym_addr, symbolName, libName, offset, libOffset);
    00989         if(success)
    00990         {
    00991          if(symbolName!=NULL && strlen(symbolName)>0)
    00992          {
    00993           strcpy(sym_name, symbolName);
    00994           strcat(sym_name, " ");
    00995          }
    00996          else
    00997          {
    00998           strcpy(sym_name, "??? ");
    00999          }
    01000          if(libName!=NULL && strlen(libName)>0)
    01001          {
    01002           strcat(sym_name, libName);
    01003           strcat(sym_name, " ");
    01004          }
    01005          else
    01006          {
    01007           strcat(sym_name, "??? ");
    01008          }
    01009          sprintf(sym_name, "%s%d ", sym_name, libOffset);
    01010          if(strlen(sym_name)<=0)
    01011          {
    01012           log << MSG::ERROR << "ERROR: Symbol name length is zero. Aborting..." << endmsg;
    01013          }
    01014         }
    01015         else
    01016         {
    01017          strcpy(sym_name,"??? ??? 0 ");
    01018         }
    01019        }
    01020        else
    01021        {
    01022         strcpy(sym_name,"??? ??? 0 ");
    01023        }
    01024        if(gzprintf(outfile, "%s %d\n", sym_name, jt->second) < (int)strlen(sym_name))
    01025        {
    01026         log << MSG::ERROR << "ERROR: gzputs err: " << gzerror(outfile, &err) << endmsg;
    01027        }
    01028       }
    01029      }
    01030     }
    01031     else
    01032     {
    01033      log << MSG::ERROR << "ERROR: Could not open file: " << filename << ". Aborting..." << endmsg;
    01034     }
    01035     gzclose(outfile);
    01036    }
    01037   }
    01038
    01039
    01040
    01041 StatusCode PerfMonAuditor::finalize()
    01042 {
    01043  if(sampling == 0) finalizepm();
    01044  else finalize_smpl();
    01045  return Auditor::finalize();
    01046 }
    01047
    01048
    01049 void PerfMonAuditor::before(StandardEventType evt, INamedInterface *alg)
    01050 {
    01051  switch(evt)
    01052  {
    01053   case IAuditor::Initialize:
    01054    i_beforeInitialize(alg);
    01055    break;
    01056   case IAuditor::Execute:
    01057    i_beforeExecute(alg);
    01058    break;
    01059   default:
    01060    break;
    01061  }
    01062  return;
    01063 }
    01064
    01065 void PerfMonAuditor::after(StandardEventType evt, INamedInterface *alg, const StatusCode &)
    01066 {
    01067  switch(evt)
    01068  {
    01069   case IAuditor::Initialize:
    01070    i_afterInitialize(alg);
    01071    break;
    01072   case IAuditor::Execute:
    01073    i_afterExecute(alg);
    01074    break;
    01075   default:
    01076    break;
    01077  }
    01078  return;
    01079 }
    01080
    01081 void PerfMonAuditor::i_beforeInitialize(INamedInterface* alg)
    01082 {
    01083  if(alg == 0)
    01084  {
    01085   return;
    01086  }
    01087  return;
    01088 }
    01089
    01090 void PerfMonAuditor::i_afterInitialize(INamedInterface* alg)
    01091 {
    01092  if(alg == 0)
    01093  {
    01094   return;
    01095  }
    01096  return;
    01097 }
    01098
    01099 void PerfMonAuditor::i_beforeExecute(INamedInterface* alg)
    01100 {
    01101  MsgStream log(msgSvc(), name());
    01102  if(alg == 0)
    01103  {
    01104   return;
    01105  }
    01106  //log << MSG::INFO << "before:inside! " << alg->name() << endmsg;
    01107  if(first_alg)
    01108  {
    01109   first_alg = false;
    01110   first_alg_name = alg->name();
    01111   //log << MSG::INFO << "first_alg_name= " << alg->name() << endmsg;
    01112  }
    01113  if(!event_count_reached)
    01114  {
    01115   if(!first_alg_name.compare(alg->name()))
    01116   {
    01117    ph_ev_count++;
    01118    //log << MSG::INFO << "EVENT COUNT: " << ph_ev_count << endmsg;
    01119    if(ph_ev_count==start_at_event)
    01120    {
    01121     event_count_reached = true;
    01122     //log << MSG::INFO << "!!! EVENT COUNT REACHED: " << ph_ev_count << endmsg;
    01123    }
    01124   }
    01125  }
    01126  if(event_count_reached)
    01127  {
    01128    //log << MSG::INFO << "before:inside! " << alg->name() << endmsg;
    01129
    01130   if(!alg_stack.empty())
    01131   {
    01132    if(sampling == 0) pausepm(); //pausing father algorithm counting
    01133    else stop_smpl();
    01134   }
    01135   ++m_indent;
    01136   std::vector <unsigned long int> zeroes(4,0);
    01137   alg_stack.push(std::make_pair(alg, zeroes));
    01138   if(sampling == 0) startpm();
    01139   else start_smpl();
    01140  }
    01141  return;
    01142 }
    01143
    01144 void PerfMonAuditor::i_afterExecute(INamedInterface* alg)
    01145 {
    01146  MsgStream log(msgSvc(), name());
    01147  if(alg == 0)
    01148  {
    01149   return;
    01150  }// log << MSG::INFO << "after:inside! " << alg->name() << endmsg;
    01151
    01152  if(event_count_reached)
    01153  {
    01154    //log << MSG::INFO << "after:inside! " << alg->name() << endmsg;
    01155
    01156   if(sampling == 0) stoppm();
    01157   else stop_smpl();
    01158   alg_stack.pop();
    01159   --m_indent;
    01160   if(!alg_stack.empty())
    01161   {
    01162    if(sampling == 0) startpm();
    01163    else start_smpl(); //resuming father algorithm counting
    01164    }
    01165  }
    01166  return;
    01167 }
    01168
    01169 DECLARE_AUDITOR_FACTORY(PerfMonAuditor)

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines