* Implement WindowsRealTimeClock::CurrentTimeVal with GetSystemTimeAsFileTime as it supposes to return a POSIX gettimeofday, so that later it can be converted to NTP timee correctly.

* Updated to ClockTest.NtpTime to verify the returned NTP is at least larger than kNtpJan1970.

Current implementation uses timeGetTime, which returns the time since windows is started, which can't be converted to NTP time.

BUG=3325
R=pwestin@webrtc.org

Review URL: https://webrtc-codereview.appspot.com/16509004

git-svn-id: http://webrtc.googlecode.com/svn/trunk@6178 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
wu@webrtc.org 2014-05-15 23:54:14 +00:00
parent bf58a75dd9
commit 75718cf80a
2 changed files with 4 additions and 109 deletions

View File

@ -32,99 +32,6 @@ int64_t Clock::NtpToMs(uint32_t ntp_secs, uint32_t ntp_frac) {
static_cast<int64_t>(ntp_frac_ms + 0.5);
}
#if defined(_WIN32)
struct reference_point {
FILETIME file_time;
LARGE_INTEGER counterMS;
};
struct WindowsHelpTimer {
volatile LONG _timeInMs;
volatile LONG _numWrapTimeInMs;
reference_point _ref_point;
volatile LONG _sync_flag;
};
void Synchronize(WindowsHelpTimer* help_timer) {
const LONG start_value = 0;
const LONG new_value = 1;
const LONG synchronized_value = 2;
LONG compare_flag = new_value;
while (help_timer->_sync_flag == start_value) {
const LONG new_value = 1;
compare_flag = InterlockedCompareExchange(
&help_timer->_sync_flag, new_value, start_value);
}
if (compare_flag != start_value) {
// This thread was not the one that incremented the sync flag.
// Block until synchronization finishes.
while (compare_flag != synchronized_value) {
::Sleep(0);
}
return;
}
// Only the synchronizing thread gets here so this part can be
// considered single threaded.
// set timer accuracy to 1 ms
timeBeginPeriod(1);
FILETIME ft0 = { 0, 0 },
ft1 = { 0, 0 };
//
// Spin waiting for a change in system time. Get the matching
// performance counter value for that time.
//
::GetSystemTimeAsFileTime(&ft0);
do {
::GetSystemTimeAsFileTime(&ft1);
help_timer->_ref_point.counterMS.QuadPart = ::timeGetTime();
::Sleep(0);
} while ((ft0.dwHighDateTime == ft1.dwHighDateTime) &&
(ft0.dwLowDateTime == ft1.dwLowDateTime));
help_timer->_ref_point.file_time = ft1;
timeEndPeriod(1);
}
void get_time(WindowsHelpTimer* help_timer, FILETIME& current_time) {
// we can't use query performance counter due to speed stepping
DWORD t = timeGetTime();
// NOTE: we have a missmatch in sign between _timeInMs(LONG) and
// (DWORD) however we only use it here without +- etc
volatile LONG* timeInMsPtr = &help_timer->_timeInMs;
// Make sure that we only inc wrapper once.
DWORD old = InterlockedExchange(timeInMsPtr, t);
if(old > t) {
// wrap
help_timer->_numWrapTimeInMs++;
}
LARGE_INTEGER elapsedMS;
elapsedMS.HighPart = help_timer->_numWrapTimeInMs;
elapsedMS.LowPart = t;
elapsedMS.QuadPart = elapsedMS.QuadPart -
help_timer->_ref_point.counterMS.QuadPart;
// Translate to 100-nanoseconds intervals (FILETIME resolution)
// and add to reference FILETIME to get current FILETIME.
ULARGE_INTEGER filetime_ref_as_ul;
filetime_ref_as_ul.HighPart =
help_timer->_ref_point.file_time.dwHighDateTime;
filetime_ref_as_ul.LowPart =
help_timer->_ref_point.file_time.dwLowDateTime;
filetime_ref_as_ul.QuadPart +=
(ULONGLONG)((elapsedMS.QuadPart)*1000*10);
// Copy to result
current_time.dwHighDateTime = filetime_ref_as_ul.HighPart;
current_time.dwLowDateTime = filetime_ref_as_ul.LowPart;
}
#endif
class RealTimeClock : public Clock {
// Return a timestamp in milliseconds relative to some arbitrary source; the
// source is fixed for this clock.
@ -178,8 +85,7 @@ class RealTimeClock : public Clock {
#if defined(_WIN32)
class WindowsRealTimeClock : public RealTimeClock {
public:
WindowsRealTimeClock(WindowsHelpTimer* helpTimer)
: _helpTimer(helpTimer) {}
WindowsRealTimeClock() {}
virtual ~WindowsRealTimeClock() {}
@ -191,9 +97,7 @@ class WindowsRealTimeClock : public RealTimeClock {
uint64_t Time;
struct timeval tv;
// We can't use query performance counter since they can change depending on
// speed stepping.
get_time(_helpTimer, StartTime);
GetSystemTimeAsFileTime(&StartTime);
Time = (((uint64_t) StartTime.dwHighDateTime) << 32) +
(uint64_t) StartTime.dwLowDateTime;
@ -205,8 +109,6 @@ class WindowsRealTimeClock : public RealTimeClock {
tv.tv_usec = (uint32_t)((Time % (uint64_t)10000000) / 10);
return tv;
}
WindowsHelpTimer* _helpTimer;
};
#elif ((defined WEBRTC_LINUX) || (defined WEBRTC_MAC))
@ -228,17 +130,9 @@ class UnixRealTimeClock : public RealTimeClock {
};
#endif
#if defined(_WIN32)
// Keeps the global state for the Windows implementation of RtpRtcpClock.
// Note that this is a POD. Only PODs are allowed to have static storage
// duration according to the Google Style guide.
static WindowsHelpTimer global_help_timer = {0, 0, {{ 0, 0}, 0}, 0};
#endif
Clock* Clock::GetRealTimeClock() {
#if defined(_WIN32)
static WindowsRealTimeClock clock(&global_help_timer);
static WindowsRealTimeClock clock;
return &clock;
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
static UnixRealTimeClock clock;

View File

@ -20,6 +20,7 @@ TEST(ClockTest, NtpTime) {
uint32_t fractions;
clock->CurrentNtp(seconds, fractions);
int64_t milliseconds = clock->CurrentNtpInMilliseconds();
EXPECT_GT(milliseconds / 1000, kNtpJan1970);
EXPECT_GE(milliseconds, Clock::NtpToMs(seconds, fractions));
EXPECT_NEAR(milliseconds, Clock::NtpToMs(seconds, fractions), 5);
}