Skip to content
Snippets Groups Projects
Select Git revision
2 results Searching

tcp_timer.c

Blame
  • 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;