5 #if defined(__GNUC__) && (defined(__i386__) || defined (__x86_64__))
11 static int init_counter(struct cycle_counter *cy) { return (0); }
12 static void teardown_counter(struct cycle_counter *cy) { ; }
14 int cycles(struct cycle_counter *cy, unsigned long long *t_out)
18 __asm__("rdtsc" : "=a"(lo), "=d"(hi));
19 *t_out = lo | ((unsigned long long)hi << 32);
23 #elif defined(__linux__)
26 #include <linux/perf_event.h>
27 #include <asm/unistd.h>
29 struct cycle_counter {
33 static int init_counter(struct cycle_counter *cy)
35 struct perf_event_attr attr = { 0 };
37 attr.type = PERF_TYPE_HARDWARE;
38 attr.size = sizeof(attr);
39 attr.config = PERF_COUNT_HW_CPU_CYCLES;
41 attr.exclude_kernel = 1;
44 cy->fd = syscall(__NR_perf_event_open, &attr, 0, -1, -1, 0);
45 if (cy->fd < 0) return (-1);
49 static void teardown_counter(struct cycle_counter *cy)
50 { if (cy->fd >= 0) close(cy->fd); }
52 int cycles(struct cycle_counter *cy, unsigned long long *t_out)
56 if (cy->fd < 0) { errno = EBADF; return (-1); }
57 n = read(cy->fd, t_out, sizeof(*t_out));
58 if (n < sizeof(*t_out)) {
59 if (n >= 0) errno = ENODATA;
60 close(cy->fd); cy->fd = -1;
68 struct cycle_counter {
72 static int init_counter(struct cycle_counter *cy)
73 { errno = ENOSYS; return (-1); }
74 static void teardown_counter(struct cycle_counter *cy) { ; }
75 int cycles(struct cycle_counter *cy, unsigned long long *t_out)
80 struct cycle_counter *open_cycle_counter(void)
82 struct cycle_counter *cy = 0, *cy_ret = 0;
84 cy = malloc(sizeof(*cy)); if (!cy) goto end;
85 if (init_counter(cy)) goto end;
92 void close_cycle_counter(struct cycle_counter *cy)
93 { teardown_counter(cy); free(cy); }
100 int thread_clock(struct clock *clk_out)
104 if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tv)) return (-1);
105 clk_out->sec = tv.tv_sec; clk_out->nsec = tv.tv_nsec;
109 int get_errno(void) { return (errno); }