summaryrefslogtreecommitdiff
path: root/nacl/cpucycles/dev4ns.c
diff options
context:
space:
mode:
Diffstat (limited to 'nacl/cpucycles/dev4ns.c')
-rw-r--r--nacl/cpucycles/dev4ns.c62
1 files changed, 62 insertions, 0 deletions
diff --git a/nacl/cpucycles/dev4ns.c b/nacl/cpucycles/dev4ns.c
new file mode 100644
index 00000000..73ff5755
--- /dev/null
+++ b/nacl/cpucycles/dev4ns.c
@@ -0,0 +1,62 @@
1#include <sys/types.h>
2#include <fcntl.h>
3#include <time.h>
4#include <stdio.h>
5#include <unistd.h>
6#include <sys/time.h>
7
8static int fddev = -1;
9static int prev[3];
10static unsigned long long prevcycles = 0;
11static int now[3];
12static long long cyclespersec = 0;
13
14static void readdev(unsigned int *result)
15{
16 if (read(fddev,result,12) == 12) return;
17 result[0] = result[1] = result[2] = 0;
18}
19
20long long cpucycles_dev4ns(void)
21{
22 unsigned long long delta4;
23 int deltan;
24 int deltas;
25 unsigned long long guesscycles;
26
27 if (fddev == -1) {
28 fddev = open("/dev/cpucycles4ns",O_RDONLY);
29 readdev(prev);
30 }
31
32 readdev(now);
33 delta4 = (unsigned int) (now[0] - prev[0]); /* unsigned change in number of cycles mod 2^32 */
34 deltan = now[1] - prev[1]; /* signed change in number of nanoseconds mod 10^9 */
35 deltas = now[2] - prev[2]; /* signed change in number of seconds */
36 if ((deltas == 0 && deltan < 200000000) || (deltas == 1 && deltan < -800000000))
37 return prevcycles + delta4;
38
39 prev[0] = now[0];
40 prev[1] = now[1];
41 prev[2] = now[2];
42
43 if ((deltas == 0 && deltan < 300000000) || (deltas == 1 && deltan < -700000000)) {
44 // actual number of cycles cannot have increased by 2^32 in <0.3ms
45 cyclespersec = 1000000000 * (unsigned long long) delta4;
46 cyclespersec /= deltan + 1000000000 * (long long) deltas;
47 } else {
48 guesscycles = deltas * cyclespersec;
49 guesscycles += (deltan * cyclespersec) / 1000000000;
50 while (delta4 + 2147483648ULL < guesscycles) delta4 += 4294967296ULL;
51 /* XXX: could do longer-term extrapolation here */
52 }
53
54 prevcycles += delta4;
55 return prevcycles;
56}
57
58long long cpucycles_dev4ns_persecond(void)
59{
60 while (!cyclespersec) cpucycles_dev4ns();
61 return cyclespersec;
62}