diff options
Diffstat (limited to 'nacl/cpucycles/cortex.c')
-rw-r--r-- | nacl/cpucycles/cortex.c | 73 |
1 files changed, 73 insertions, 0 deletions
diff --git a/nacl/cpucycles/cortex.c b/nacl/cpucycles/cortex.c new file mode 100644 index 00000000..07e2fa02 --- /dev/null +++ b/nacl/cpucycles/cortex.c | |||
@@ -0,0 +1,73 @@ | |||
1 | /* | ||
2 | cpucycles/cortex.c version 20101203 | ||
3 | D. J. Bernstein | ||
4 | Public domain. | ||
5 | */ | ||
6 | |||
7 | #define SCALE 1 | ||
8 | #include <time.h> | ||
9 | #include <unistd.h> | ||
10 | #include <sys/time.h> | ||
11 | |||
12 | static int enabled = 0; | ||
13 | |||
14 | static int prev[3]; | ||
15 | static unsigned long long prevcycles = 0; | ||
16 | static int now[3]; | ||
17 | static long long cyclespersec = 0; | ||
18 | |||
19 | static void readticks(unsigned int *result) | ||
20 | { | ||
21 | struct timeval t; | ||
22 | unsigned int cc; | ||
23 | if (!enabled) { | ||
24 | asm volatile("mcr p15, 0, %0, c9, c12, 0" :: "r"(17)); | ||
25 | asm volatile("mcr p15, 0, %0, c9, c12, 1" :: "r"(0x8000000f)); | ||
26 | asm volatile("mcr p15, 0, %0, c9, c12, 3" :: "r"(0x8000000f)); | ||
27 | enabled = 1; | ||
28 | } | ||
29 | asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(cc)); | ||
30 | gettimeofday(&t,(struct timezone *) 0); | ||
31 | result[0] = cc; | ||
32 | result[1] = t.tv_usec; | ||
33 | result[2] = t.tv_sec; | ||
34 | } | ||
35 | |||
36 | long long cpucycles_cortex(void) | ||
37 | { | ||
38 | unsigned long long delta4; | ||
39 | int deltan; | ||
40 | int deltas; | ||
41 | unsigned long long guesscycles; | ||
42 | |||
43 | readticks(now); | ||
44 | delta4 = (unsigned int) (now[0] - prev[0]); /* unsigned change in number of cycles mod 2^32 */ | ||
45 | deltan = now[1] - prev[1]; /* signed change in number of nanoseconds mod 10^9 */ | ||
46 | deltas = now[2] - prev[2]; /* signed change in number of seconds */ | ||
47 | if ((deltas == 0 && deltan < 200000) || (deltas == 1 && deltan < -800000)) | ||
48 | return (prevcycles + delta4) * SCALE; | ||
49 | |||
50 | prev[0] = now[0]; | ||
51 | prev[1] = now[1]; | ||
52 | prev[2] = now[2]; | ||
53 | |||
54 | if ((deltas == 0 && deltan < 300000) || (deltas == 1 && deltan < -700000)) { | ||
55 | // actual number of cycles cannot have increased by 2^32 in <0.3ms | ||
56 | cyclespersec = 1000000 * (unsigned long long) delta4; | ||
57 | cyclespersec /= deltan + 1000000 * (long long) deltas; | ||
58 | } else { | ||
59 | guesscycles = deltas * cyclespersec; | ||
60 | guesscycles += (deltan * cyclespersec) / 1000000; | ||
61 | while (delta4 + 2147483648ULL < guesscycles) delta4 += 4294967296ULL; | ||
62 | /* XXX: could do longer-term extrapolation here */ | ||
63 | } | ||
64 | |||
65 | prevcycles += delta4; | ||
66 | return prevcycles * SCALE; | ||
67 | } | ||
68 | |||
69 | long long cpucycles_cortex_persecond(void) | ||
70 | { | ||
71 | while (!cyclespersec) cpucycles_cortex(); | ||
72 | return cyclespersec * SCALE; | ||
73 | } | ||