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
); }