#define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #include #include #define TIMINGS 5 static struct perf_event_attr attr; static int fdperf = -1; static struct perf_event_mmap_page *buf; static cpu_set_t cores; static long long core; static int64_t where[TIMINGS]; static int64_t offset[TIMINGS]; static int64_t result[TIMINGS]; static long long lastwhere; static long long lastoffset; void printresults(void) { printf("core %lld",core); for (int i = 0;i < TIMINGS;++i) { if (where[i] != lastwhere) { lastwhere = where[i]; printf(" [index 0x%llx]",lastwhere); } if (offset[i] != lastoffset) { lastoffset = offset[i]; printf(" [offset 0x%llx]",lastoffset); } printf(" %lld",(long long) result[i]); } if (result[TIMINGS-1] == result[0]) printf(" stuck (perf bug 1)"); printf("\n"); fflush(stdout); } void sigsegv() { printf("core %lld segmentation fault (perf bug 2)\n",core); exit(100); } int main() { signal(SIGSEGV,sigsegv); attr.type = PERF_TYPE_HARDWARE; attr.size = sizeof(struct perf_event_attr); attr.config = PERF_COUNT_HW_CPU_CYCLES; attr.exclude_kernel = 1; attr.exclude_hv = 1; fdperf = syscall(__NR_perf_event_open,&attr,0,-1,-1,0); if (fdperf == -1) abort(); for (int rdpmc = 0;rdpmc < 3;++rdpmc) { if (rdpmc) { buf = mmap(NULL,sysconf(_SC_PAGESIZE),PROT_READ,MAP_SHARED,fdperf,0); if (!buf) { printf("mmap failed for rdpmc; quitting\n"); return 111; } if (rdpmc == 1) printf("will now use rdpmc in an intel-specific way (fails on amd)\n"); else printf("will now use rdpmc according to the perf manual\n"); fflush(stdout); } for (int loop = 0;loop < 3;++loop) { for (core = 0;;++core) { CPU_ZERO(&cores); CPU_SET(core,&cores); if (sched_setaffinity(0,sizeof cores,&cores) != 0) break; for (int i = 0;i < TIMINGS;++i) { if (rdpmc == 1) { asm volatile("rdpmc;shlq $32,%%rdx;orq %%rdx,%%rax" : "=a"(result[i]) : "c"((1<<30)|1) : "%rdx"); } else if (rdpmc) { unsigned int seq; do { seq = buf->lock; asm volatile("" ::: "memory"); where[i] = buf->index; offset[i] = buf->offset; asm volatile("rdpmc;shlq $32,%%rdx;orq %%rdx,%%rax" : "=a"(result[i]) : "c"(where[i]-1) : "%rdx"); asm volatile("" ::: "memory"); } while (buf->lock != seq); result[i] += offset[i]; result[i] &= 0xffffffffffff; } else { int r = read(fdperf,&result[i],8); if (r < 8) result[i] = r; if (r == -1) result[i] = -errno; } } printresults(); } } } return 0; }