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:
parent
c4fa4dc85a
commit
ffaa85ae89
29
SConstruct
29
SConstruct
@ -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
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user