Commit 4749ccd4 authored by gejun's avatar gejun

Workaround of the bug of gcc345 met by cpuwide_time_ns()

parent 633d8a3c
...@@ -39,6 +39,8 @@ int64_t monotonic_time_ns() { ...@@ -39,6 +39,8 @@ int64_t monotonic_time_ns() {
return now.tv_sec * 1000000000L + now.tv_nsec; return now.tv_sec * 1000000000L + now.tv_nsec;
} }
namespace detail {
// read_cpu_frequency() is modified from source code of glibc. // read_cpu_frequency() is modified from source code of glibc.
int64_t read_cpu_frequency(bool* invariant_tsc) { int64_t read_cpu_frequency(bool* invariant_tsc) {
/* We read the information from the /proc filesystem. It contains at /* We read the information from the /proc filesystem. It contains at
...@@ -109,5 +111,6 @@ int64_t read_invariant_cpu_frequency() { ...@@ -109,5 +111,6 @@ int64_t read_invariant_cpu_frequency() {
} }
int64_t invariant_cpu_freq = -1; int64_t invariant_cpu_freq = -1;
} // namespace detail
} // namespace butil } // namespace butil
...@@ -210,6 +210,11 @@ inline uint64_t clock_cycles() { ...@@ -210,6 +210,11 @@ inline uint64_t clock_cycles() {
); );
return ((uint64_t)hi << 32) | lo; return ((uint64_t)hi << 32) | lo;
} }
extern int64_t read_invariant_cpu_frequency();
// Be positive iff:
// 1 Intel x86_64 CPU (multiple cores) supporting constant_tsc and
// nonstop_tsc(check flags in /proc/cpuinfo)
extern int64_t invariant_cpu_freq;
} // namespace detail } // namespace detail
// --------------------------------------------------------------- // ---------------------------------------------------------------
...@@ -219,25 +224,19 @@ inline uint64_t clock_cycles() { ...@@ -219,25 +224,19 @@ inline uint64_t clock_cycles() {
// note: Inlining shortens time cost per-call for 15ns in a loop of many // note: Inlining shortens time cost per-call for 15ns in a loop of many
// calls to this function. // calls to this function.
inline int64_t cpuwide_time_ns() { inline int64_t cpuwide_time_ns() {
extern int64_t read_invariant_cpu_frequency(); if (detail::invariant_cpu_freq > 0) {
// Be positive iff:
// 1 Intel x86_64 CPU (multiple cores) supporting constant_tsc and
// nonstop_tsc(check flags in /proc/cpuinfo)
extern int64_t invariant_cpu_freq;
if (invariant_cpu_freq > 0) {
const uint64_t tsc = detail::clock_cycles(); const uint64_t tsc = detail::clock_cycles();
const uint64_t sec = tsc / invariant_cpu_freq; const uint64_t sec = tsc / detail::invariant_cpu_freq;
// TODO: should be OK until CPU's frequency exceeds 16GHz. // TODO: should be OK until CPU's frequency exceeds 16GHz.
return (tsc - sec * invariant_cpu_freq) * 1000000000L / return (tsc - sec * detail::invariant_cpu_freq) * 1000000000L /
invariant_cpu_freq + sec * 1000000000L; detail::invariant_cpu_freq + sec * 1000000000L;
} else if (!invariant_cpu_freq) { } else if (!detail::invariant_cpu_freq) {
// Lack of necessary features, return system-wide monotonic time instead. // Lack of necessary features, return system-wide monotonic time instead.
return monotonic_time_ns(); return monotonic_time_ns();
} else { } else {
// Use a thread-unsafe method(OK to us) to initialize the freq // Use a thread-unsafe method(OK to us) to initialize the freq
// to save a "if" test comparing to using a local static variable // to save a "if" test comparing to using a local static variable
invariant_cpu_freq = read_invariant_cpu_frequency(); detail::invariant_cpu_freq = detail::read_invariant_cpu_frequency();
return cpuwide_time_ns(); return cpuwide_time_ns();
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment