Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / common / Cycles.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
2 // vim: ts=8 sw=2 smarttab
3 /*
4  * Ceph - scalable distributed file system
5  *
6  * Copyright (C) 2014 UnitedStack <haomai@unitedstack.com>
7  *
8  * Author: Haomai Wang <haomaiwang@gmail.com>
9  *
10  * This is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public
12  * License version 2.1, as published by the Free Software
13  * Foundation.  See file COPYING.
14  *
15  */
16 /* Copyright (c) 2011-2014 Stanford University
17  *
18  * Permission to use, copy, modify, and distribute this software for any
19  * purpose with or without fee is hereby granted, provided that the above
20  * copyright notice and this permission notice appear in all copies.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES
23  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
24  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR
25  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
26  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
27  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
28  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29  */
30
31
32 #ifndef CEPH_CYCLES_H
33 #define CEPH_CYCLES_H
34
35 /**
36  * This class provides static methods that read the fine-grain CPU
37  * cycle counter and translate between cycle-level times and absolute
38  * times.
39  */
40 class Cycles {
41  public:
42   static void init();
43
44   /**
45    * Return the current value of the fine-grain CPU cycle counter
46    * (accessed via the RDTSC instruction).
47    */
48   static __inline __attribute__((always_inline)) uint64_t rdtsc() {
49 #if defined(__i386__)
50     int64_t ret;
51     __asm__ volatile ("rdtsc" : "=A" (ret) );
52     return ret;
53 #elif defined(__x86_64__) || defined(__amd64__)
54     uint32_t lo, hi;
55     __asm__ __volatile__("rdtsc" : "=a" (lo), "=d" (hi));
56     return (((uint64_t)hi << 32) | lo);
57 #elif defined(__aarch64__)
58     //
59     // arch/arm64/include/asm/arch_timer.h
60     //
61     // static inline u64 arch_counter_get_cntvct(void)
62     // {
63     //         u64 cval;
64     // 
65     //         isb();
66     //         asm volatile("mrs %0, cntvct_el0" : "=r" (cval));
67     // 
68     //         return cval;
69     // }
70     //
71     // https://github.com/cloudius-systems/osv/blob/master/arch/aarch64/arm-clock.cc
72     uint64_t cntvct;
73     asm volatile ("isb; mrs %0, cntvct_el0; isb; " : "=r" (cntvct) :: "memory");
74     return cntvct;
75 #elif defined(__powerpc__) || defined (__powerpc64__)
76     // Based on:
77     // https://github.com/randombit/botan/blob/net.randombit.botan/src/lib/entropy/hres_timer/hres_timer.cpp
78     uint32_t lo = 0, hi = 0;
79     asm volatile("mftbu %0; mftb %1" : "=r" (hi), "=r" (lo));
80     return (((uint64_t)hi << 32) | lo);
81 #else
82 #warning No high-precision counter available for your OS/arch
83     return 0;
84 #endif
85   }
86
87   static double per_second();
88   static double to_seconds(uint64_t cycles, double cycles_per_sec = 0);
89   static uint64_t from_seconds(double seconds, double cycles_per_sec = 0);
90   static uint64_t to_microseconds(uint64_t cycles, double cycles_per_sec = 0);
91   static uint64_t to_nanoseconds(uint64_t cycles, double cycles_per_sec = 0);
92   static uint64_t from_nanoseconds(uint64_t ns, double cycles_per_sec = 0);
93   static void sleep(uint64_t us);
94
95 private:
96   Cycles();
97
98   /// Conversion factor between cycles and the seconds; computed by
99   /// Cycles::init.
100   static double cycles_per_sec;
101
102   /**
103    * Returns the conversion factor between cycles in seconds, using
104    * a mock value for testing when appropriate.
105    */
106   static __inline __attribute__((always_inline)) double get_cycles_per_sec() {
107     return cycles_per_sec;
108   }
109 };
110
111 #endif  // CEPH_CYCLES_H