stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. |
| 3 | * |
| 4 | * Use of this source code is governed by a BSD-style license |
| 5 | * that can be found in the LICENSE file in the root of the source |
| 6 | * tree. An additional intellectual property rights grant can be found |
| 7 | * in the file PATENTS. All contributing project authors may |
| 8 | * be found in the AUTHORS file in the root of the source tree. |
| 9 | */ |
| 10 | |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 11 | #include "system_wrappers/include/clock.h" |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 12 | |
Paul Hallak | 704d6e5 | 2021-04-08 14:57:45 +0200 | [diff] [blame] | 13 | #include "system_wrappers/include/field_trial.h" |
| 14 | |
Sergey Ulanov | 6acefdb | 2017-12-11 17:38:13 -0800 | [diff] [blame] | 15 | #if defined(WEBRTC_WIN) |
Karl Wiberg | 79eb1d9 | 2017-11-08 12:26:07 +0100 | [diff] [blame] | 16 | |
pbos@webrtc.org | acaf3a1 | 2013-05-27 15:07:45 +0000 | [diff] [blame] | 17 | // Windows needs to be included before mmsystem.h |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 18 | #include "rtc_base/win32.h" |
Karl Wiberg | 79eb1d9 | 2017-11-08 12:26:07 +0100 | [diff] [blame] | 19 | |
Mirko Bonadei | 0191441 | 2018-03-23 16:30:58 +0100 | [diff] [blame] | 20 | #include <mmsystem.h> |
Karl Wiberg | 79eb1d9 | 2017-11-08 12:26:07 +0100 | [diff] [blame] | 21 | |
Yves Gerey | 988cc08 | 2018-10-23 12:03:01 +0200 | [diff] [blame] | 22 | |
Sergey Ulanov | 6acefdb | 2017-12-11 17:38:13 -0800 | [diff] [blame] | 23 | #elif defined(WEBRTC_POSIX) |
Karl Wiberg | 79eb1d9 | 2017-11-08 12:26:07 +0100 | [diff] [blame] | 24 | |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 25 | #include <sys/time.h> |
| 26 | #include <time.h> |
Karl Wiberg | 79eb1d9 | 2017-11-08 12:26:07 +0100 | [diff] [blame] | 27 | |
Sergey Ulanov | 6acefdb | 2017-12-11 17:38:13 -0800 | [diff] [blame] | 28 | #endif // defined(WEBRTC_POSIX) |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 29 | |
Markus Handell | 85585f4 | 2020-07-08 23:04:37 +0200 | [diff] [blame] | 30 | #include "rtc_base/synchronization/mutex.h" |
Steve Anton | 10542f2 | 2019-01-11 09:11:00 -0800 | [diff] [blame] | 31 | #include "rtc_base/time_utils.h" |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 32 | |
| 33 | namespace webrtc { |
Paul Hallak | 704d6e5 | 2021-04-08 14:57:45 +0200 | [diff] [blame] | 34 | namespace { |
| 35 | |
| 36 | int64_t NtpOffsetUsCalledOnce() { |
| 37 | constexpr int64_t kNtpJan1970Sec = 2208988800; |
| 38 | int64_t clock_time = rtc::TimeMicros(); |
| 39 | int64_t utc_time = rtc::TimeUTCMicros(); |
| 40 | return utc_time - clock_time + kNtpJan1970Sec * rtc::kNumMicrosecsPerSec; |
| 41 | } |
| 42 | |
| 43 | NtpTime TimeMicrosToNtp(int64_t time_us) { |
| 44 | static int64_t ntp_offset_us = NtpOffsetUsCalledOnce(); |
| 45 | |
| 46 | int64_t time_ntp_us = time_us + ntp_offset_us; |
| 47 | RTC_DCHECK_GE(time_ntp_us, 0); // Time before year 1900 is unsupported. |
| 48 | |
| 49 | // Convert seconds to uint32 through uint64 for a well-defined cast. |
| 50 | // A wrap around, which will happen in 2036, is expected for NTP time. |
| 51 | uint32_t ntp_seconds = |
| 52 | static_cast<uint64_t>(time_ntp_us / rtc::kNumMicrosecsPerSec); |
| 53 | |
| 54 | // Scale fractions of the second to NTP resolution. |
| 55 | constexpr int64_t kNtpFractionsInSecond = 1LL << 32; |
| 56 | int64_t us_fractions = time_ntp_us % rtc::kNumMicrosecsPerSec; |
| 57 | uint32_t ntp_fractions = |
| 58 | us_fractions * kNtpFractionsInSecond / rtc::kNumMicrosecsPerSec; |
| 59 | |
| 60 | return NtpTime(ntp_seconds, ntp_fractions); |
| 61 | } |
| 62 | |
| 63 | void GetSecondsAndFraction(const timeval& time, |
| 64 | uint32_t* seconds, |
| 65 | double* fraction) { |
| 66 | *seconds = time.tv_sec + kNtpJan1970; |
| 67 | *fraction = time.tv_usec / 1e6; |
| 68 | |
| 69 | while (*fraction >= 1) { |
| 70 | --*fraction; |
| 71 | ++*seconds; |
| 72 | } |
| 73 | while (*fraction < 0) { |
| 74 | ++*fraction; |
| 75 | --*seconds; |
| 76 | } |
| 77 | } |
| 78 | |
| 79 | } // namespace |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 80 | |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 81 | class RealTimeClock : public Clock { |
Paul Hallak | 704d6e5 | 2021-04-08 14:57:45 +0200 | [diff] [blame] | 82 | public: |
| 83 | RealTimeClock() |
| 84 | : use_system_independent_ntp_time_(!field_trial::IsEnabled( |
| 85 | "WebRTC-SystemIndependentNtpTimeKillSwitch")) {} |
| 86 | |
Danil Chapovalov | 0c626af | 2020-02-10 11:16:00 +0100 | [diff] [blame] | 87 | Timestamp CurrentTime() override { |
| 88 | return Timestamp::Micros(rtc::TimeMicros()); |
| 89 | } |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 90 | |
Sebastian Jansson | 2a96ab2 | 2019-01-30 20:44:45 +0100 | [diff] [blame] | 91 | NtpTime CurrentNtpTime() override { |
Paul Hallak | 704d6e5 | 2021-04-08 14:57:45 +0200 | [diff] [blame] | 92 | return use_system_independent_ntp_time_ ? TimeMicrosToNtp(rtc::TimeMicros()) |
| 93 | : SystemDependentNtpTime(); |
stefan@webrtc.org | b8e7f4c | 2013-04-12 11:56:23 +0000 | [diff] [blame] | 94 | } |
| 95 | |
Paul Hallak | b59e904 | 2021-05-20 17:21:49 +0200 | [diff] [blame] | 96 | NtpTime ConvertTimestampToNtpTime(Timestamp timestamp) override { |
Artem Titov | f067192 | 2021-07-27 12:40:17 +0200 | [diff] [blame] | 97 | // This method does not check `use_system_independent_ntp_time_` because |
| 98 | // all callers never used the old behavior of `CurrentNtpTime`. |
Paul Hallak | b59e904 | 2021-05-20 17:21:49 +0200 | [diff] [blame] | 99 | return TimeMicrosToNtp(timestamp.us()); |
| 100 | } |
| 101 | |
stefan@webrtc.org | b8e7f4c | 2013-04-12 11:56:23 +0000 | [diff] [blame] | 102 | protected: |
Sebastian Jansson | 2a96ab2 | 2019-01-30 20:44:45 +0100 | [diff] [blame] | 103 | virtual timeval CurrentTimeVal() = 0; |
stefan@webrtc.org | b8e7f4c | 2013-04-12 11:56:23 +0000 | [diff] [blame] | 104 | |
Paul Hallak | 704d6e5 | 2021-04-08 14:57:45 +0200 | [diff] [blame] | 105 | private: |
| 106 | NtpTime SystemDependentNtpTime() { |
| 107 | uint32_t seconds; |
| 108 | double fraction; |
| 109 | GetSecondsAndFraction(CurrentTimeVal(), &seconds, &fraction); |
stefan@webrtc.org | b8e7f4c | 2013-04-12 11:56:23 +0000 | [diff] [blame] | 110 | |
Paul Hallak | 704d6e5 | 2021-04-08 14:57:45 +0200 | [diff] [blame] | 111 | return NtpTime(seconds, static_cast<uint32_t>( |
| 112 | fraction * kMagicNtpFractionalUnit + 0.5)); |
stefan@webrtc.org | b8e7f4c | 2013-04-12 11:56:23 +0000 | [diff] [blame] | 113 | } |
Paul Hallak | 704d6e5 | 2021-04-08 14:57:45 +0200 | [diff] [blame] | 114 | |
| 115 | bool use_system_independent_ntp_time_; |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 116 | }; |
| 117 | |
Robin Raymond | ce1b140 | 2018-11-22 20:10:11 -0500 | [diff] [blame] | 118 | #if defined(WINUWP) |
| 119 | class WinUwpRealTimeClock final : public RealTimeClock { |
| 120 | public: |
| 121 | WinUwpRealTimeClock() = default; |
| 122 | ~WinUwpRealTimeClock() override {} |
| 123 | |
| 124 | protected: |
Sebastian Jansson | 2a96ab2 | 2019-01-30 20:44:45 +0100 | [diff] [blame] | 125 | timeval CurrentTimeVal() override { |
Johannes Kron | 373bb7b | 2021-02-23 14:23:47 +0100 | [diff] [blame] | 126 | // The rtc::WinUwpSystemTimeNanos() method is already time offset from a |
| 127 | // base epoch value and might as be synchronized against an NTP time server |
| 128 | // as an added bonus. |
| 129 | auto nanos = rtc::WinUwpSystemTimeNanos(); |
Robin Raymond | ce1b140 | 2018-11-22 20:10:11 -0500 | [diff] [blame] | 130 | |
| 131 | struct timeval tv; |
| 132 | |
| 133 | tv.tv_sec = rtc::dchecked_cast<long>(nanos / 1000000000); |
| 134 | tv.tv_usec = rtc::dchecked_cast<long>(nanos / 1000); |
| 135 | |
| 136 | return tv; |
| 137 | } |
| 138 | }; |
| 139 | |
| 140 | #elif defined(WEBRTC_WIN) |
pbos@webrtc.org | f938922 | 2015-01-21 12:51:13 +0000 | [diff] [blame] | 141 | // TODO(pbos): Consider modifying the implementation to synchronize itself |
Sebastian Jansson | 2a96ab2 | 2019-01-30 20:44:45 +0100 | [diff] [blame] | 142 | // against system time (update ref_point_) periodically to |
pbos@webrtc.org | f938922 | 2015-01-21 12:51:13 +0000 | [diff] [blame] | 143 | // prevent clock drift. |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 144 | class WindowsRealTimeClock : public RealTimeClock { |
| 145 | public: |
pbos@webrtc.org | f938922 | 2015-01-21 12:51:13 +0000 | [diff] [blame] | 146 | WindowsRealTimeClock() |
| 147 | : last_time_ms_(0), |
| 148 | num_timer_wraps_(0), |
| 149 | ref_point_(GetSystemReferencePoint()) {} |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 150 | |
Mirko Bonadei | c14d9bb | 2018-07-16 15:44:28 +0200 | [diff] [blame] | 151 | ~WindowsRealTimeClock() override {} |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 152 | |
stefan@webrtc.org | b8e7f4c | 2013-04-12 11:56:23 +0000 | [diff] [blame] | 153 | protected: |
pbos@webrtc.org | f938922 | 2015-01-21 12:51:13 +0000 | [diff] [blame] | 154 | struct ReferencePoint { |
| 155 | FILETIME file_time; |
| 156 | LARGE_INTEGER counter_ms; |
| 157 | }; |
| 158 | |
Sebastian Jansson | 2a96ab2 | 2019-01-30 20:44:45 +0100 | [diff] [blame] | 159 | timeval CurrentTimeVal() override { |
pbos@webrtc.org | 046deb9 | 2013-04-09 09:06:11 +0000 | [diff] [blame] | 160 | const uint64_t FILETIME_1970 = 0x019db1ded53e8000; |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 161 | |
| 162 | FILETIME StartTime; |
pbos@webrtc.org | 046deb9 | 2013-04-09 09:06:11 +0000 | [diff] [blame] | 163 | uint64_t Time; |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 164 | struct timeval tv; |
| 165 | |
wu@webrtc.org | 7a9a3b7 | 2014-05-29 19:40:28 +0000 | [diff] [blame] | 166 | // We can't use query performance counter since they can change depending on |
| 167 | // speed stepping. |
pbos@webrtc.org | f938922 | 2015-01-21 12:51:13 +0000 | [diff] [blame] | 168 | GetTime(&StartTime); |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 169 | |
Karl Wiberg | 79eb1d9 | 2017-11-08 12:26:07 +0100 | [diff] [blame] | 170 | Time = (((uint64_t)StartTime.dwHighDateTime) << 32) + |
| 171 | (uint64_t)StartTime.dwLowDateTime; |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 172 | |
stefan@webrtc.org | b8e7f4c | 2013-04-12 11:56:23 +0000 | [diff] [blame] | 173 | // Convert the hecto-nano second time to tv format. |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 174 | Time -= FILETIME_1970; |
| 175 | |
pbos@webrtc.org | 046deb9 | 2013-04-09 09:06:11 +0000 | [diff] [blame] | 176 | tv.tv_sec = (uint32_t)(Time / (uint64_t)10000000); |
| 177 | tv.tv_usec = (uint32_t)((Time % (uint64_t)10000000) / 10); |
stefan@webrtc.org | b8e7f4c | 2013-04-12 11:56:23 +0000 | [diff] [blame] | 178 | return tv; |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 179 | } |
wu@webrtc.org | 7a9a3b7 | 2014-05-29 19:40:28 +0000 | [diff] [blame] | 180 | |
Sebastian Jansson | 2a96ab2 | 2019-01-30 20:44:45 +0100 | [diff] [blame] | 181 | void GetTime(FILETIME* current_time) { |
pbos@webrtc.org | f938922 | 2015-01-21 12:51:13 +0000 | [diff] [blame] | 182 | DWORD t; |
| 183 | LARGE_INTEGER elapsed_ms; |
| 184 | { |
Markus Handell | 85585f4 | 2020-07-08 23:04:37 +0200 | [diff] [blame] | 185 | MutexLock lock(&mutex_); |
pbos@webrtc.org | f938922 | 2015-01-21 12:51:13 +0000 | [diff] [blame] | 186 | // time MUST be fetched inside the critical section to avoid non-monotonic |
| 187 | // last_time_ms_ values that'll register as incorrect wraparounds due to |
| 188 | // concurrent calls to GetTime. |
| 189 | t = timeGetTime(); |
| 190 | if (t < last_time_ms_) |
| 191 | num_timer_wraps_++; |
| 192 | last_time_ms_ = t; |
| 193 | elapsed_ms.HighPart = num_timer_wraps_; |
| 194 | } |
| 195 | elapsed_ms.LowPart = t; |
| 196 | elapsed_ms.QuadPart = elapsed_ms.QuadPart - ref_point_.counter_ms.QuadPart; |
| 197 | |
| 198 | // Translate to 100-nanoseconds intervals (FILETIME resolution) |
| 199 | // and add to reference FILETIME to get current FILETIME. |
| 200 | ULARGE_INTEGER filetime_ref_as_ul; |
| 201 | filetime_ref_as_ul.HighPart = ref_point_.file_time.dwHighDateTime; |
| 202 | filetime_ref_as_ul.LowPart = ref_point_.file_time.dwLowDateTime; |
| 203 | filetime_ref_as_ul.QuadPart += |
| 204 | static_cast<ULONGLONG>((elapsed_ms.QuadPart) * 1000 * 10); |
| 205 | |
| 206 | // Copy to result |
| 207 | current_time->dwHighDateTime = filetime_ref_as_ul.HighPart; |
| 208 | current_time->dwLowDateTime = filetime_ref_as_ul.LowPart; |
| 209 | } |
| 210 | |
| 211 | static ReferencePoint GetSystemReferencePoint() { |
dcheng | a771bf8 | 2015-07-01 17:52:10 -0700 | [diff] [blame] | 212 | ReferencePoint ref = {}; |
| 213 | FILETIME ft0 = {}; |
| 214 | FILETIME ft1 = {}; |
pbos@webrtc.org | f938922 | 2015-01-21 12:51:13 +0000 | [diff] [blame] | 215 | // Spin waiting for a change in system time. As soon as this change happens, |
| 216 | // get the matching call for timeGetTime() as soon as possible. This is |
| 217 | // assumed to be the most accurate offset that we can get between |
| 218 | // timeGetTime() and system time. |
| 219 | |
| 220 | // Set timer accuracy to 1 ms. |
| 221 | timeBeginPeriod(1); |
| 222 | GetSystemTimeAsFileTime(&ft0); |
| 223 | do { |
| 224 | GetSystemTimeAsFileTime(&ft1); |
| 225 | |
| 226 | ref.counter_ms.QuadPart = timeGetTime(); |
| 227 | Sleep(0); |
| 228 | } while ((ft0.dwHighDateTime == ft1.dwHighDateTime) && |
| 229 | (ft0.dwLowDateTime == ft1.dwLowDateTime)); |
| 230 | ref.file_time = ft1; |
| 231 | timeEndPeriod(1); |
| 232 | return ref; |
| 233 | } |
| 234 | |
Markus Handell | 85585f4 | 2020-07-08 23:04:37 +0200 | [diff] [blame] | 235 | Mutex mutex_; |
Sebastian Jansson | 2a96ab2 | 2019-01-30 20:44:45 +0100 | [diff] [blame] | 236 | DWORD last_time_ms_; |
| 237 | LONG num_timer_wraps_; |
pbos@webrtc.org | f938922 | 2015-01-21 12:51:13 +0000 | [diff] [blame] | 238 | const ReferencePoint ref_point_; |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 239 | }; |
| 240 | |
Sergey Ulanov | 6acefdb | 2017-12-11 17:38:13 -0800 | [diff] [blame] | 241 | #elif defined(WEBRTC_POSIX) |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 242 | class UnixRealTimeClock : public RealTimeClock { |
| 243 | public: |
| 244 | UnixRealTimeClock() {} |
| 245 | |
kjellander@webrtc.org | 14665ff | 2015-03-04 12:58:35 +0000 | [diff] [blame] | 246 | ~UnixRealTimeClock() override {} |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 247 | |
stefan@webrtc.org | b8e7f4c | 2013-04-12 11:56:23 +0000 | [diff] [blame] | 248 | protected: |
Sebastian Jansson | 2a96ab2 | 2019-01-30 20:44:45 +0100 | [diff] [blame] | 249 | timeval CurrentTimeVal() override { |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 250 | struct timeval tv; |
John Elliott | 59aba46 | 2021-10-29 11:57:15 -0700 | [diff] [blame] | 251 | gettimeofday(&tv, nullptr); |
stefan@webrtc.org | b8e7f4c | 2013-04-12 11:56:23 +0000 | [diff] [blame] | 252 | return tv; |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 253 | } |
| 254 | }; |
Sergey Ulanov | 6acefdb | 2017-12-11 17:38:13 -0800 | [diff] [blame] | 255 | #endif // defined(WEBRTC_POSIX) |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 256 | |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 257 | Clock* Clock::GetRealTimeClock() { |
Robin Raymond | ce1b140 | 2018-11-22 20:10:11 -0500 | [diff] [blame] | 258 | #if defined(WINUWP) |
| 259 | static Clock* const clock = new WinUwpRealTimeClock(); |
| 260 | #elif defined(WEBRTC_WIN) |
Mirko Bonadei | 6c092d2 | 2018-09-10 13:27:11 +0200 | [diff] [blame] | 261 | static Clock* const clock = new WindowsRealTimeClock(); |
Sergey Ulanov | 6acefdb | 2017-12-11 17:38:13 -0800 | [diff] [blame] | 262 | #elif defined(WEBRTC_POSIX) |
Mirko Bonadei | 6c092d2 | 2018-09-10 13:27:11 +0200 | [diff] [blame] | 263 | static Clock* const clock = new UnixRealTimeClock(); |
| 264 | #else |
| 265 | static Clock* const clock = nullptr; |
| 266 | #endif |
| 267 | return clock; |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 268 | } |
| 269 | |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 270 | SimulatedClock::SimulatedClock(int64_t initial_time_us) |
Niels Möller | 9308b7a | 2020-11-03 13:55:44 +0100 | [diff] [blame] | 271 | : time_us_(initial_time_us) {} |
Sebastian Jansson | 4de3115 | 2019-06-11 08:52:11 +0200 | [diff] [blame] | 272 | |
| 273 | SimulatedClock::SimulatedClock(Timestamp initial_time) |
Niels Möller | 9308b7a | 2020-11-03 13:55:44 +0100 | [diff] [blame] | 274 | : SimulatedClock(initial_time.us()) {} |
henrik.lundin@webrtc.org | 59336e8 | 2014-05-27 09:34:58 +0000 | [diff] [blame] | 275 | |
Karl Wiberg | 79eb1d9 | 2017-11-08 12:26:07 +0100 | [diff] [blame] | 276 | SimulatedClock::~SimulatedClock() {} |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 277 | |
Sebastian Jansson | 4de3115 | 2019-06-11 08:52:11 +0200 | [diff] [blame] | 278 | Timestamp SimulatedClock::CurrentTime() { |
Niels Möller | 9308b7a | 2020-11-03 13:55:44 +0100 | [diff] [blame] | 279 | return Timestamp::Micros(time_us_.load(std::memory_order_relaxed)); |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 280 | } |
| 281 | |
Paul Hallak | b59e904 | 2021-05-20 17:21:49 +0200 | [diff] [blame] | 282 | NtpTime SimulatedClock::ConvertTimestampToNtpTime(Timestamp timestamp) { |
| 283 | int64_t now_us = timestamp.us(); |
| 284 | uint32_t seconds = (now_us / 1'000'000) + kNtpJan1970; |
| 285 | uint32_t fractions = static_cast<uint32_t>( |
| 286 | (now_us % 1'000'000) * kMagicNtpFractionalUnit / 1'000'000); |
danilchap | 21dc189 | 2017-03-07 02:51:09 -0800 | [diff] [blame] | 287 | return NtpTime(seconds, fractions); |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 288 | } |
| 289 | |
stefan@webrtc.org | a678a3b | 2013-01-21 07:42:11 +0000 | [diff] [blame] | 290 | void SimulatedClock::AdvanceTimeMilliseconds(int64_t milliseconds) { |
Danil Chapovalov | 0c626af | 2020-02-10 11:16:00 +0100 | [diff] [blame] | 291 | AdvanceTime(TimeDelta::Millis(milliseconds)); |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 292 | } |
| 293 | |
stefan@webrtc.org | a678a3b | 2013-01-21 07:42:11 +0000 | [diff] [blame] | 294 | void SimulatedClock::AdvanceTimeMicroseconds(int64_t microseconds) { |
Danil Chapovalov | 0c626af | 2020-02-10 11:16:00 +0100 | [diff] [blame] | 295 | AdvanceTime(TimeDelta::Micros(microseconds)); |
Sebastian Jansson | 4de3115 | 2019-06-11 08:52:11 +0200 | [diff] [blame] | 296 | } |
| 297 | |
Niels Möller | 9308b7a | 2020-11-03 13:55:44 +0100 | [diff] [blame] | 298 | // TODO(bugs.webrtc.org(12102): It's desirable to let a single thread own |
| 299 | // advancement of the clock. We could then replace this read-modify-write |
| 300 | // operation with just a thread checker. But currently, that breaks a couple of |
| 301 | // tests, in particular, RepeatingTaskTest.ClockIntegration and |
| 302 | // CallStatsTest.LastProcessedRtt. |
Sebastian Jansson | 4de3115 | 2019-06-11 08:52:11 +0200 | [diff] [blame] | 303 | void SimulatedClock::AdvanceTime(TimeDelta delta) { |
Niels Möller | 9308b7a | 2020-11-03 13:55:44 +0100 | [diff] [blame] | 304 | time_us_.fetch_add(delta.us(), std::memory_order_relaxed); |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 305 | } |
| 306 | |
Nico Weber | 22f9925 | 2019-02-20 10:13:16 -0500 | [diff] [blame] | 307 | } // namespace webrtc |