Main Page   File List  

rdtsc.h

00001 
00007 /* (c) 2003 Technische Universitaet Dresden
00008  * This file is part of DROPS, which is distributed under the terms of the
00009  * GNU General Public License 2. Please see the COPYING file for details. */
00010 
00011 #ifndef __l4_rdtsc_h
00012 #define __l4_rdtsc_h
00013 
00014 #include <l4/sys/compiler.h>
00015 #include <l4/sys/l4int.h>
00016 
00017 EXTERN_C_BEGIN
00018 
00019 /* interface */
00020 
00021 #define L4_TSC_INIT_AUTO             0
00022 #define L4_TSC_INIT_KERNEL           1
00023 #define L4_TSC_INIT_CALIBRATE        2
00024 
00027 extern l4_uint32_t l4_scaler_tsc_to_ns;
00028 extern l4_uint32_t l4_scaler_tsc_to_us;
00029 extern l4_uint32_t l4_scaler_ns_to_tsc;
00030 extern l4_uint32_t l4_scaler_tsc_linux;
00031 
00035 L4_INLINE l4_cpu_time_t
00036 l4_rdtsc (void);
00037 
00042 L4_INLINE l4_cpu_time_t
00043 l4_rdpmc (int nr);
00044 
00045 /* the same, but only 32 bit. Useful for smaller differences,
00046    needs less cycles. */
00047 L4_INLINE
00048 l4_uint32_t l4_rdpmc_32(int nr);
00049 
00055 L4_INLINE l4_uint64_t
00056 l4_tsc_to_ns (l4_cpu_time_t tsc);
00057 
00063 L4_INLINE l4_uint64_t
00064 l4_tsc_to_us (l4_cpu_time_t tsc);
00065 
00072 L4_INLINE void
00073 l4_tsc_to_s_and_ns (l4_cpu_time_t tsc, l4_uint32_t *s, l4_uint32_t *ns);
00074 
00080 L4_INLINE l4_cpu_time_t
00081 l4_ns_to_tsc (l4_uint64_t ns);
00082 
00087 L4_INLINE void
00088 l4_busy_wait_ns (l4_uint64_t ns);
00089 
00094 L4_INLINE void
00095 l4_busy_wait_us (l4_uint64_t us);
00096 
00097 EXTERN_C_BEGIN
00098 
00105 L4_INLINE l4_uint32_t
00106 l4_calibrate_tsc (void);
00107 
00130 L4_CV l4_uint32_t
00131 l4_tsc_init (int constraint);
00132 
00137 L4_CV l4_uint32_t
00138 l4_get_hz (void);
00139 
00140 EXTERN_C_END
00141 
00142 /* implementaion */
00143 
00144 L4_INLINE l4_uint32_t
00145 l4_calibrate_tsc (void)
00146 {
00147   return l4_tsc_init(L4_TSC_INIT_AUTO);
00148 }
00149 
00150 L4_INLINE l4_cpu_time_t
00151 l4_rdtsc (void)
00152 {
00153     l4_cpu_time_t v;
00154     
00155     __asm__ __volatile__ 
00156         (".byte 0x0f, 0x31              \n\t"
00157          "mov   $0xffffffff, %%rcx      \n\t" /* clears the upper 32 bits! */
00158          "and   %%rcx,%%rax             \n\t"
00159          "shlq  $32,%%rdx               \n\t"
00160          "orq   %%rdx,%%rax             \n\t"
00161         :
00162         "=a" (v)
00163         : /* no inputs */
00164         :"rdx", "rcx"
00165         );
00166     
00167     return v;
00168 }
00169 
00170 L4_INLINE l4_cpu_time_t
00171 l4_rdpmc (int nr)
00172 {
00173     l4_cpu_time_t v;
00174     l4_uint64_t dummy;
00175 
00176     __asm__ __volatile__ (
00177          "rdpmc                         \n\t"
00178          "mov   $0xffffffff, %%rcx      \n\t" /* clears the upper 32 bits! */
00179          "and   %%rcx,%%rax             \n\t"
00180          "shlq  $32,%%rdx               \n\t"
00181          "orq   %%rdx,%%rax             \n\t"
00182         :
00183         "=a" (v), "=c"(dummy)
00184         : "c" (nr)
00185         : "rdx"
00186         );
00187 
00188     return v;
00189 }
00190 
00191 /* the same, but only 32 bit. Useful for smaller differences */
00192 L4_INLINE
00193 l4_uint32_t l4_rdpmc_32(int nr)
00194 {
00195   l4_uint32_t x;
00196   l4_uint64_t dummy;
00197 
00198   __asm__ __volatile__ (
00199          "rdpmc                         \n\t"
00200          "mov   $0xffffffff, %%rcx      \n\t" /* clears the upper 32 bits! */
00201          "and   %%rcx,%%rax             \n\t"
00202        : "=a" (x), "=c"(dummy)
00203        : "c" (nr)
00204        : "rdx");
00205 
00206   return x;
00207 }
00208 
00209 /* the same, but only 32 bit. Useful for smaller differences, 
00210    needs less cycles. */
00211 static inline 
00212 l4_uint32_t l4_rdtsc_32(void)
00213 {
00214   l4_uint32_t x;
00215 
00216   __asm__ __volatile__ (
00217        ".byte 0x0f, 0x31\n\t"   // rdtsc
00218        : "=a" (x)
00219        :
00220        : "rdx");
00221     
00222   return x;
00223 }
00224 
00225 L4_INLINE l4_uint64_t
00226 l4_tsc_to_ns (l4_cpu_time_t tsc)
00227 {
00228     l4_uint64_t ns, dummy;
00229     __asm__
00230         ("                              \n\t"
00231          "mulq  %3                      \n\t"
00232          "shrd  $27, %%rdx, %%rax       \n\t"
00233         :"=a" (ns), "=d"(dummy)
00234         :"a" (tsc), "r" ((l4_uint64_t)l4_scaler_tsc_to_ns)
00235         );
00236     return ns;
00237 }
00238 
00239 L4_INLINE l4_uint64_t
00240 l4_tsc_to_us (l4_cpu_time_t tsc)
00241 {
00242     l4_uint64_t ns, dummy;
00243     __asm__
00244         ("                              \n\t"
00245          "mulq  %3                      \n\t"
00246          "shrd  $32, %%rdx, %%rax       \n\t"
00247         :"=a" (ns), "=d" (dummy)
00248         :"a" (tsc), "r" ((l4_uint64_t)l4_scaler_tsc_to_us)
00249         );
00250     return ns;
00251 }
00252 
00253 L4_INLINE void
00254 l4_tsc_to_s_and_ns (l4_cpu_time_t tsc, l4_uint32_t *s, l4_uint32_t *ns)
00255 {
00256     __asm__
00257         ("                              \n\t"
00258          "mulq  %3                      \n\t"
00259          "shrd  $27, %%rdx, %%rax       \n\t"
00260          "xorq  %%rdx, %%rdx            \n\t"
00261          "divq  %4                      \n\t"
00262         :"=a" (*s), "=&d" (*ns)
00263         : "a" (tsc), "r" ((l4_uint64_t)l4_scaler_tsc_to_ns),
00264           "rm"(1000000000ULL)
00265         );
00266 }
00267 
00268 L4_INLINE l4_cpu_time_t
00269 l4_ns_to_tsc (l4_uint64_t ns)
00270 {
00271     l4_uint64_t tsc, dummy;
00272     __asm__
00273         ("                              \n\t"
00274          "mulq  %3                      \n\t"
00275          "shrd  $27, %%rdx, %%rax       \n\t"
00276         :"=a" (tsc), "=d" (dummy)
00277         :"a" (ns), "r" ((l4_uint64_t)l4_scaler_ns_to_tsc)
00278         );
00279     return tsc;
00280 }
00281 
00282 L4_INLINE void
00283 l4_busy_wait_ns (l4_uint64_t ns)
00284 {
00285   l4_cpu_time_t stop = l4_rdtsc();
00286   stop += l4_ns_to_tsc(ns);
00287   
00288   while (l4_rdtsc() < stop)
00289     ;
00290 }
00291 
00292 L4_INLINE void
00293 l4_busy_wait_us (l4_uint64_t us)
00294 {
00295   l4_cpu_time_t stop = l4_rdtsc ();
00296   stop += l4_ns_to_tsc(us*1000ULL);
00297   
00298   while (l4_rdtsc() < stop)
00299     ;
00300 }
00301 
00302 EXTERN_C_END
00303 
00304 #endif /* __l4_rdtsc_h */
00305 

L4 Utilities, part of DROPS  © 2000-2003