38 #include <sys/types.h>
50 #include <sys/ptrace.h>
54 #include <sys/resource.h>
70 #define MAX_EVT_NAME_LEN 256
71 #define NUM_PMCS PFMLIB_MAX_PMCS
72 #define NUM_PMDS PFMLIB_MAX_PMDS
73 #define FMT_NAME PFM_DFL_SMPL_NAME
74 #define BPL (sizeof(uint64_t)<<3)
77 #define SYM_NAME_MAX_LENGTH 10000
78 #define MAX_OUTPUT_FILENAME_LENGTH 1024
79 #define MAX_EVENT_NAME_LENGTH 500
80 #define MAX_PREFIX_NAME_LENGTH 1024
81 #define FILENAME_MAX_LENGTH 1024
83 #define MAX_NUMBER_OF_PROGRAMMABLE_COUNTERS 4
85 #define cpuid(func,ax,bx,cx,dx) __asm__ __volatile__ ("cpuid": "=a" (ax), "=b" (bx), "=c" (cx), "=d" (dx) : "a" (func));
108 template <
typename T>
109 inline T function_cast(
void *p) {
115 return caster.function;
120 typedef void (*pfm_stop_t)(
int);
122 typedef void (*pfm_self_stop_t)(
int);
123 pfm_self_stop_t pfm_self_stop;
144 typedef char* (*pfm_strerror_t)(
int);
148 typedef pfm_err_t (*pfm_get_num_counters_t)(
unsigned int *);
150 static PFMon &instance() {
159 handle = dlopen(
"libpfm.so", RTLD_NOW);
160 if (handle) { loaded =
true; }
else { loaded =
false; }
162 pfm_start = function_cast<pfm_start_t>(dlsym(handle,
"pfm_start"));
163 pfm_stop = function_cast<pfm_stop_t>(dlsym(handle,
"pfm_stop"));
164 pfm_self_stop = function_cast<pfm_self_stop_t>(dlsym(handle,
"pfm_stop"));
165 pfm_restart = function_cast<pfm_restart_t>(dlsym(handle,
"pfm_restart"));
166 pfm_read_pmds = function_cast<pfm_read_pmds_t>(dlsym(handle,
"pfm_read_pmds"));
167 pfm_initialize = function_cast<pfm_initialize_t>(dlsym(handle,
"pfm_initialize"));
168 pfm_find_full_event = function_cast<pfm_find_full_event_t>(dlsym(handle,
"pfm_find_full_event"));
169 pfm_dispatch_events = function_cast<pfm_dispatch_events_t>(dlsym(handle,
"pfm_dispatch_events"));
170 pfm_create_context = function_cast<pfm_create_context_t>(dlsym(handle,
"pfm_create_context"));
171 pfm_write_pmcs = function_cast<pfm_write_pmcs_t>(dlsym(handle,
"pfm_write_pmcs"));
172 pfm_write_pmds = function_cast<pfm_write_pmds_t>(dlsym(handle,
"pfm_write_pmds"));
173 pfm_load_context = function_cast<pfm_load_context_t>(dlsym(handle,
"pfm_load_context"));
174 pfm_strerror = function_cast<pfm_strerror_t>(dlsym(handle,
"pfm_strerror"));
175 pfm_set_options = function_cast<pfm_set_options_t>(dlsym(handle,
"pfm_set_options"));
176 pfm_get_num_counters = function_cast<pfm_get_num_counters_t>(dlsym(handle,
"pfm_get_num_counters"));
182 if (handle) dlclose(handle);
185 static PFMon s_instance;
188 PFMon PFMon::s_instance;
226 #pragma warning(push)
227 #pragma warning(disable:593)
231 int sse4_2_mask = 1 << 20;
232 if(c & sse4_2_mask)
return 1;
else return 0;
280 m_pfm(PFMon::instance()),
402 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));}}
404 static void sigio_handler(
int,
struct siginfo *,
struct sigcontext *);
429 memset(&
ctx,0,
sizeof(
ctx));
430 memset(&
inp,0,
sizeof(
inp));
432 memset(
pd, 0,
sizeof(
pd));
433 memset(
pc, 0,
sizeof(
pc));
483 fd =
m_pfm.pfm_create_context(&
ctx, NULL, 0, 0);
499 log <<
MSG::ERROR <<
"ERROR: Could not load context. Aborting..." <<
endmsg;
563 for(
int j=0; j<(
int)strlen(filename); j++)
573 strcpy(to_cat,
"_INV_1");
577 sprintf(to_cat,
"%s_CMASK_%d", to_cat,
cmask[i]);
579 sprintf(filename,
"%s%s.txt", filename, to_cat);
581 outfile = fopen(filename,
"w");
584 fprintf(outfile,
"NHM ");
588 fprintf(outfile,
"WSM ");
592 fprintf(outfile,
"CORE ");
597 fprintf(outfile,
"%s\n", (it->first).c_str());
600 fprintf(outfile,
"%lu\n", *j);
667 printf(
"skipping identical set of samples...\n");
672 pos = (
unsigned long)ent;
703 PFMon& pfm = PFMon::instance();
711 if(pfm.pfm_read_pmds(fd, pd_smpl+1, 1) == -1)
717 r = read(fd, &msg,
sizeof(msg));
720 if(r==-1 &&
errno==EINTR)
722 printf(
"read interrupted, retrying\n");
734 if(pfm.pfm_restart(fd))
742 printf(
"pfm_restart: task probably terminated \n");
778 struct sigaction act;
779 memset(&act, 0,
sizeof(act));
782 sigaction(SIGIO, &act, 0);
783 memset(&
ctx, 0,
sizeof(
ctx));
785 memset(&
inp,0,
sizeof(
inp));
787 memset(pd_smpl, 0,
sizeof(pd_smpl));
788 memset(
pc, 0,
sizeof(
pc));
839 pfm_bv_set(pd_smpl[0].reg_smpl_pmds, pd_smpl[
i].reg_num);
865 log <<
MSG::ERROR <<
"ERROR: Your kernel does not have performance monitoring support! Aborting..." <<
endmsg;
867 log <<
MSG::ERROR <<
"ERROR: Can't create PFM context " << strerror(
errno) <<
". Aborting..." <<
endmsg;
872 log <<
MSG::ERROR <<
"ERROR: cannot mmap sampling buffer: " << strerror(
errno) <<
". Aborting..." <<
endmsg;
877 log <<
MSG::ERROR <<
"ERROR: invalid buffer format version. Aborting..." <<
endmsg;
881 log <<
MSG::ERROR <<
"ERROR: pfm_write_pmcs error errno " << strerror(
errno) <<
". Aborting..." <<
endmsg;
885 log <<
MSG::ERROR <<
"ERROR: pfm_write_pmds error errno " << strerror(
errno) <<
". Aborting..." <<
endmsg;
890 log <<
MSG::ERROR <<
"ERROR: pfm_load_context error errno " << strerror(
errno) <<
". Aborting..." <<
endmsg;
940 for(
int j=0; j<(
int)strlen(filename); j++)
950 strcpy(to_cat,
"_INV_1");
954 sprintf(to_cat,
"%s_CMASK_%d", to_cat,
cmask[i]);
956 sprintf(filename,
"%s%s.txt.gz", filename, to_cat);
957 outfile = gzopen(filename,
"wb");
962 gzprintf(outfile,
"NHM ");
966 gzprintf(outfile,
"WSM ");
970 gzprintf(outfile,
"CORE ");
974 log <<
MSG::ERROR <<
"ERROR: gzputs err: " << gzerror(outfile, &err) <<
". Aborting..." <<
endmsg;
978 unsigned long long sum = 0;
983 if(gzprintf(outfile,
"%s%%%llu\n", (it->first).c_str(),
sum) < (
int)((it->first).length()))
985 log <<
MSG::ERROR <<
"ERROR: gzputs err: " << gzerror(outfile, &err) <<
". Aborting..." <<
endmsg;
992 const char *symbolName;
1001 if(symbolName!=NULL && strlen(symbolName)>0)
1003 strcpy(sym_name, symbolName);
1004 strcat(sym_name,
" ");
1008 strcpy(sym_name,
"??? ");
1010 if(libName!=NULL && strlen(libName)>0)
1012 strcat(sym_name, libName);
1013 strcat(sym_name,
" ");
1017 strcat(sym_name,
"??? ");
1019 sprintf(sym_name,
"%s%d ", sym_name, libOffset);
1020 if(strlen(sym_name)<=0)
1022 log <<
MSG::ERROR <<
"ERROR: Symbol name length is zero. Aborting..." <<
endmsg;
1027 strcpy(sym_name,
"??? ??? 0 ");
1032 strcpy(sym_name,
"??? ??? 0 ");
1034 if(gzprintf(outfile,
"%s %d\n", sym_name, jt->second) < (
int)strlen(sym_name))
1036 log <<
MSG::ERROR <<
"ERROR: gzputs err: " << gzerror(outfile, &err) <<
endmsg;
1043 log <<
MSG::ERROR <<
"ERROR: Could not open file: " << filename <<
". Aborting..." <<
endmsg;
1140 if(!alg_stack.
empty())
1170 if(!alg_stack.
empty())