• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 //          Copyright Oliver Kowalke 2009.
3 // Distributed under the Boost Software License, Version 1.0.
4 //    (See accompanying file LICENSE_1_0.txt or copy at
5 //          http://www.boost.org/LICENSE_1_0.txt)
6 
7 #ifndef CYCLE_I386_H
8 #define CYCLE_I386_H
9 
10 #include <algorithm>
11 #include <numeric>
12 #include <cstddef>
13 #include <vector>
14 
15 #include <boost/assert.hpp>
16 #include <boost/bind.hpp>
17 #include <boost/cstdint.hpp>
18 
19 #define BOOST_CONTEXT_CYCLE
20 
21 typedef boost::uint64_t cycle_type;
22 
23 #if _MSC_VER
24 inline
cycles()25 cycle_type cycles()
26 {
27     cycle_type c;
28     __asm {
29         cpuid
30         rdtsc
31         mov dword ptr [c + 0], eax
32         mov dword ptr [c + 4], edx
33     }
34     return c;
35 }
36 #elif defined(__GNUC__) || \
37       defined(__INTEL_COMPILER) || defined(__ICC) || defined(_ECC) || defined(__ICL)
38 inline
cycles()39 cycle_type cycles()
40 {
41     boost::uint32_t lo, hi;
42 
43     __asm__ __volatile__ (
44         "xorl %%eax, %%eax\n"
45         "cpuid\n"
46         ::: "%eax", "%ebx", "%ecx", "%edx"
47     );
48     __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi) );
49     __asm__ __volatile__ (
50         "xorl %%eax, %%eax\n"
51         "cpuid\n"
52         ::: "%eax", "%ebx", "%ecx", "%edx"
53     );
54 
55     return ( cycle_type)hi << 32 | lo;
56 }
57 #else
58 # error "this compiler is not supported"
59 #endif
60 
61 struct cycle_overhead
62 {
operator ()cycle_overhead63     cycle_type operator()()
64     {
65         cycle_type start( cycles() );
66         return cycles() - start;
67     }
68 };
69 
70 inline
overhead_cycle()71 cycle_type overhead_cycle()
72 {
73     std::size_t iterations( 10);
74     std::vector< cycle_type >  overhead( iterations, 0);
75     for ( std::size_t i( 0); i < iterations; ++i)
76         std::generate(
77             overhead.begin(), overhead.end(),
78             cycle_overhead() );
79     BOOST_ASSERT( overhead.begin() != overhead.end() );
80     return std::accumulate( overhead.begin(), overhead.end(), 0) / iterations;
81 }
82 
83 #endif // CYCLE_I386_H
84