32 #include <sys/types.h> 44 #include <sys/ptrace.h> 48 #include <sys/resource.h> 64 #define MAX_EVT_NAME_LEN 256 65 #define NUM_PMCS PFMLIB_MAX_PMCS 66 #define NUM_PMDS PFMLIB_MAX_PMDS 67 #define FMT_NAME PFM_DFL_SMPL_NAME 68 #define BPL (sizeof(uint64_t)<<3) 71 #define SYM_NAME_MAX_LENGTH 10000 72 #define MAX_OUTPUT_FILENAME_LENGTH 1024 73 #define MAX_EVENT_NAME_LENGTH 500 74 #define MAX_PREFIX_NAME_LENGTH 1024 75 #define FILENAME_MAX_LENGTH 1024 77 #define MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS 4 79 #define cpuid(func,ax,bx,cx,dx) __asm__ __volatile__ ("cpuid": "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) : "a" (func)); 83 static uint64_t collected_samples, collected_partial;
87 static size_t entry_size;
88 static unsigned int num_smpl_pmds;
102 template <
typename T>
103 inline T function_cast(
void *p) {
109 return caster.function;
114 typedef void (*pfm_stop_t)(int);
116 typedef void (*pfm_self_stop_t)(int);
117 pfm_self_stop_t pfm_self_stop;
118 typedef os_err_t (*pfm_restart_t)(int);
120 typedef int (*pfm_read_pmds_t)(int,
pfarg_pmd_t*, int);
132 typedef os_err_t (*pfm_write_pmds_t)(int, pfarg_pmd_t *, int);
138 typedef char* (*pfm_strerror_t)(int);
142 typedef pfm_err_t (*pfm_get_num_counters_t)(
unsigned int *);
144 static PFMon &instance() {
153 handle = dlopen(
"libpfm.so", RTLD_NOW);
154 if (handle) { loaded =
true; }
else { loaded =
false; }
156 pfm_start = function_cast<pfm_start_t>(dlsym(handle,
"pfm_start"));
157 pfm_stop = function_cast<pfm_stop_t>(dlsym(handle,
"pfm_stop"));
158 pfm_self_stop = function_cast<pfm_self_stop_t>(dlsym(handle,
"pfm_stop"));
159 pfm_restart = function_cast<pfm_restart_t>(dlsym(handle,
"pfm_restart"));
160 pfm_read_pmds = function_cast<pfm_read_pmds_t>(dlsym(handle,
"pfm_read_pmds"));
161 pfm_initialize = function_cast<pfm_initialize_t>(dlsym(handle,
"pfm_initialize"));
162 pfm_find_full_event = function_cast<pfm_find_full_event_t>(dlsym(handle,
"pfm_find_full_event"));
163 pfm_dispatch_events = function_cast<pfm_dispatch_events_t>(dlsym(handle,
"pfm_dispatch_events"));
164 pfm_create_context = function_cast<pfm_create_context_t>(dlsym(handle,
"pfm_create_context"));
165 pfm_write_pmcs = function_cast<pfm_write_pmcs_t>(dlsym(handle,
"pfm_write_pmcs"));
166 pfm_write_pmds = function_cast<pfm_write_pmds_t>(dlsym(handle,
"pfm_write_pmds"));
167 pfm_load_context = function_cast<pfm_load_context_t>(dlsym(handle,
"pfm_load_context"));
168 pfm_strerror = function_cast<pfm_strerror_t>(dlsym(handle,
"pfm_strerror"));
169 pfm_set_options = function_cast<pfm_set_options_t>(dlsym(handle,
"pfm_set_options"));
170 pfm_get_num_counters = function_cast<pfm_get_num_counters_t>(dlsym(handle,
"pfm_get_num_counters"));
176 if (handle) dlclose(handle);
179 static PFMon s_instance;
182 PFMon PFMon::s_instance;
220 #pragma warning(push) 221 #pragma warning(disable:593) 225 int sse4_2_mask = 1 << 20;
226 if(c & sse4_2_mask)
return 1;
else return 0;
274 m_pfm(PFMon::instance()),
397 static void sigio_handler(
int,
struct siginfo *,
struct sigcontext *);
401 void finalize_smpl();
421 memset(&ctx,0,
sizeof(ctx));
422 memset(&inp,0,
sizeof(inp));
423 memset(&outp,0,
sizeof(outp));
424 memset(pd, 0,
sizeof(pd));
425 memset(
pc, 0,
sizeof(
pc));
426 memset(&load_arg, 0,
sizeof(load_arg));
427 memset(¶ms, 0,
sizeof(params));
428 memset(&nhm_params, 0,
sizeof(nhm_params));
430 for(
int i=0; i<used_counters_number; i++)
432 ret = m_pfm.pfm_find_full_event(event_cstr[i], &inp.pfp_events[i]);
435 error() <<
"ERROR: cannot find event: " << event_cstr[i] <<
". Aborting..." <<
endmsg;
439 inp.pfp_event_count = 4;
440 for(
int i=0; i<used_counters_number; i++)
449 (params.pfp_core_counters[i]).cnt_mask = cmask[i];
450 (nhm_params.pfp_nhm_counters[i]).cnt_mask = cmask[i];
453 if(nehalem || westmere)
455 ret = m_pfm.pfm_dispatch_events(&inp, &nhm_params, &outp, NULL);
459 ret = m_pfm.pfm_dispatch_events(&inp, ¶ms, &outp, NULL);
463 error() <<
"ERROR: cannot dispatch events: " << m_pfm.pfm_strerror(ret) <<
". Aborting..." <<
endmsg;
465 for(
unsigned int i=0; i<outp.pfp_pmc_count; i++)
467 pc[i].reg_num = outp.pfp_pmcs[i].reg_num;
468 pc[i].reg_value = outp.pfp_pmcs[i].reg_value;
470 for(
unsigned int i=0; i<outp.pfp_pmd_count; i++)
472 pd[i].reg_num = outp.pfp_pmds[i].reg_num;
475 fd = m_pfm.pfm_create_context(&ctx, NULL, 0, 0);
478 error() <<
"ERROR: Context not created. Aborting..." <<
endmsg;
480 if(m_pfm.pfm_write_pmcs(fd,
pc, outp.pfp_pmc_count) == -1)
482 error() <<
"ERROR: Could not write pmcs. Aborting..." <<
endmsg;
484 if(m_pfm.pfm_write_pmds(fd, pd, outp.pfp_pmd_count) == -1)
486 error() <<
"ERROR: Could not write pmds. Aborting..." <<
endmsg;
488 load_arg.load_pid = getpid();
489 if(m_pfm.pfm_load_context(fd, &load_arg) == -1)
491 error() <<
"ERROR: Could not load context. Aborting..." <<
endmsg;
495 m_pfm.pfm_start(fd, NULL);
508 if(m_pfm.pfm_read_pmds(fd, pd, inp.pfp_event_count) == -1)
510 error() <<
"Could not read pmds" <<
endmsg;
512 for(
int i=0; i<used_counters_number; i++)
514 results[i][(alg_stack.
top().first)->
name()].push_back(alg_stack.
top().second[i] + pd[i].reg_value);
524 if(m_pfm.pfm_read_pmds(fd, pd, inp.pfp_event_count) == -1)
526 error() <<
"Could not read pmds" <<
endmsg;
529 for(
int i=0; i<used_counters_number; i++)
531 alg_stack.
top().second[i] += pd[i].reg_value;
543 info() <<
"start of finalizepm ucn:" << used_counters_number <<
endmsg;
547 for(
int i=0; i<used_counters_number; i++)
550 sprintf(filename,
"%s_%s", prefix_cstr, event_cstr[i]);
551 for(
int j=0; j<(int)strlen(filename); j++)
561 strcpy(to_cat,
"_INV_1");
565 sprintf(to_cat,
"%s_CMASK_%d", to_cat, cmask[i]);
567 sprintf(filename,
"%s%s.txt", filename, to_cat);
568 info() <<
"Filename:" << filename <<
endmsg;
569 outfile = fopen(filename,
"w");
572 fprintf(outfile,
"NHM ");
576 fprintf(outfile,
"WSM ");
580 fprintf(outfile,
"CORE ");
582 fprintf(outfile,
"%s %d %d %d\n", event_cstr[i], cmask[i], inv[i],
sp[i]);
585 fprintf(outfile,
"%s\n", (it->first).c_str());
588 fprintf(outfile,
"%lu\n", *j);
598 error() <<
"pfm library could not be loaded" <<
endmsg;
602 info() <<
"Initializing..." <<
endmsg;
608 used_counters_number = 0;
611 if(event_str[i].length()>0) used_counters_number++;
615 strcpy(event_cstr[i], event_str[i].c_str());
617 strcpy(prefix_cstr,
prefix.c_str());
621 error() <<
"Cannot initialize perfmon!!" <<
endmsg;
625 event_count_reached =
false;
629 if(family.compare(
"CORE")==0) core =
true;
630 else if(family.compare(
"NEHALEM")==0) nehalem =
true;
631 else if(family.compare(
"WESTMERE")==0) westmere =
true;
634 error() <<
"ERROR: Unsupported processor family " << family <<
". aborting..." <<
endmsg;
637 info() <<
"Initialized!" <<
endmsg;
653 printf(
"skipping identical set of samples...\n");
658 pos = (
unsigned long)ent;
659 entry = collected_samples;
665 ((samples[ent->
ovfl_pmd])[(alg_stack.
top().first)->
name()])[(
unsigned long)(ent->
ip)]++;
671 collected_samples = entry;
673 if (last_count != hdr->
hdr_count && (last_count || last_overflow == 0))
688 PFMon& pfm = PFMon::instance();
696 if(pfm.pfm_read_pmds(fd, pd_smpl+1, 1) == -1)
702 r =
read(fd, &msg,
sizeof(msg));
705 if(r==-1 && errno==EINTR)
707 printf(
"read interrupted, retrying\n");
717 process_smpl_buf(hdr, entry_size);
719 if(pfm.pfm_restart(fd))
727 printf(
"pfm_restart: task probably terminated \n");
753 memset(&pfmlib_options, 0,
sizeof(pfmlib_options));
754 pfmlib_options.pfm_debug = 0;
755 pfmlib_options.pfm_verbose = 0;
756 m_pfm.pfm_set_options(&pfmlib_options);
757 ret = m_pfm.pfm_initialize();
760 error() <<
"ERROR: Cannot initialize library: " << m_pfm.pfm_strerror(ret) <<
". Aborting..." <<
endmsg;
762 struct sigaction act;
763 memset(&act, 0,
sizeof(act));
764 act.sa_handler = (sig_t)sigio_handler;
766 sigaction(SIGIO, &act, 0);
767 memset(&ctx, 0,
sizeof(ctx));
768 memset(&buf_arg, 0,
sizeof(buf_arg));
769 memset(&inp,0,
sizeof(inp));
770 memset(&outp,0,
sizeof(outp));
771 memset(pd_smpl, 0,
sizeof(pd_smpl));
772 memset(
pc, 0,
sizeof(
pc));
773 memset(&load_args, 0,
sizeof(load_args));
774 m_pfm.pfm_get_num_counters(&num_counters);
775 memset(¶ms, 0,
sizeof(params));
776 memset(&nhm_params, 0,
sizeof(nhm_params));
778 for(
int i=0; i<used_counters_number; i++)
780 ret = m_pfm.pfm_find_full_event(event_cstr[i], &inp.pfp_events[i]);
783 error() <<
"ERROR: cannot find event: " << event_cstr[i] <<
". Aborting..." <<
endmsg;
787 inp.pfp_event_count = 4;
788 for(
int i=0; i<used_counters_number; i++)
797 (params.pfp_core_counters[i]).cnt_mask = cmask[i];
798 (nhm_params.pfp_nhm_counters[i]).cnt_mask = cmask[i];
801 if(nehalem || westmere)
803 ret = m_pfm.pfm_dispatch_events(&inp, &nhm_params, &outp, NULL);
807 ret = m_pfm.pfm_dispatch_events(&inp, ¶ms, &outp, NULL);
811 error() <<
"ERROR: cannot configure events: " << m_pfm.pfm_strerror(ret) <<
". Aborting..." <<
endmsg;
813 for(
unsigned int i=0; i<outp.pfp_pmc_count; i++)
815 pc[i].reg_num = outp.pfp_pmcs[i].reg_num;
816 pc[i].reg_value = outp.pfp_pmcs[i].reg_value;
818 for(
unsigned int i=0; i<outp.pfp_pmd_count; i++)
820 pd_smpl[i].
reg_num = outp.pfp_pmds[i].reg_num;
823 pfm_bv_set(pd_smpl[0].reg_smpl_pmds, pd_smpl[i].reg_num);
824 if(pd_smpl[i].reg_num>max_pmd)
831 for(
int i=0; i<used_counters_number; i++)
834 pfm_bv_copy(pd_smpl[i].reg_reset_pmds, pd_smpl[i].reg_smpl_pmds, max_pmd);
843 buf_arg.buf_size = 3*getpagesize()+512;
844 ctx_fd = m_pfm.pfm_create_context(&ctx, (
char *)
FMT_NAME, &buf_arg,
sizeof(buf_arg));
849 error() <<
"ERROR: Your kernel does not have performance monitoring support! Aborting..." <<
endmsg;
851 error() <<
"ERROR: Can't create PFM context " << strerror(errno) <<
". Aborting..." <<
endmsg;
853 buf_addr = mmap(NULL, (
size_t)buf_arg.buf_size, PROT_READ, MAP_PRIVATE, ctx_fd, 0);
854 if(buf_addr==MAP_FAILED)
856 error() <<
"ERROR: cannot mmap sampling buffer: " << strerror(errno) <<
". Aborting..." <<
endmsg;
861 error() <<
"ERROR: invalid buffer format version. Aborting..." <<
endmsg;
863 if(m_pfm.pfm_write_pmcs(ctx_fd,
pc, outp.pfp_pmc_count))
865 error() <<
"ERROR: pfm_write_pmcs error errno " << strerror(errno) <<
". Aborting..." <<
endmsg;
867 if(m_pfm.pfm_write_pmds(ctx_fd, pd_smpl, outp.pfp_pmd_count))
869 error() <<
"ERROR: pfm_write_pmds error errno " << strerror(errno) <<
". Aborting..." <<
endmsg;
871 load_args.load_pid = getpid();
872 if(m_pfm.pfm_load_context(ctx_fd, &load_args))
874 error() <<
"ERROR: pfm_load_context error errno " << strerror(errno) <<
". Aborting..." <<
endmsg;
876 ret = fcntl(ctx_fd, F_SETFL, fcntl(ctx_fd, F_GETFL, 0) | O_ASYNC);
879 error() <<
"ERROR: cannot set ASYNC: " << strerror(errno) <<
". Aborting..." <<
endmsg;
881 ret = fcntl(ctx_fd, F_SETOWN, getpid());
884 error() <<
"ERROR: cannot setown: " << strerror(errno) <<
". Aborting..." <<
endmsg;
887 m_pfm.pfm_start(ctx_fd, NULL);
896 m_pfm.pfm_self_stop(ctx_fd);
897 process_smpl_buf(hdr, entry_size);
899 ret = munmap(hdr, (
size_t)buf_arg.buf_size);
902 error() <<
"Cannot unmap buffer: %s" << strerror(errno) <<
endmsg;
919 for(
int i=0; i<used_counters_number; i++)
921 sprintf(filename,
"%s_%s", prefix_cstr, event_cstr[i]);
922 for(
int j=0; j<(int)strlen(filename); j++)
932 strcpy(to_cat,
"_INV_1");
936 sprintf(to_cat,
"%s_CMASK_%d", to_cat, cmask[i]);
938 sprintf(filename,
"%s%s.txt.gz", filename, to_cat);
939 outfile = gzopen(filename,
"wb");
944 gzprintf(outfile,
"NHM ");
948 gzprintf(outfile,
"WSM ");
952 gzprintf(outfile,
"CORE ");
954 if(gzprintf(outfile,
"%s %d %d %d\n", event_cstr[i], cmask[i], inv[i],
sp[i]) < (
int)strlen(event_cstr[i]))
956 error() <<
"ERROR: gzputs err: " << gzerror(outfile, &err) <<
". Aborting..." <<
endmsg;
960 unsigned long long sum = 0;
965 if(gzprintf(outfile,
"%s%%%llu\n", (it->first).c_str(),
sum) < (
int)((it->first).length()))
967 error() <<
"ERROR: gzputs err: " << gzerror(outfile, &err) <<
". Aborting..." <<
endmsg;
974 const char *symbolName;
983 if(symbolName!=NULL && strlen(symbolName)>0)
985 strcpy(sym_name, symbolName);
986 strcat(sym_name,
" ");
990 strcpy(sym_name,
"??? ");
992 if(libName!=NULL && strlen(libName)>0)
994 strcat(sym_name, libName);
995 strcat(sym_name,
" ");
999 strcat(sym_name,
"??? ");
1001 sprintf(sym_name,
"%s%d ", sym_name, libOffset);
1002 if(strlen(sym_name)<=0)
1004 error() <<
"ERROR: Symbol name length is zero. Aborting..." <<
endmsg;
1009 strcpy(sym_name,
"??? ??? 0 ");
1014 strcpy(sym_name,
"??? ??? 0 ");
1016 if(gzprintf(outfile,
"%s %d\n", sym_name, jt->second) < (
int)strlen(sym_name))
1018 error() <<
"ERROR: gzputs err: " << gzerror(outfile, &err) <<
endmsg;
1025 error() <<
"ERROR: Could not open file: " << filename <<
". Aborting..." <<
endmsg;
1035 if(sampling == 0) finalizepm();
1036 else finalize_smpl();
1046 i_beforeInitialize(alg);
1049 i_beforeExecute(alg);
1062 i_afterInitialize(alg);
1065 i_afterExecute(alg);
1092 first_alg_name = alg->
name();
1095 if(!event_count_reached)
1097 if(!first_alg_name.compare(alg->
name()))
1101 if(ph_ev_count==start_at_event)
1103 event_count_reached =
true;
1108 if(event_count_reached)
1112 if(!alg_stack.
empty())
1114 if(sampling == 0) pausepm();
1120 if(sampling == 0) startpm();
1131 if(event_count_reached) {
1134 if(sampling == 0) stoppm();
1138 if(!alg_stack.
empty())
1140 if(sampling == 0) startpm();
pfmlib_core_input_param_t params
os_err_t pfm_write_pmds(int fd, pfarg_pmd_t *pmds, int count)
virtual StatusCode finalize()
#define PFM_REGFL_OVFL_NOTIFY
#define MAX_PREFIX_NAME_LENGTH
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
os_err_t pfm_create_context(pfarg_ctx_t *ctx, char *smpl_name, void *smpl_arg, size_t smpl_size)
PerfMonAuditor(const std::string &name, ISvcLocator *pSvc)
char * pfm_strerror(int code)
static void * tosymbol(void *address)
double sum(double x, double y, double z)
pfm_err_t pfm_get_num_counters(unsigned int *num)
#define SYM_NAME_MAX_LENGTH
class MergingTransformer< Out(const vector_of_const_< In > void
def read(f, regex='.*', skipevents=0)
unsigned long long uint64_t
void i_afterExecute(INamedInterface *alg)
#define MAX_OUTPUT_FILENAME_LENGTH
unsigned short int uint16_t
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)
pfmlib_options_t pfmlib_options
static void sigio_handler(int, struct siginfo *, struct sigcontext *)
bool isFailure() const
Test for a status code of FAILURE.
std::string first_alg_name
pfm_err_t pfm_find_full_event(const char *str, pfmlib_event_t *e)
StatusCode finalize() override
#define MAX_EVENT_NAME_LENGTH
pfmlib_nhm_input_param_t nhm_params
#define DECLARE_COMPONENT(type)
auto begin(reverse_wrapper< T > &w)
PropertyMgr & operator=(const PropertyMgr &)=delete
#define PFM_VERSION_MAJOR(x)
void pfm_bv_copy(uint64_t *d, uint64_t *j, uint16_t n)
int detect_unavail_pmcs(int fd, pfmlib_regmask_t *r_pmcs)
void pfm_bv_set(uint64_t *bv, uint16_t rnum)
os_err_t pfm_restart(int fd)
This class is used for returning status codes from appropriate routines.
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
static bool symbol(void *address, const char *&sym, const char *&lib, int &offset, int &liboffset)
auto end(reverse_wrapper< T > &w)
void after(StandardEventType evt, INamedInterface *alg, const StatusCode &sc) override
os_err_t pfm_start(int fd, pfarg_start_t *start)
pfm_err_t pfm_initialize(void)
IInterface compliant class extending IInterface with the name() method.
int pfm_bv_isset(uint64_t *bv, uint16_t rnum)
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 cpuid(func, ax, bx, cx, dx)
pfm_dfl_smpl_arg_t buf_arg
os_err_t pfm_read_pmds(int fd, pfarg_pmd_t *pmds, int count)
StatusCode initialize() override
void i_beforeExecute(INamedInterface *alg)
virtual StatusCode initialize()
#define MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS
void i_afterInitialize(INamedInterface *alg)
void i_beforeInitialize(INamedInterface *alg)
os_err_t pfm_stop(int fd)
virtual ~PerfMonAuditor()
GaudiUtils::VectorMap< const INamedInterface *, int > Map
void before(StandardEventType, INamedInterface *) override
The following methods are meant to be implemented by the child class...
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.
virtual const std::string & name() const =0
Retrieve the name of the instance.
void before(StandardEventType evt, INamedInterface *alg) override
pfm_err_t pfm_set_options(pfmlib_options_t *opt)
Base class from which all concrete auditor classes should be derived.