chiark / gitweb /
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); }