The Gaudi Framework  v30r3 (a5ef0a68)
PerfMonAuditor.cpp
Go to the documentation of this file.
1 #include "GaudiKernel/Auditor.h"
2 #include "GaudiKernel/HashMap.h"
5 #include "GaudiKernel/IToolSvc.h"
8 
9 /*BEGIN: perfmon*/
10 #include <cstring>
11 #include <fstream>
12 #include <iostream>
13 #include <map>
14 #include <perfmon/pfmlib.h>
15 #include <perfmon/pfmlib_core.h>
17 #include <sstream>
18 #include <string>
19 #include <utility>
20 #include <vector>
21 
22 #include <perfmon/perfmon.h>
24 
26 
28 
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <getopt.h>
32 #include <signal.h>
33 #include <stdarg.h>
34 #include <stdint.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <sys/mman.h>
39 #include <sys/ptrace.h>
40 #include <sys/resource.h>
41 #include <sys/time.h>
42 #include <sys/types.h>
43 #include <sys/wait.h>
44 #include <time.h>
45 #include <unistd.h>
46 #include <zlib.h>
47 
48 #include "IgHook_IgHookTrace.h"
49 #include <algorithm>
50 #include <cmath>
51 #include <list>
52 #include <stack>
53 #include <sys/stat.h>
54 
55 // dlopen (link with -ldl)
56 #include <dlfcn.h>
57 
58 #define MAX_EVT_NAME_LEN 256
59 #define NUM_PMCS PFMLIB_MAX_PMCS
60 #define NUM_PMDS PFMLIB_MAX_PMDS
61 #define FMT_NAME PFM_DFL_SMPL_NAME
62 #define BPL ( sizeof( uint64_t ) << 3 )
63 #define LBPL 6
64 
65 #define SYM_NAME_MAX_LENGTH 10000
66 #define MAX_OUTPUT_FILENAME_LENGTH 1024
67 #define MAX_EVENT_NAME_LENGTH 500
68 #define MAX_PREFIX_NAME_LENGTH 1024
69 #define FILENAME_MAX_LENGTH 1024
70 
71 #define MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS 4
72 
73 #define cpuid( func, ax, bx, cx, dx ) \
74  __asm__ __volatile__( "cpuid" : "=a"( ax ), "=b"( bx ), "=c"( cx ), "=d"( dx ) : "a"( func ) );
75 
76 static pfarg_pmd_t pd_smpl[NUM_PMDS];
77 static uint64_t collected_samples, collected_partial;
78 static int ctx_fd;
79 static pfm_dfl_smpl_hdr_t* hdr;
80 static uint64_t ovfl_count;
81 static size_t entry_size;
82 static unsigned int num_smpl_pmds;
84  MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS ); // a map of modules each containing numbers of samples of their addresses
86  results( MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS ); // a map of modules and their result values across multiple events
87 static uint64_t last_overflow;
88 static uint64_t last_count;
90 
92 /*END: perfmon*/
93 
94 namespace
95 {
97  template <typename T>
98  inline T function_cast( void* p )
99  {
100  union {
101  void* object;
102  T function;
103  } caster;
104  caster.object = p;
105  return caster.function;
106  }
107  class PFMon
108  {
109  public:
110  bool loaded;
111  typedef void ( *pfm_stop_t )( int );
112  pfm_stop_t pfm_stop;
113  typedef void ( *pfm_self_stop_t )( int );
114  pfm_self_stop_t pfm_self_stop;
115  typedef os_err_t ( *pfm_restart_t )( int );
116  pfm_restart_t pfm_restart;
117  typedef int ( *pfm_read_pmds_t )( int, pfarg_pmd_t*, int );
118  pfm_read_pmds_t pfm_read_pmds;
119  typedef pfm_err_t ( *pfm_initialize_t )();
120  pfm_initialize_t pfm_initialize;
121  typedef pfm_err_t ( *pfm_find_full_event_t )( const char*, pfmlib_event_t* );
122  pfm_find_full_event_t pfm_find_full_event;
123  typedef pfm_err_t ( *pfm_dispatch_events_t )( pfmlib_input_param_t*, void*, pfmlib_output_param_t*, void* );
124  pfm_dispatch_events_t pfm_dispatch_events;
125  typedef os_err_t ( *pfm_create_context_t )( pfarg_ctx_t*, char*, void*, size_t );
126  pfm_create_context_t pfm_create_context;
127  typedef os_err_t ( *pfm_write_pmcs_t )( int, pfarg_pmc_t*, int );
128  pfm_write_pmcs_t pfm_write_pmcs;
129  typedef os_err_t ( *pfm_write_pmds_t )( int, pfarg_pmd_t*, int );
130  pfm_write_pmds_t pfm_write_pmds;
131  typedef os_err_t ( *pfm_load_context_t )( int, pfarg_load_t* );
132  pfm_load_context_t pfm_load_context;
133  typedef os_err_t ( *pfm_start_t )( int fd, pfarg_start_t* );
134  pfm_start_t pfm_start;
135  typedef char* ( *pfm_strerror_t )( int );
136  pfm_strerror_t pfm_strerror;
137  typedef pfm_err_t ( *pfm_set_options_t )( pfmlib_options_t* );
138  pfm_set_options_t pfm_set_options;
139  typedef pfm_err_t ( *pfm_get_num_counters_t )( unsigned int* );
140  pfm_get_num_counters_t pfm_get_num_counters;
141  static PFMon& instance() { return s_instance; }
142 
143  private:
144  // static void failure() { throw 1; }
145 
146  void* handle;
147 
148  PFMon()
149  {
150  handle = dlopen( "libpfm.so", RTLD_NOW );
151  if ( handle ) {
152  loaded = true;
153  } else {
154  loaded = false;
155  }
156  if ( loaded ) {
157  pfm_start = function_cast<pfm_start_t>( dlsym( handle, "pfm_start" ) );
158  pfm_stop = function_cast<pfm_stop_t>( dlsym( handle, "pfm_stop" ) );
159  pfm_self_stop = function_cast<pfm_self_stop_t>( dlsym( handle, "pfm_stop" ) ); // it's the same
160  pfm_restart = function_cast<pfm_restart_t>( dlsym( handle, "pfm_restart" ) );
161  pfm_read_pmds = function_cast<pfm_read_pmds_t>( dlsym( handle, "pfm_read_pmds" ) );
162  pfm_initialize = function_cast<pfm_initialize_t>( dlsym( handle, "pfm_initialize" ) );
163  pfm_find_full_event = function_cast<pfm_find_full_event_t>( dlsym( handle, "pfm_find_full_event" ) );
164  pfm_dispatch_events = function_cast<pfm_dispatch_events_t>( dlsym( handle, "pfm_dispatch_events" ) );
165  pfm_create_context = function_cast<pfm_create_context_t>( dlsym( handle, "pfm_create_context" ) );
166  pfm_write_pmcs = function_cast<pfm_write_pmcs_t>( dlsym( handle, "pfm_write_pmcs" ) );
167  pfm_write_pmds = function_cast<pfm_write_pmds_t>( dlsym( handle, "pfm_write_pmds" ) );
168  pfm_load_context = function_cast<pfm_load_context_t>( dlsym( handle, "pfm_load_context" ) );
169  pfm_strerror = function_cast<pfm_strerror_t>( dlsym( handle, "pfm_strerror" ) );
170  pfm_set_options = function_cast<pfm_set_options_t>( dlsym( handle, "pfm_set_options" ) );
171  pfm_get_num_counters = function_cast<pfm_get_num_counters_t>( dlsym( handle, "pfm_get_num_counters" ) );
172  } else {
173  // pfm_start = pfm_stop = pfm_self_stop = pfm_restart = pfm_read_pmds = pfm_initialize = pfm_find_full_event =
174  // pfm_dispatch_events = pfm_create_context = pfm_write_pmcs = pfm_write_pmds = pfm_load_context = pfm_strerror
175  // = pfm_set_options = pfm_get_num_counters = failure;
176  }
177  }
178  ~PFMon()
179  {
180  if ( handle ) dlclose( handle );
181  }
182 
183  static PFMon s_instance;
184  };
185 
186  PFMon PFMon::s_instance;
187 }
188 
189 // ============================================================================
190 // GaudiAlg
191 // ============================================================================
192 // ============================================================================
202 class PerfMonAuditor : virtual public Auditor
203 {
204 public:
205  void before( StandardEventType evt, INamedInterface* alg ) override;
206  void after( StandardEventType evt, INamedInterface* alg, const StatusCode& sc ) override;
207  using Auditor::before;
208  using Auditor::after;
209 
210 private:
211  void i_beforeInitialize( INamedInterface* alg );
212  void i_afterInitialize( INamedInterface* alg );
213  void i_beforeExecute( INamedInterface* alg );
214  void i_afterExecute( INamedInterface* alg );
215 
216 public:
217  StatusCode initialize() override;
218  StatusCode finalize() override;
220  {
221 #ifdef __ICC
222 // Disable ICC remark #593: variable "x" was set but never used
223 #pragma warning( push )
224 #pragma warning( disable : 593 )
225 #endif
226  int a, b, c, d;
227  cpuid( 1, a, b, c, d );
228  int sse4_2_mask = 1 << 20;
229  if ( c & sse4_2_mask )
230  return 1;
231  else
232  return 0;
233 #ifdef __ICC
234 #pragma warning( pop )
235 #endif
236  }
237 
238 private:
239  PFMon& m_pfm;
240  /*
241  typedef void (*pfm_stop_t)(int);
242  pfm_stop_t pfm_stop;
243  typedef void (*pfm_self_stop_t)(int);
244  pfm_self_stop_t pfm_self_stop;
245 
246  typedef os_err_t (*pfm_restart_t)(int);
247  pfm_restart_t pfm_restart;
248 
249  //typedef int (*pfm_read_pmds_t)(int, pfarg_pmd_t*, int);
250  //pfm_read_pmds_t pfm_read_pmds;
251 
252  typedef pfm_err_t (*pfm_initialize_t)();
253  pfm_initialize_t pfm_initialize;
254  typedef pfm_err_t (*pfm_find_full_event_t)(const char *, pfmlib_event_t *);
255  pfm_find_full_event_t pfm_find_full_event;
256  typedef pfm_err_t (*pfm_dispatch_events_t)(pfmlib_input_param_t *, void *, pfmlib_output_param_t *, void *);
257  pfm_dispatch_events_t pfm_dispatch_events;
258  typedef os_err_t (*pfm_create_context_t)(pfarg_ctx_t *, char *, void *, size_t);
259  pfm_create_context_t pfm_create_context;
260  typedef os_err_t (*pfm_write_pmcs_t)(int, pfarg_pmc_t *, int);
261  pfm_write_pmcs_t pfm_write_pmcs;
262  typedef os_err_t (*pfm_write_pmds_t)(int, pfarg_pmd_t *, int);
263  pfm_write_pmds_t pfm_write_pmds;
264  typedef os_err_t (*pfm_load_context_t)(int, pfarg_load_t *);
265  pfm_load_context_t pfm_load_context;
266  typedef os_err_t (*pfm_start_t)(int fd, pfarg_start_t *);
267  pfm_start_t pfm_start;
268  typedef char* (*pfm_strerror_t)(int);
269  pfm_strerror_t pfm_strerror;
270  typedef pfm_err_t (*pfm_set_options_t)(pfmlib_options_t *);
271  pfm_set_options_t pfm_set_options;
272  typedef pfm_err_t (*pfm_get_num_counters_t)(unsigned int *);
273  pfm_get_num_counters_t pfm_get_num_counters;
274  */
275 
276 public:
278  : // standard constructor
279  Auditor( name, pSvc )
280  , m_pfm( PFMon::instance() )
281  , m_map()
282  , m_indent( 0 )
283  , m_inEvent( false )
284  {
285  is_nehalem_ret = is_nehalem();
286  declareProperty( "EVENT0", event_str[0] );
287  declareProperty( "EVENT1", event_str[1] );
288  declareProperty( "EVENT2", event_str[2] );
289  declareProperty( "EVENT3", event_str[3] );
290  declareProperty( "FAMILY", family );
291  declareProperty( "PREFIX", prefix );
292  declareProperty( "INV0", inv[0] );
293  declareProperty( "INV1", inv[1] );
294  declareProperty( "INV2", inv[2] );
295  declareProperty( "INV3", inv[3] );
296  declareProperty( "CMASK0", cmask[0] );
297  declareProperty( "CMASK1", cmask[1] );
298  declareProperty( "CMASK2", cmask[2] );
299  declareProperty( "CMASK3", cmask[3] );
300  declareProperty( "SP0", sp[0] );
301  declareProperty( "SP1", sp[1] );
302  declareProperty( "SP2", sp[2] );
303  declareProperty( "SP3", sp[3] );
304  declareProperty( "SAMPLE", sampling );
305  declareProperty( "START_AT_EVENT", start_at_event );
306  declareProperty( "IS_NEHALEM", is_nehalem_ret );
307 
309  /*
310  // loading functions from PFM library
311  void* handle = dlopen("libpfm.so", RTLD_NOW);
312  if (!handle) {
313  // error() << "Cannot open library: " << dlerror() << endmsg;
314  }
315  typedef void (*hello_t)();
316  hello_t hello = (hello_t) dlsym(handle, "hello");
317  if (!hello) {
318  // error() << "Cannot load symbol 'hello': " << dlerror() << endmsg;
319  dlclose(handle);
320  }
321 
322  pfm_start = (pfm_start_t) dlsym(handle, "pfm_start");
323  pfm_stop = (pfm_stop_t) dlsym(handle, "pfm_stop");
324  pfm_self_stop = (pfm_self_stop_t) dlsym(handle, "pfm_stop"); //it's the same
325  pfm_restart = (pfm_restart_t) dlsym(handle, "pfm_restart");
326  //pfm_read_pmds = (pfm_read_pmds_t) dlsym(handle, "pfm_read_pmds");
327  pfm_initialize = (pfm_initialize_t) dlsym(handle, "pfm_initialize");
328  pfm_find_full_event = (pfm_find_full_event_t) dlsym(handle, "pfm_find_full_event");
329  pfm_dispatch_events = (pfm_dispatch_events_t) dlsym(handle, "pfm_dispatch_events");
330  pfm_create_context = (pfm_create_context_t) dlsym(handle, "pfm_create_context");
331  pfm_write_pmcs = (pfm_write_pmcs_t) dlsym(handle, "pfm_write_pmcs");
332  pfm_write_pmds = (pfm_write_pmds_t) dlsym(handle, "pfm_write_pmds");
333  pfm_load_context = (pfm_load_context_t) dlsym(handle, "pfm_load_context");
334  pfm_strerror = (pfm_strerror_t) dlsym(handle, "pfm_strerror");
335  pfm_set_options = (pfm_set_options_t) dlsym(handle, "pfm_set_options");
336  pfm_get_num_counters = (pfm_get_num_counters_t) dlsym(handle, "pfm_get_num_counters");
337  // use it to do the calculation
338  // info() << "Calling hello..." << endmsg;
339  // hello();
340 
341  // close the library
342  // info() << "Closing library..." << endmsg;
343  dlclose(handle);
344  */
345 
347  }
348 
349  virtual ~PerfMonAuditor() {} // virtual destructor
350 
351 private:
352  PerfMonAuditor(); // the default constructor is disabled
353  PerfMonAuditor( const PerfMonAuditor& ); // copy constructor is disabled
354  PerfMonAuditor& operator=( const PerfMonAuditor& ); // assignement operator is disabled
355 
356 private:
358  Map m_map;
359  int m_indent; // indentation level
360  bool m_inEvent; // "In event" flag
361 
362 private:
364 
365  pfmlib_input_param_t inp;
366  pfmlib_output_param_t outp;
367  pfarg_ctx_t ctx;
368  pfarg_pmd_t pd[NUM_PMDS];
369  pfarg_pmc_t pc[NUM_PMCS];
371  int fd;
372  unsigned int i;
373  int ret;
374  void startpm();
375  void pausepm();
376  void stoppm();
377  void finalizepm();
382  char prefix_cstr[MAX_PREFIX_NAME_LENGTH];
383  unsigned int ph_ev_count;
386  unsigned int start_at_event;
390  bool nehalem;
391  bool westmere;
392  bool core;
393 
394  bool sampling;
395  int detect_unavail_pmu_regs( int fd, pfmlib_regmask_t* r_pmcs, pfmlib_regmask_t* r_pmds );
396  int detect_unavail_pmcs( int fd, pfmlib_regmask_t* r_pmcs ) { return detect_unavail_pmu_regs( fd, r_pmcs, NULL ); }
397  void pfm_bv_set( uint64_t* bv, uint16_t rnum ) { bv[rnum >> LBPL] |= 1UL << ( rnum & ( BPL - 1 ) ); }
398  int pfm_bv_isset( uint64_t* bv, uint16_t rnum )
399  {
400  return bv[rnum >> LBPL] & ( 1UL << ( rnum & ( BPL - 1 ) ) ) ? 1 : 0;
401  }
403  {
404  if ( n <= BPL )
405  *d = *j;
406  else {
407  memcpy( d, j, ( n >> LBPL ) * sizeof( uint64_t ) );
408  }
409  }
410  static void process_smpl_buf( pfm_dfl_smpl_hdr_t* hdr, size_t entry_size );
411  static void sigio_handler( int, struct siginfo*, struct sigcontext* ); // dlopen ==>
412  // void sigio_handler(int, struct siginfo *, struct sigcontext *);
413  void start_smpl();
414  void stop_smpl();
415  void finalize_smpl();
418  void* buf_addr;
419  unsigned num_counters;
420  unsigned int max_pmd;
422 
423  int level;
424 
425  bool first_alg;
428 };
429 
431 {
432  memset( &ctx, 0, sizeof( ctx ) );
433  memset( &inp, 0, sizeof( inp ) );
434  memset( &outp, 0, sizeof( outp ) );
435  memset( pd, 0, sizeof( pd ) );
436  memset( pc, 0, sizeof( pc ) );
437  memset( &load_arg, 0, sizeof( load_arg ) );
438  memset( &params, 0, sizeof( params ) );
439  memset( &nhm_params, 0, sizeof( nhm_params ) );
440 
441  for ( int i = 0; i < used_counters_number; i++ ) {
442  ret = m_pfm.pfm_find_full_event( event_cstr[i], &inp.pfp_events[i] );
443  if ( ret != PFMLIB_SUCCESS ) {
444  error() << "ERROR: cannot find event: " << event_cstr[i] << ". Aborting..." << endmsg;
445  }
446  }
447  inp.pfp_dfl_plm = PFM_PLM3;
448  inp.pfp_event_count = 4;
449  for ( int i = 0; i < used_counters_number; i++ ) {
450  if ( inv[i] ) {
451  ( params.pfp_core_counters[i] ).flags |= PFM_CORE_SEL_INV;
452  ( nhm_params.pfp_nhm_counters[i] ).flags |= PFM_NHM_SEL_INV;
453  }
454  if ( cmask[i] > 0 ) {
455  ( params.pfp_core_counters[i] ).cnt_mask = cmask[i];
456  ( nhm_params.pfp_nhm_counters[i] ).cnt_mask = cmask[i];
457  }
458  }
459  if ( nehalem || westmere ) {
460  ret = m_pfm.pfm_dispatch_events( &inp, &nhm_params, &outp, NULL );
461  } else {
462  ret = m_pfm.pfm_dispatch_events( &inp, &params, &outp, NULL );
463  }
464  if ( ret != PFMLIB_SUCCESS ) {
465  error() << "ERROR: cannot dispatch events: " << m_pfm.pfm_strerror( ret ) << ". Aborting..." << endmsg;
466  }
467  for ( unsigned int i = 0; i < outp.pfp_pmc_count; i++ ) {
468  pc[i].reg_num = outp.pfp_pmcs[i].reg_num;
469  pc[i].reg_value = outp.pfp_pmcs[i].reg_value;
470  }
471  for ( unsigned int i = 0; i < outp.pfp_pmd_count; i++ ) {
472  pd[i].reg_num = outp.pfp_pmds[i].reg_num;
473  pd[i].reg_value = 0;
474  }
475  fd = m_pfm.pfm_create_context( &ctx, NULL, 0, 0 );
476  if ( fd == -1 ) {
477  error() << "ERROR: Context not created. Aborting..." << endmsg;
478  }
479  if ( m_pfm.pfm_write_pmcs( fd, pc, outp.pfp_pmc_count ) == -1 ) {
480  error() << "ERROR: Could not write pmcs. Aborting..." << endmsg;
481  }
482  if ( m_pfm.pfm_write_pmds( fd, pd, outp.pfp_pmd_count ) == -1 ) {
483  error() << "ERROR: Could not write pmds. Aborting..." << endmsg;
484  }
485  load_arg.load_pid = getpid();
486  if ( m_pfm.pfm_load_context( fd, &load_arg ) == -1 ) {
487  error() << "ERROR: Could not load context. Aborting..." << endmsg;
488  // error() << "Could not read pmds" << endmsg;
489  }
490 
491  m_pfm.pfm_start( fd, NULL );
492 }
493 
494 // stoppm()
495 // const ModuleDescription& desc : description of the module that just finished its execution (we are only interested in
496 // its name)
497 // stops the counting calling pfm_stop() and stores the counting results into the "results" map
499 {
500  m_pfm.pfm_stop( fd );
501  if ( m_pfm.pfm_read_pmds( fd, pd, inp.pfp_event_count ) == -1 ) {
502  error() << "Could not read pmds" << endmsg;
503  }
504  for ( int i = 0; i < used_counters_number; i++ ) {
505  results[i][( alg_stack.top().first )->name()].push_back( alg_stack.top().second[i] + pd[i].reg_value );
506  }
507 
508  close( fd );
509 }
510 
512 {
513  m_pfm.pfm_stop( fd );
514  if ( m_pfm.pfm_read_pmds( fd, pd, inp.pfp_event_count ) == -1 ) {
515  error() << "Could not read pmds" << endmsg;
516  }
517 
518  for ( int i = 0; i < used_counters_number; i++ ) {
519  alg_stack.top().second[i] += pd[i].reg_value;
520  }
521 
522  close( fd );
523 }
524 
525 // finalizepm()
526 // called when all the countings of the current event are finished, it dumps the results
527 // into the output file corresponding to the event being counted
529 {
530  info() << "start of finalizepm ucn:" << used_counters_number << endmsg;
531  for ( int i = 0; i < used_counters_number; i++ ) {
532  std::string filename = prefix_cstr;
533  filename += '_';
534  filename += event_cstr[i];
535 
536  for ( auto& c : filename )
537  if ( c == ':' ) c = '-';
538 
539  if ( inv[i] ) filename += "_INV_1";
540  if ( cmask[i] > 0 ) filename += "_CMASK_" + std::to_string( cmask[i] );
541  filename += ".txt";
542 
543  info() << "Filename:" << filename << endmsg;
544  FILE* outfile = fopen( filename.c_str(), "w" );
545  if ( nehalem ) {
546  fprintf( outfile, "NHM " );
547  } else if ( westmere ) {
548  fprintf( outfile, "WSM " );
549  } else if ( core ) {
550  fprintf( outfile, "CORE " );
551  }
552  fprintf( outfile, "%s %d %d %d\n", event_cstr[i], cmask[i], inv[i], sp[i] );
553  for ( std::map<std::string, std::vector<unsigned long int>>::iterator it = ( results[i] ).begin();
554  it != ( results[i] ).end(); it++ ) {
555  fprintf( outfile, "%s\n", ( it->first ).c_str() );
556  for ( std::vector<unsigned long int>::iterator j = ( it->second ).begin(); j != ( it->second ).end(); j++ ) {
557  fprintf( outfile, "%lu\n", *j );
558  }
559  }
560  fclose( outfile );
561  }
562 }
563 
565 {
566  if ( !m_pfm.loaded ) {
567  error() << "pfm library could not be loaded" << endmsg;
568  return StatusCode::FAILURE;
569  }
570 
571  info() << "Initializing..." << endmsg;
573  if ( sc.isFailure() ) {
574  return sc;
575  }
576  used_counters_number = 0;
577  for ( int i = 0; i < MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS; i++ ) {
578  if ( event_str[i].length() > 0 ) used_counters_number++;
579  }
580  for ( int i = 0; i < MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS; i++ ) {
581  strcpy( event_cstr[i], event_str[i].c_str() );
582  }
583  strcpy( prefix_cstr, prefix.c_str() );
584 
585  if ( m_pfm.pfm_initialize() != PFMLIB_SUCCESS ) {
586  error() << "Cannot initialize perfmon!!" << endmsg;
587  }
588  ph_ev_count = 0;
589  first_alg = true;
590  event_count_reached = false;
591  nehalem = false;
592  core = false;
593  westmere = false;
594  if ( family.compare( "CORE" ) == 0 )
595  core = true;
596  else if ( family.compare( "NEHALEM" ) == 0 )
597  nehalem = true;
598  else if ( family.compare( "WESTMERE" ) == 0 )
599  westmere = true;
600  else {
601  error() << "ERROR: Unsupported processor family " << family << ". aborting..." << endmsg;
602  }
603 
604  info() << "Initialized!" << endmsg;
605  return StatusCode::SUCCESS;
606 }
607 
608 // process_smpl_buf()
609 // pfm_dfl_smpl_hdr_t *hdr : pointer to header of the buffer containing addresses sampled during the sampling process
610 // size_t entry_size : size of each entry, used to navigate through the various entries
611 // called when the sampling buffer is full, saves the samples into memory ("samples" map)
613 {
616  size_t pos, count;
617  uint64_t entry;
618  if ( hdr->hdr_overflows == last_overflow && hdr->hdr_count == last_count ) {
619  printf( "skipping identical set of samples...\n" );
620  return;
621  }
622  count = hdr->hdr_count;
623  ent = (pfm_dfl_smpl_entry_t*)( hdr + 1 );
624  pos = (unsigned long)ent;
625  entry = collected_samples;
626  while ( count-- ) {
627  // if(ent->ovfl_pmd>=0 && ent->ovfl_pmd<=3)
628  if ( ent->ovfl_pmd <= 3 ) {
629  ( ( samples[ent->ovfl_pmd] )[( alg_stack.top().first )->name()] )[(unsigned long)( ent->ip )]++;
630  }
631  pos += entry_size;
632  ent = (pfm_dfl_smpl_entry_t*)pos;
633  entry++;
634  }
635  collected_samples = entry;
636  last_overflow = hdr->hdr_overflows;
637  if ( last_count != hdr->hdr_count && ( last_count || last_overflow == 0 ) ) {
638  collected_partial += hdr->hdr_count;
639  }
640  last_count = hdr->hdr_count;
641  return;
642 }
643 
644 // sigio_handler()
645 // int n : signal number of the signal being delivered
646 // struct siginfo *info : pointer to a siginfo_t structure containing info about the signal
647 // struct sigcontext *sc : context of the signal, NULL in our case
648 // signal handler used to catch sampling buffer overflows. When they occur it calls the process_smpl_buf() function
649 void PerfMonAuditor::sigio_handler( int /*n*/, struct siginfo* /*info*/, struct sigcontext* /*sc*/ )
650 {
651  PFMon& pfm = PFMon::instance();
653  int fd = ctx_fd;
654  int r;
655  if ( fd != ctx_fd ) {
656  // error() << "ERROR: handler does not get valid file descriptor. Aborting..." << endmsg;
657  }
658  if ( pfm.pfm_read_pmds( fd, pd_smpl + 1, 1 ) == -1 ) {
659  // error() << "ERROR: pfm_read_pmds: " << strerror(errno) << ". Aborting..." << endmsg;
660  }
661  while ( true ) {
662  r = read( fd, &msg, sizeof( msg ) );
663  if ( r != sizeof( msg ) ) {
664  if ( r == -1 && errno == EINTR ) {
665  printf( "read interrupted, retrying\n" );
666  continue;
667  }
668  // error() << "ERROR: cannot read overflow message: " << strerror(errno) << ". Aborting..." << endmsg;
669  }
670  break;
671  }
672  switch ( msg.type ) {
673  case PFM_MSG_OVFL: // the sampling buffer is full
674  process_smpl_buf( hdr, entry_size );
675  ovfl_count++;
676  if ( pfm.pfm_restart( fd ) ) {
677  if ( errno != EBUSY ) {
678  // error() << "ERROR: pfm_restart error errno " << errno << ". Aborting..." << endmsg;
679  } else {
680  printf( "pfm_restart: task probably terminated \n" );
681  }
682  }
683  break;
684  default:
685  // error() << "ERROR: unknown message type " << msg.type << ". Aborting..." << endmsg;
686  break;
687  }
688 }
689 
690 // start_smpl()
691 // const ModuleDescription& desc : description of the module that is just starting its execution (we are only interested
692 // in its name)
693 // initializes all the necessary structures to start the sampling, calling pfm_self_start()
695 {
696  ovfl_count = 0;
697  num_smpl_pmds = 0;
698  last_overflow = ~0;
699  max_pmd = 0;
700  memset( &pfmlib_options, 0, sizeof( pfmlib_options ) );
701  pfmlib_options.pfm_debug = 0;
702  pfmlib_options.pfm_verbose = 0;
703  m_pfm.pfm_set_options( &pfmlib_options );
704  ret = m_pfm.pfm_initialize();
705  if ( ret != PFMLIB_SUCCESS ) {
706  error() << "ERROR: Cannot initialize library: " << m_pfm.pfm_strerror( ret ) << ". Aborting..." << endmsg;
707  }
708  struct sigaction act;
709  memset( &act, 0, sizeof( act ) );
710  act.sa_handler = (sig_t)sigio_handler; // dlopen() ==>
711  // act.sa_handler = (sig_t)&sigio_handler;
712  sigaction( SIGIO, &act, 0 );
713  memset( &ctx, 0, sizeof( ctx ) );
714  memset( &buf_arg, 0, sizeof( buf_arg ) );
715  memset( &inp, 0, sizeof( inp ) );
716  memset( &outp, 0, sizeof( outp ) );
717  memset( pd_smpl, 0, sizeof( pd_smpl ) );
718  memset( pc, 0, sizeof( pc ) );
719  memset( &load_args, 0, sizeof( load_args ) );
720  m_pfm.pfm_get_num_counters( &num_counters );
721  memset( &params, 0, sizeof( params ) );
722  memset( &nhm_params, 0, sizeof( nhm_params ) );
723 
724  for ( int i = 0; i < used_counters_number; i++ ) {
725  ret = m_pfm.pfm_find_full_event( event_cstr[i], &inp.pfp_events[i] );
726  if ( ret != PFMLIB_SUCCESS ) {
727  error() << "ERROR: cannot find event: " << event_cstr[i] << ". Aborting..." << endmsg;
728  }
729  }
730  inp.pfp_dfl_plm = PFM_PLM3;
731  inp.pfp_event_count = 4;
732  for ( int i = 0; i < used_counters_number; i++ ) {
733  if ( inv[i] ) {
734  ( params.pfp_core_counters[i] ).flags |= PFM_CORE_SEL_INV;
735  ( nhm_params.pfp_nhm_counters[i] ).flags |= PFM_NHM_SEL_INV;
736  }
737  if ( cmask[i] > 0 ) {
738  ( params.pfp_core_counters[i] ).cnt_mask = cmask[i];
739  ( nhm_params.pfp_nhm_counters[i] ).cnt_mask = cmask[i];
740  }
741  }
742  if ( nehalem || westmere ) {
743  ret = m_pfm.pfm_dispatch_events( &inp, &nhm_params, &outp, NULL );
744  } else {
745  ret = m_pfm.pfm_dispatch_events( &inp, &params, &outp, NULL );
746  }
747  if ( ret != PFMLIB_SUCCESS ) {
748  error() << "ERROR: cannot configure events: " << m_pfm.pfm_strerror( ret ) << ". Aborting..." << endmsg;
749  }
750  for ( unsigned int i = 0; i < outp.pfp_pmc_count; i++ ) {
751  pc[i].reg_num = outp.pfp_pmcs[i].reg_num;
752  pc[i].reg_value = outp.pfp_pmcs[i].reg_value;
753  }
754  for ( unsigned int i = 0; i < outp.pfp_pmd_count; i++ ) {
755  pd_smpl[i].reg_num = outp.pfp_pmds[i].reg_num;
756  if ( i ) {
757  pfm_bv_set( pd_smpl[0].reg_smpl_pmds, pd_smpl[i].reg_num );
758  if ( pd_smpl[i].reg_num > max_pmd ) {
759  max_pmd = pd_smpl[i].reg_num;
760  }
761  num_smpl_pmds++;
762  }
763  }
764  for ( int i = 0; i < used_counters_number; i++ ) {
766  pfm_bv_copy( pd_smpl[i].reg_reset_pmds, pd_smpl[i].reg_smpl_pmds, max_pmd );
767  pd_smpl[i].reg_value = ( uint64_t )( sp[i] * -1 );
768  pd_smpl[i].reg_short_reset = ( uint64_t )( sp[i] * -1 );
769  pd_smpl[i].reg_long_reset = ( uint64_t )( sp[i] * -1 );
770  pd_smpl[i].reg_random_seed = 5; // tocheck
771  pd_smpl[i].reg_random_mask = 0xff; // tocheck
772  }
773  entry_size = sizeof( pfm_dfl_smpl_entry_t ) + ( num_smpl_pmds << 3 );
774  ctx.ctx_flags = 0;
775  buf_arg.buf_size = 3 * getpagesize() + 512;
776  ctx_fd = m_pfm.pfm_create_context( &ctx, (char*)FMT_NAME, &buf_arg, sizeof( buf_arg ) );
777  if ( ctx_fd == -1 ) {
778  if ( errno == ENOSYS ) {
779  error() << "ERROR: Your kernel does not have performance monitoring support! Aborting..." << endmsg;
780  }
781  error() << "ERROR: Can't create PFM context " << strerror( errno ) << ". Aborting..." << endmsg;
782  }
783  buf_addr = mmap( NULL, (size_t)buf_arg.buf_size, PROT_READ, MAP_PRIVATE, ctx_fd, 0 );
784  if ( buf_addr == MAP_FAILED ) {
785  error() << "ERROR: cannot mmap sampling buffer: " << strerror( errno ) << ". Aborting..." << endmsg;
786  }
787  hdr = (pfm_dfl_smpl_hdr_t*)buf_addr;
788  if ( PFM_VERSION_MAJOR( hdr->hdr_version ) < 1 ) {
789  error() << "ERROR: invalid buffer format version. Aborting..." << endmsg;
790  }
791  if ( m_pfm.pfm_write_pmcs( ctx_fd, pc, outp.pfp_pmc_count ) ) {
792  error() << "ERROR: pfm_write_pmcs error errno " << strerror( errno ) << ". Aborting..." << endmsg;
793  }
794  if ( m_pfm.pfm_write_pmds( ctx_fd, pd_smpl, outp.pfp_pmd_count ) ) {
795  error() << "ERROR: pfm_write_pmds error errno " << strerror( errno ) << ". Aborting..." << endmsg;
796  }
797  load_args.load_pid = getpid();
798  if ( m_pfm.pfm_load_context( ctx_fd, &load_args ) ) {
799  error() << "ERROR: pfm_load_context error errno " << strerror( errno ) << ". Aborting..." << endmsg;
800  }
801  ret = fcntl( ctx_fd, F_SETFL, fcntl( ctx_fd, F_GETFL, 0 ) | O_ASYNC );
802  if ( ret == -1 ) {
803  error() << "ERROR: cannot set ASYNC: " << strerror( errno ) << ". Aborting..." << endmsg;
804  }
805  ret = fcntl( ctx_fd, F_SETOWN, getpid() );
806  if ( ret == -1 ) {
807  error() << "ERROR: cannot setown: " << strerror( errno ) << ". Aborting..." << endmsg;
808  }
809  // pfm_self_start(ctx_fd); ==>
810  m_pfm.pfm_start( ctx_fd, NULL );
811 }
812 
813 // stop_smpl()
814 // const ModuleDescription& desc : description of the module that just finished its execution (we are only interested in
815 // its name)
816 // stops the sampling and calls process_smpl_buf() one last time to process all the remaining samples
818 {
819  m_pfm.pfm_self_stop( ctx_fd );
820  process_smpl_buf( hdr, entry_size );
821  close( ctx_fd );
822  ret = munmap( hdr, (size_t)buf_arg.buf_size );
823  if ( ret ) {
824  error() << "Cannot unmap buffer: %s" << strerror( errno ) << endmsg;
825  }
826  return;
827 }
828 
829 // finalize_smpl()
830 // processes the sampling results in order to find library and offset of each sampled address, using the symbol() and
831 // tosymbol() functions,
832 // and then dumps the new found information into gzipped output files, to be processed later
834 {
835  int err;
836  for ( int i = 0; i < used_counters_number; i++ ) {
837  std::string filename = prefix_cstr;
838  filename += '_';
839  filename += event_cstr[i];
840 
841  for ( auto& c : filename )
842  if ( c == ':' ) c = '-';
843 
844  if ( inv[i] ) filename += "_INV_1";
845  if ( cmask[i] > 0 ) filename += "_CMASK_" + std::to_string( cmask[i] );
846  filename += ".txt.gz";
847 
848  gzFile outfile = gzopen( filename.c_str(), "wb" );
849  if ( outfile != NULL ) {
850  if ( nehalem ) {
851  gzprintf( outfile, "NHM " );
852  } else if ( westmere ) {
853  gzprintf( outfile, "WSM " );
854  } else if ( core ) {
855  gzprintf( outfile, "CORE " );
856  }
857  if ( gzprintf( outfile, "%s %d %d %d\n", event_cstr[i], cmask[i], inv[i], sp[i] ) <
858  (int)strlen( event_cstr[i] ) ) {
859  error() << "ERROR: gzputs err: " << gzerror( outfile, &err ) << ". Aborting..." << endmsg;
860  }
861  for ( std::map<std::string, std::map<unsigned long, unsigned int>>::iterator it = samples[i].begin();
862  it != samples[i].end(); it++ ) {
863  unsigned long long sum = 0;
864  for ( std::map<unsigned long, unsigned int>::iterator jt = ( it->second ).begin(); jt != ( it->second ).end();
865  jt++ ) {
866  sum += jt->second;
867  }
868  if ( gzprintf( outfile, "%s%%%llu\n", ( it->first ).c_str(), sum ) < (int)( ( it->first ).length() ) ) {
869  error() << "ERROR: gzputs err: " << gzerror( outfile, &err ) << ". Aborting..." << endmsg;
870  }
871  for ( std::map<unsigned long, unsigned int>::iterator jt = ( it->second ).begin(); jt != ( it->second ).end();
872  jt++ ) {
873  char sym_name[SYM_NAME_MAX_LENGTH];
874  bzero( sym_name, SYM_NAME_MAX_LENGTH );
875  const char* libName;
876  const char* symbolName;
877  int libOffset = 0;
878  int offset = 0;
879  void* sym_addr = IgHookTrace::tosymbol( (void*)( jt->first ) );
880  if ( sym_addr != NULL ) {
881  bool success = IgHookTrace::symbol( sym_addr, symbolName, libName, offset, libOffset );
882  if ( success ) {
883  if ( symbolName != NULL && strlen( symbolName ) > 0 ) {
884  strcpy( sym_name, symbolName );
885  strcat( sym_name, " " );
886  } else {
887  strcpy( sym_name, "??? " );
888  }
889  if ( libName != NULL && strlen( libName ) > 0 ) {
890  strcat( sym_name, libName );
891  strcat( sym_name, " " );
892  } else {
893  strcat( sym_name, "??? " );
894  }
895  sprintf( sym_name, "%s%d ", sym_name, libOffset );
896  if ( strlen( sym_name ) <= 0 ) {
897  error() << "ERROR: Symbol name length is zero. Aborting..." << endmsg;
898  }
899  } else {
900  strcpy( sym_name, "??? ??? 0 " );
901  }
902  } else {
903  strcpy( sym_name, "??? ??? 0 " );
904  }
905  if ( gzprintf( outfile, "%s %d\n", sym_name, jt->second ) < (int)strlen( sym_name ) ) {
906  error() << "ERROR: gzputs err: " << gzerror( outfile, &err ) << endmsg;
907  }
908  }
909  }
910  } else {
911  error() << "ERROR: Could not open file: " << filename << ". Aborting..." << endmsg;
912  }
913  gzclose( outfile );
914  }
915 }
916 
918 {
919  if ( sampling == 0 )
920  finalizepm();
921  else
922  finalize_smpl();
923  return Auditor::finalize();
924 }
925 
926 void PerfMonAuditor::before( StandardEventType evt, INamedInterface* alg )
927 {
928  switch ( evt ) {
930  i_beforeInitialize( alg );
931  break;
932  case IAuditor::Execute:
933  i_beforeExecute( alg );
934  break;
935  default:
936  break;
937  }
938  return;
939 }
940 
941 void PerfMonAuditor::after( StandardEventType evt, INamedInterface* alg, const StatusCode& )
942 {
943  switch ( evt ) {
945  i_afterInitialize( alg );
946  break;
947  case IAuditor::Execute:
948  i_afterExecute( alg );
949  break;
950  default:
951  break;
952  }
953  return;
954 }
955 
957 {
958  if ( !alg ) return;
959  return;
960 }
961 
963 {
964  if ( !alg ) return;
965  return;
966 }
967 
969 {
970  if ( !alg ) return;
971  // info() << "before:inside! " << alg->name() << endmsg;
972  if ( first_alg ) {
973  first_alg = false;
974  first_alg_name = alg->name();
975  // info() << "first_alg_name= " << alg->name() << endmsg;
976  }
977  if ( !event_count_reached ) {
978  if ( !first_alg_name.compare( alg->name() ) ) {
979  ph_ev_count++;
980  // info() << "EVENT COUNT: " << ph_ev_count << endmsg;
981  if ( ph_ev_count == start_at_event ) {
982  event_count_reached = true;
983  // info() << "!!! EVENT COUNT REACHED: " << ph_ev_count << endmsg;
984  }
985  }
986  }
987  if ( event_count_reached ) {
988  // info() << "before:inside! " << alg->name() << endmsg;
989 
990  if ( !alg_stack.empty() ) {
991  if ( sampling == 0 )
992  pausepm(); // pausing father algorithm counting
993  else
994  stop_smpl();
995  }
996  ++m_indent;
997  std::vector<unsigned long int> zeroes( 4, 0 );
998  alg_stack.push( std::make_pair( alg, zeroes ) );
999  if ( sampling == 0 )
1000  startpm();
1001  else
1002  start_smpl();
1003  }
1004 }
1005 
1007 {
1008  if ( !alg ) {
1009  return;
1010  } // info() << "after:inside! " << alg->name() << endmsg;
1011 
1012  if ( event_count_reached ) {
1013  // info() << "after:inside! " << alg->name() << endmsg;
1014 
1015  if ( sampling == 0 )
1016  stoppm();
1017  else
1018  stop_smpl();
1019  alg_stack.pop();
1020  --m_indent;
1021  if ( !alg_stack.empty() ) {
1022  if ( sampling == 0 )
1023  startpm();
1024  else
1025  start_smpl(); // resuming father algorithm counting
1026  }
1027  }
1028 }
1029 
pfarg_load_t load_args
int pfm_err_t
Definition: pfmlib.h:150
constexpr static const auto FAILURE
Definition: StatusCode.h:88
uint64_t reg_short_reset
Definition: perfmon_v2.h:44
pfmlib_core_input_param_t params
os_err_t pfm_write_pmds(int fd, pfarg_pmd_t *pmds, int count)
#define cpuid(func, ax, bx, cx, dx)
virtual StatusCode finalize()
Definition: Auditor.cpp:200
#define PFM_REGFL_OVFL_NOTIFY
Definition: perfmon.h:112
#define MAX_PREFIX_NAME_LENGTH
T empty(T...args)
#define PFM_NHM_SEL_INV
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
Definition: ISvcLocator.h:25
os_err_t pfm_create_context(pfarg_ctx_t *ctx, char *smpl_name, void *smpl_arg, size_t smpl_size)
#define PFM_PLM3
Definition: pfmlib.h:53
PerfMonAuditor(const std::string &name, ISvcLocator *pSvc)
std::string family
char * pfm_strerror(int code)
#define PFM_CORE_SEL_INV
Definition: pfmlib_core.h:68
static void * tosymbol(void *address)
double sum(double x, double y, double z)
#define PFMLIB_SUCCESS
Definition: pfmlib.h:267
T to_string(T...args)
pfm_err_t pfm_get_num_counters(unsigned int *num)
#define SYM_NAME_MAX_LENGTH
T pop(T...args)
constexpr double pc
class MergingTransformer< Out(const vector_of_const_< In > void
T top(T...args)
int os_err_t
Definition: perfmon.h:69
def read(f, regex='.*', skipevents=0)
Definition: hivetimeline.py:22
uint16_t reg_num
Definition: perfmon_v2.h:39
unsigned long long uint64_t
Definition: instrset.h:143
void i_afterExecute(INamedInterface *alg)
pfmlib_input_param_t inp
unsigned short int uint16_t
Definition: instrset.h:139
uint32_t type
Definition: perfmon.h:206
os_err_t pfm_write_pmcs(int fd, pfarg_pmc_t *pmcs, int count)
Performance Monitoring Auditor that uses Perfmon2 library to monitor algorithms.
pfm_err_t pfm_dispatch_events(pfmlib_input_param_t *p, void *model_in, pfmlib_output_param_t *q, void *model_out)
T push(T...args)
pfmlib_options_t pfmlib_options
bool is_nehalem()
Definition: CPUFamily.cpp:18
static void sigio_handler(int, struct siginfo *, struct sigcontext *)
STL class.
bool isFailure() const
Definition: StatusCode.h:139
uint32_t reg_random_seed
Definition: perfmon_v2.h:51
std::string first_alg_name
pfm_err_t pfm_find_full_event(const char *str, pfmlib_event_t *e)
uint64_t reg_long_reset
Definition: perfmon_v2.h:43
StatusCode finalize() override
#define MAX_EVENT_NAME_LENGTH
pfmlib_nhm_input_param_t nhm_params
#define NUM_PMCS
PropertyMgr & operator=(const PropertyMgr &)=delete
STL class.
#define DECLARE_COMPONENT(type)
#define PFM_VERSION_MAJOR(x)
Definition: perfmon.h:213
void pfm_bv_copy(uint64_t *d, uint64_t *j, uint16_t n)
GaudiUtils::VectorMap< const INamedInterface *, int > Map
int detect_unavail_pmcs(int fd, pfmlib_regmask_t *r_pmcs)
uint16_t ovfl_pmd
uint64_t ip
void pfm_bv_set(uint64_t *bv, uint16_t rnum)
uint32_t reg_flags
Definition: perfmon_v2.h:41
os_err_t pfm_restart(int fd)
STL class.
#define NUM_PMDS
std::string prefix
This class is used for returning status codes from appropriate routines.
Definition: StatusCode.h:51
Gaudi::Details::PropertyBase * declareProperty(const std::string &name, TYPE &value, const std::string &doc="none")
Declare a property (templated)
pfmlib_output_param_t outp
void after(StandardEventType, INamedInterface *, const StatusCode &) override
Definition: Auditor.cpp:110
static bool symbol(void *address, const char *&sym, const char *&lib, int &offset, int &liboffset)
T make_pair(T...args)
string prefix
Definition: gaudirun.py:268
#define LBPL
void after(StandardEventType evt, INamedInterface *alg, const StatusCode &sc) override
os_err_t pfm_start(int fd, pfarg_start_t *start)
constexpr static const auto SUCCESS
Definition: StatusCode.h:87
pfm_err_t pfm_initialize(void)
#define BPL
unsigned int i
IInterface compliant class extending IInterface with the name() method.
unsigned int ph_ev_count
STL class.
int pfm_bv_isset(uint64_t *bv, uint16_t rnum)
T begin(T...args)
#define FMT_NAME
unsigned int start_at_event
static void process_smpl_buf(pfm_dfl_smpl_hdr_t *hdr, size_t entry_size)
os_err_t pfm_load_context(int fd, pfarg_load_t *load)
#define PFM_REGFL_RANDOM
Definition: perfmon.h:113
pfm_dfl_smpl_arg_t buf_arg
os_err_t pfm_read_pmds(int fd, pfarg_pmd_t *pmds, int count)
unsigned int max_pmd
uint64_t reg_random_mask
Definition: perfmon_v2.h:50
StatusCode initialize() override
void i_beforeExecute(INamedInterface *alg)
virtual StatusCode initialize()
Definition: Auditor.cpp:70
AttribStringParser::Iterator begin(const AttribStringParser &parser)
#define MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS
void i_afterInitialize(INamedInterface *alg)
void i_beforeInitialize(INamedInterface *alg)
pfarg_load_t load_arg
#define PFM_MSG_OVFL
Definition: perfmon.h:210
os_err_t pfm_stop(int fd)
virtual ~PerfMonAuditor()
void before(StandardEventType, INamedInterface *) override
The following methods are meant to be implemented by the child class...
Definition: Auditor.cpp:73
uint64_t reg_value
Definition: perfmon_v2.h:42
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
Definition: MsgStream.h:209
virtual const std::string & name() const =0
Retrieve the name of the instance.
void before(StandardEventType evt, INamedInterface *alg) override
evt
Definition: IOTest.py:96
pfm_err_t pfm_set_options(pfmlib_options_t *opt)
Base class from which all concrete auditor classes should be derived.
Definition: Auditor.h:35