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() {
return now.tv_sec * 1000000000L + now.tv_nsec;
}
namespace detail {
// read_cpu_frequency() is modified from source code of glibc.
int64_t read_cpu_frequency(bool* invariant_tsc) {
/* We read the information from the /proc filesystem. It contains at
......@@ -109,5 +111,6 @@ int64_t read_invariant_cpu_frequency() {
}
int64_t invariant_cpu_freq = -1;
} // namespace detail
} // namespace butil
......@@ -210,6 +210,11 @@ inline uint64_t clock_cycles() {
);
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
// ---------------------------------------------------------------
......@@ -219,25 +224,19 @@ inline uint64_t clock_cycles() {
// note: Inlining shortens time cost per-call for 15ns in a loop of many
// calls to this function.
inline int64_t cpuwide_time_ns() {
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;
if (invariant_cpu_freq > 0) {
if (detail::invariant_cpu_freq > 0) {
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.
return (tsc - sec * invariant_cpu_freq) * 1000000000L /
invariant_cpu_freq + sec * 1000000000L;
} else if (!invariant_cpu_freq) {
return (tsc - sec * detail::invariant_cpu_freq) * 1000000000L /
detail::invariant_cpu_freq + sec * 1000000000L;
} else if (!detail::invariant_cpu_freq) {
// Lack of necessary features, return system-wide monotonic time instead.
return monotonic_time_ns();
} else {
// Use a thread-unsafe method(OK to us) to initialize the freq
// 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();
}
}
......
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