Initial commit.
[collect-bench] / benchspt.c
1 #include <errno.h>
2 #include <stdlib.h>
3 #include <time.h>
4
5 #if defined(__GNUC__) && (defined(__i386__) || defined (__x86_64__))
6
7 struct cycle_counter {
8 char dummy;
9 };
10
11 static int init_counter(struct cycle_counter *cy) { return (0); }
12 static void teardown_counter(struct cycle_counter *cy) { ; }
13
14 int cycles(struct cycle_counter *cy, unsigned long long *t_out)
15 {
16 unsigned lo, hi;
17
18 __asm__("rdtsc" : "=a"(lo), "=d"(hi));
19 *t_out = lo | ((unsigned long long)hi << 32);
20 return (0);
21 }
22
23 #elif defined(__linux__)
24
25 #include <unistd.h>
26 #include <linux/perf_event.h>
27 #include <asm/unistd.h>
28
29 struct cycle_counter {
30 int fd;
31 };
32
33 static int init_counter(struct cycle_counter *cy)
34 {
35 struct perf_event_attr attr = { 0 };
36
37 attr.type = PERF_TYPE_HARDWARE;
38 attr.size = sizeof(attr);
39 attr.config = PERF_COUNT_HW_CPU_CYCLES;
40 attr.disabled = 0;
41 attr.exclude_kernel = 1;
42 attr.exclude_hv = 1;
43
44 cy->fd = syscall(__NR_perf_event_open, &attr, 0, -1, -1, 0);
45 if (cy->fd < 0) return (-1);
46 return (0);
47 }
48
49 static void teardown_counter(struct cycle_counter *cy)
50 { if (cy->fd >= 0) close(cy->fd); }
51
52 int cycles(struct cycle_counter *cy, unsigned long long *t_out)
53 {
54 ssize_t n;
55
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;
61 return (-1);
62 }
63 return (0);
64 }
65
66 #else
67
68 struct cycle_counter {
69 char dummy;
70 };
71
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)
76 { return (-1); }
77
78 #endif
79
80 struct cycle_counter *open_cycle_counter(void)
81 {
82 struct cycle_counter *cy = 0, *cy_ret = 0;
83
84 cy = malloc(sizeof(*cy)); if (!cy) goto end;
85 if (init_counter(cy)) goto end;
86 cy_ret = cy; cy = 0;
87 end:
88 free(cy);
89 return (cy_ret);
90 }
91
92 void close_cycle_counter(struct cycle_counter *cy)
93 { teardown_counter(cy); free(cy); }
94
95 struct clock {
96 long long sec;
97 unsigned nsec;
98 };
99
100 int thread_clock(struct clock *clk_out)
101 {
102 struct timespec tv;
103
104 if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tv)) return (-1);
105 clk_out->sec = tv.tv_sec; clk_out->nsec = tv.tv_nsec;
106 return (0);
107 }
108
109 int get_errno(void) { return (errno); }