Initial commit.
[collect-bench] / benchspt.c
CommitLineData
7642fe3b
MW
1#include <errno.h>
2#include <stdlib.h>
3#include <time.h>
4
5#if defined(__GNUC__) && (defined(__i386__) || defined (__x86_64__))
6
7struct cycle_counter {
8 char dummy;
9};
10
11static int init_counter(struct cycle_counter *cy) { return (0); }
12static void teardown_counter(struct cycle_counter *cy) { ; }
13
14int 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
29struct cycle_counter {
30 int fd;
31};
32
33static 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
49static void teardown_counter(struct cycle_counter *cy)
50 { if (cy->fd >= 0) close(cy->fd); }
51
52int 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
68struct cycle_counter {
69 char dummy;
70};
71
72static int init_counter(struct cycle_counter *cy)
73 { errno = ENOSYS; return (-1); }
74static void teardown_counter(struct cycle_counter *cy) { ; }
75int cycles(struct cycle_counter *cy, unsigned long long *t_out)
76 { return (-1); }
77
78#endif
79
80struct 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;
87end:
88 free(cy);
89 return (cy_ret);
90}
91
92void close_cycle_counter(struct cycle_counter *cy)
93 { teardown_counter(cy); free(cy); }
94
95struct clock {
96 long long sec;
97 unsigned nsec;
98};
99
100int 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
109int get_errno(void) { return (errno); }