0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-30 17:10:48 +01:00

SERVER-13792 added runtime and build-time checks for POSIX monotonic clocks. de-inlined Timer::now() implementations

This commit is contained in:
Benety Goh 2014-06-03 16:52:03 -04:00
parent c4fa4dc85a
commit ffaa85ae89
7 changed files with 97 additions and 236 deletions

View File

@ -1343,6 +1343,32 @@ def doConfigure(myenv):
posix_system = conf.CheckPosixSystem()
conf.Finish()
# Check if we are on a system that support the POSIX clock_gettime function
# and the "monotonic" clock.
posix_monotonic_clock = False
if posix_system:
def CheckPosixMonotonicClock(context):
test_body = """
#include <unistd.h>
#if !(defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0)
#error POSIX clock_gettime not supported
#elif !(defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0)
#error POSIX monotonic clock not supported
#endif
"""
context.Message('Checking if the POSIX monotonic clock is supported... ')
ret = context.TryCompile(textwrap.dedent(test_body), ".c")
context.Result(ret)
return ret
conf = Configure(myenv, help=False, custom_tests = {
'CheckPosixMonotonicClock' : CheckPosixMonotonicClock,
})
posix_monotonic_clock = conf.CheckPosixMonotonicClock()
conf.Finish()
if has_option('sanitize'):
if not (using_clang() or using_gcc()):
@ -1615,6 +1641,9 @@ def doConfigure(myenv):
conf.CheckLib('rt')
conf.CheckLib('dl')
if posix_monotonic_clock:
conf.env.Append(CPPDEFINES=['MONGO_HAVE_POSIX_MONOTONIC_CLOCK'])
if (conf.CheckCXXHeader( "execinfo.h" ) and
conf.CheckDeclaration('backtrace', includes='#include <execinfo.h>') and
conf.CheckDeclaration('backtrace_symbols', includes='#include <execinfo.h>') and

View File

@ -1,49 +0,0 @@
// @file mongo/util/timer-generic-inl.h
/* Copyright 2010 10gen Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the GNU Affero General Public License in all respects
* for all of the code used other than as permitted herein. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you do not
* wish to do so, delete this exception statement from your version. If you
* delete this exception statement from all source files in the program,
* then also delete it in the license file.
*/
/**
* Inline function implementations for the "generic" implementation of the
* Timer class. This implementation often has pretty poor resolution, but is available
* on all supported platforms.
*
* This file should only be included through timer-inl.h, which selects the
* particular implementation based on target platform.
*/
#pragma once
#define MONGO_TIMER_IMPL_GENERIC
#include "mongo/util/time_support.h"
namespace mongo {
long long Timer::now() const { return curTimeMicros64(); }
} // namespace mongo

View File

@ -1,60 +0,0 @@
// @file mongo/util/timer-inl.h
/* Copyright 2010 10gen Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the GNU Affero General Public License in all respects
* for all of the code used other than as permitted herein. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you do not
* wish to do so, delete this exception statement from your version. If you
* delete this exception statement from all source files in the program,
* then also delete it in the license file.
*/
/**
* Inline function implementations for the Timer class. This file simply selects
* the platform-appropriate inline functions to include.
*
* This file should only be included through timer-inl.h, which selects the
* particular implementation based on target platform.
*/
#pragma once
#if defined(MONGO_HAVE_HEADER_UNISTD_H)
#include <unistd.h>
#endif
#if defined(_WIN32)
// On Windows, prefer the Windows-specific implementation, which employs QueryPerformanceCounter.
#include "mongo/util/timer-win32-inl.h"
#elif defined(_POSIX_TIMERS) and _POSIX_TIMERS > 0 and defined(_POSIX_MONOTONIC_CLOCK) and _POSIX_MONOTONIC_CLOCK > 0
// On systems that support the POSIX clock_gettime function, and the "monotonic" clock,
// use those.
#include "mongo/util/timer-posixclock-inl.h"
#else
// If all else fails, fall back to a generic implementation. Performance may suffer.
#include "mongo/util/timer-generic-inl.h"
#endif

View File

@ -1,58 +0,0 @@
/* Copyright 2010 10gen Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the GNU Affero General Public License in all respects
* for all of the code used other than as permitted herein. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you do not
* wish to do so, delete this exception statement from your version. If you
* delete this exception statement from all source files in the program,
* then also delete it in the license file.
*/
/**
* Inline function implementations for timers on systems that support the
* POSIX clock API and CLOCK_MONOTONIC clock.
*
* This file should only be included through timer-inl.h, which selects the
* particular implementation based on target platform.
*/
#define MONGO_TIMER_IMPL_POSIX_MONOTONIC_CLOCK
#include <ctime>
#include "mongo/util/assert_util.h"
namespace mongo {
long long Timer::now() const {
timespec the_time;
long long result;
fassert(16160, !clock_gettime(CLOCK_MONOTONIC, &the_time));
// Safe for 292 years after the clock epoch, even if we switch to a signed time value. On
// Linux, the monotonic clock's epoch is the UNIX epoch.
result = static_cast<long long>(the_time.tv_sec);
result *= nanosPerSecond;
result += static_cast<long long>(the_time.tv_nsec);
return result;
}
} // namespace mongo

View File

@ -1,54 +0,0 @@
// @file mongo/util/timer-win32-inl.h
/* Copyright 2010 10gen Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the GNU Affero General Public License in all respects
* for all of the code used other than as permitted herein. If you modify
* file(s) with this exception, you may extend this exception to your
* version of the file(s), but you are not obligated to do so. If you do not
* wish to do so, delete this exception statement from your version. If you
* delete this exception statement from all source files in the program,
* then also delete it in the license file.
*/
/**
* Inline function implementations for the Windows-specific implementation of the
* Timer class. Windows selects the best available timer, in its estimation, for
* measuring time at high resolution. This may be the HPET of the TSC on x86 systems,
* but is promised to be synchronized across processors, barring BIOS errors.
*
* Do not include directly. Include "mongo/util/timer.h".
*/
#pragma once
#define MONGO_TIMER_IMPL_WIN32
#include "mongo/platform/windows_basic.h"
#include "mongo/util/assert_util.h"
namespace mongo {
long long Timer::now() const {
LARGE_INTEGER i;
fassert(16161, QueryPerformanceCounter(&i));
return i.QuadPart;
}
} // namespace mongo

View File

@ -27,14 +27,25 @@
* then also delete it in the license file.
*/
#include "mongo/platform/basic.h"
#include "mongo/util/timer.h"
#include <ctime>
#include <limits>
#if defined(MONGO_HAVE_HEADER_UNISTD_H)
#include <unistd.h>
#endif
#include "mongo/util/assert_util.h"
#include "mongo/util/time_support.h"
namespace mongo {
// default value of 1 so that during startup initialization if referenced no division by zero
long long Timer::_countsPerSecond = 1;
// Set default value to reflect "generic" timer implementation.
// Define Timer::_countsPerSecond before static initializer "atstartuputil" to ensure correct
// relative sequencing regardless of how _countsPerSecond is initialized (static or dynamic).
long long Timer::_countsPerSecond = Timer::microsPerSecond;
namespace {
@ -43,19 +54,66 @@ namespace mongo {
AtStartup();
} atstartuputil;
#if defined(MONGO_TIMER_IMPL_WIN32)
// "Generic" implementation for Timer::now().
long long _timerNowGeneric() {
return curTimeMicros64();
}
// Function pointer to Timer::now() implementation.
// Overridden in AtStartup() with better implementation where available.
long long (*_timerNow)() = &_timerNowGeneric;
#if defined(_WIN32)
/**
* Windows-specific implementation of the
* Timer class. Windows selects the best available timer, in its estimation, for
* measuring time at high resolution. This may be the HPET of the TSC on x86 systems,
* but is promised to be synchronized across processors, barring BIOS errors.
*/
long long timerNowWindows() {
LARGE_INTEGER i;
fassert(16161, QueryPerformanceCounter(&i));
return i.QuadPart;
}
AtStartup::AtStartup() {
LARGE_INTEGER x;
bool ok = QueryPerformanceFrequency(&x);
verify(ok);
Timer::_countsPerSecond = x.QuadPart;
_timerNow = &timerNowWindows;
}
#elif defined(MONGO_TIMER_IMPL_POSIX_MONOTONIC_CLOCK)
#elif defined(MONGO_HAVE_POSIX_MONOTONIC_CLOCK)
/**
* Implementation for timer on systems that support the
* POSIX clock API and CLOCK_MONOTONIC clock.
*/
long long timerNowPosixMonotonicClock() {
timespec the_time;
long long result;
fassert(16160, !clock_gettime(CLOCK_MONOTONIC, &the_time));
// Safe for 292 years after the clock epoch, even if we switch to a signed time value.
// On Linux, the monotonic clock's epoch is the UNIX epoch.
result = static_cast<long long>(the_time.tv_sec);
result *= Timer::nanosPerSecond;
result += static_cast<long long>(the_time.tv_nsec);
return result;
}
AtStartup::AtStartup() {
// If the monotonic clock is not available at runtime (sysconf() returns 0 or -1),
// do not override the generic implementation or modify Timer::_countsPerSecond.
if (sysconf(_SC_MONOTONIC_CLOCK) <= 0) {
return;
}
Timer::_countsPerSecond = Timer::nanosPerSecond;
_timerNow = &timerNowPosixMonotonicClock;
// Make sure that the current time relative to the (unspecified) epoch isn't already too
// big to represent as a 64-bit count of nanoseconds.
@ -65,17 +123,14 @@ namespace mongo {
fassert(16162, !clock_gettime(CLOCK_MONOTONIC, &the_time));
fassert(16163, static_cast<long long>(the_time.tv_sec) < maxSecs);
}
#elif defined(MONGO_TIMER_IMPL_GENERIC)
AtStartup::AtStartup() {
Timer::_countsPerSecond = Timer::microsPerSecond;
}
#else
#error "Unknown mongo::Timer implementation"
AtStartup::AtStartup() { }
#endif
} // namespace
long long Timer::now() const {
return _timerNow();
}
} // namespace mongo

View File

@ -85,10 +85,8 @@ namespace mongo {
static long long _countsPerSecond;
private:
inline long long now() const;
long long now() const;
long long _old;
};
} // namespace mongo
#include "mongo/util/timer-inl.h"