Select Git revision
tcp_timer.c
rdpmc.c 3.19 KiB
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/mman.h>
#include <linux/types.h>
#include "perf.h"
#include "debug.h"
#include "tests/tests.h"
#include "cloexec.h"
#include "arch-tests.h"
static u64 rdpmc(unsigned int counter)
{
unsigned int low, high;
asm volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (counter));
return low | ((u64)high) << 32;
}
static u64 rdtsc(void)
{
unsigned int low, high;
asm volatile("rdtsc" : "=a" (low), "=d" (high));
return low | ((u64)high) << 32;
}
static u64 mmap_read_self(void *addr)
{
struct perf_event_mmap_page *pc = addr;
u32 seq, idx, time_mult = 0, time_shift = 0;
u64 count, cyc = 0, time_offset = 0, enabled, running, delta;
do {
seq = pc->lock;
barrier();
enabled = pc->time_enabled;
running = pc->time_running;
if (enabled != running) {
cyc = rdtsc();
time_mult = pc->time_mult;
time_shift = pc->time_shift;
time_offset = pc->time_offset;
}
idx = pc->index;
count = pc->offset;
if (idx)
count += rdpmc(idx - 1);
barrier();
} while (pc->lock != seq);
if (enabled != running) {
u64 quot, rem;
quot = (cyc >> time_shift);
rem = cyc & (((u64)1 << time_shift) - 1);
delta = time_offset + quot * time_mult +
((rem * time_mult) >> time_shift);
enabled += delta;
if (idx)
running += delta;
quot = count / running;