diff options
Diffstat (limited to 'nacl/cpucycles/dev4ns.c')
-rw-r--r-- | nacl/cpucycles/dev4ns.c | 62 |
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 | |||
8 | static int fddev = -1; | ||
9 | static int prev[3]; | ||
10 | static unsigned long long prevcycles = 0; | ||
11 | static int now[3]; | ||
12 | static long long cyclespersec = 0; | ||
13 | |||
14 | static void readdev(unsigned int *result) | ||
15 | { | ||
16 | if (read(fddev,result,12) == 12) return; | ||
17 | result[0] = result[1] = result[2] = 0; | ||
18 | } | ||
19 | |||
20 | long 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 | |||
58 | long long cpucycles_dev4ns_persecond(void) | ||
59 | { | ||
60 | while (!cyclespersec) cpucycles_dev4ns(); | ||
61 | return cyclespersec; | ||
62 | } | ||