summaryrefslogtreecommitdiff
path: root/nacl/cpucycles/x86estimate.c
diff options
context:
space:
mode:
Diffstat (limited to 'nacl/cpucycles/x86estimate.c')
-rw-r--r--nacl/cpucycles/x86estimate.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/nacl/cpucycles/x86estimate.c b/nacl/cpucycles/x86estimate.c
new file mode 100644
index 00000000..e5ae66cf
--- /dev/null
+++ b/nacl/cpucycles/x86estimate.c
@@ -0,0 +1,59 @@
1#include <time.h>
2#include <sys/time.h>
3#include <sys/types.h>
4#include <sys/sysctl.h>
5
6long long cpucycles_x86estimate(void)
7{
8 long long result;
9 asm volatile(".byte 15;.byte 49" : "=A" (result));
10 return result;
11}
12
13static long long microseconds(void)
14{
15 struct timeval t;
16 gettimeofday(&t,(struct timezone *) 0);
17 return t.tv_sec * (long long) 1000000 + t.tv_usec;
18}
19
20static double guessfreq(void)
21{
22 long long tb0; long long us0;
23 long long tb1; long long us1;
24
25 tb0 = cpucycles_x86estimate();
26 us0 = microseconds();
27 do {
28 tb1 = cpucycles_x86estimate();
29 us1 = microseconds();
30 } while (us1 - us0 < 10000 || tb1 - tb0 < 1000);
31 if (tb1 <= tb0) return 0;
32 tb1 -= tb0;
33 us1 -= us0;
34 return ((double) tb1) / (0.000001 * (double) us1);
35}
36
37static double cpufrequency = 0;
38
39static void init(void)
40{
41 double guess1;
42 double guess2;
43 int loop;
44
45 for (loop = 0;loop < 100;++loop) {
46 guess1 = guessfreq();
47 guess2 = guessfreq();
48 if (guess1 > 1.01 * guess2) continue;
49 if (guess2 > 1.01 * guess1) continue;
50 cpufrequency = 0.5 * (guess1 + guess2);
51 break;
52 }
53}
54
55long long cpucycles_x86estimate_persecond(void)
56{
57 if (!cpufrequency) init();
58 return cpufrequency;
59}