#include <stdbool.h> | |
#include <errno.h> | |
#include <linux/perf_event.h> | |
#include "../../perf.h" | |
#include <linux/types.h> | |
#include "../../util/debug.h" | |
#include "../../util/tsc.h" | |
#include "tsc.h" | |
int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc, | |
struct perf_tsc_conversion *tc) | |
{ | |
bool cap_user_time_zero; | |
u32 seq; | |
int i = 0; | |
while (1) { | |
seq = pc->lock; | |
rmb(); | |
tc->time_mult = pc->time_mult; | |
tc->time_shift = pc->time_shift; | |
tc->time_zero = pc->time_zero; | |
cap_user_time_zero = pc->cap_user_time_zero; | |
rmb(); | |
if (pc->lock == seq && !(seq & 1)) | |
break; | |
if (++i > 10000) { | |
pr_debug("failed to get perf_event_mmap_page lock\n"); | |
return -EINVAL; | |
} | |
} | |
if (!cap_user_time_zero) | |
return -EOPNOTSUPP; | |
return 0; | |
} | |
u64 rdtsc(void) | |
{ | |
unsigned int low, high; | |
asm volatile("rdtsc" : "=a" (low), "=d" (high)); | |
return low | ((u64)high) << 32; | |
} |