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 | |
Steve Anton | 10542f2 | 2019-01-11 09:11:00 -0800 | [diff] [blame] | 13 | #include "rtc_base/time_utils.h" |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 14 | |
| 15 | namespace webrtc { |
Paul Hallak | 704d6e5 | 2021-04-08 14:57:45 +0200 | [diff] [blame] | 16 | namespace { |
| 17 | |
| 18 | int64_t NtpOffsetUsCalledOnce() { |
| 19 | constexpr int64_t kNtpJan1970Sec = 2208988800; |
| 20 | int64_t clock_time = rtc::TimeMicros(); |
| 21 | int64_t utc_time = rtc::TimeUTCMicros(); |
| 22 | return utc_time - clock_time + kNtpJan1970Sec * rtc::kNumMicrosecsPerSec; |
| 23 | } |
| 24 | |
| 25 | NtpTime TimeMicrosToNtp(int64_t time_us) { |
| 26 | static int64_t ntp_offset_us = NtpOffsetUsCalledOnce(); |
| 27 | |
| 28 | int64_t time_ntp_us = time_us + ntp_offset_us; |
| 29 | RTC_DCHECK_GE(time_ntp_us, 0); // Time before year 1900 is unsupported. |
| 30 | |
| 31 | // Convert seconds to uint32 through uint64 for a well-defined cast. |
| 32 | // A wrap around, which will happen in 2036, is expected for NTP time. |
| 33 | uint32_t ntp_seconds = |
| 34 | static_cast<uint64_t>(time_ntp_us / rtc::kNumMicrosecsPerSec); |
| 35 | |
| 36 | // Scale fractions of the second to NTP resolution. |
| 37 | constexpr int64_t kNtpFractionsInSecond = 1LL << 32; |
| 38 | int64_t us_fractions = time_ntp_us % rtc::kNumMicrosecsPerSec; |
| 39 | uint32_t ntp_fractions = |
| 40 | us_fractions * kNtpFractionsInSecond / rtc::kNumMicrosecsPerSec; |
| 41 | |
| 42 | return NtpTime(ntp_seconds, ntp_fractions); |
| 43 | } |
| 44 | |
Paul Hallak | 704d6e5 | 2021-04-08 14:57:45 +0200 | [diff] [blame] | 45 | } // namespace |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 46 | |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 47 | class RealTimeClock : public Clock { |
Paul Hallak | 704d6e5 | 2021-04-08 14:57:45 +0200 | [diff] [blame] | 48 | public: |
Danil Chapovalov | fbe6672 | 2022-05-11 13:59:57 +0200 | [diff] [blame^] | 49 | RealTimeClock() = default; |
Paul Hallak | 704d6e5 | 2021-04-08 14:57:45 +0200 | [diff] [blame] | 50 | |
Danil Chapovalov | 0c626af | 2020-02-10 11:16:00 +0100 | [diff] [blame] | 51 | Timestamp CurrentTime() override { |
| 52 | return Timestamp::Micros(rtc::TimeMicros()); |
| 53 | } |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 54 | |
Paul Hallak | b59e904 | 2021-05-20 17:21:49 +0200 | [diff] [blame] | 55 | NtpTime ConvertTimestampToNtpTime(Timestamp timestamp) override { |
Paul Hallak | b59e904 | 2021-05-20 17:21:49 +0200 | [diff] [blame] | 56 | return TimeMicrosToNtp(timestamp.us()); |
| 57 | } |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 58 | }; |
| 59 | |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 60 | Clock* Clock::GetRealTimeClock() { |
Danil Chapovalov | fbe6672 | 2022-05-11 13:59:57 +0200 | [diff] [blame^] | 61 | static Clock* const clock = new RealTimeClock(); |
Mirko Bonadei | 6c092d2 | 2018-09-10 13:27:11 +0200 | [diff] [blame] | 62 | return clock; |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 63 | } |
| 64 | |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 65 | SimulatedClock::SimulatedClock(int64_t initial_time_us) |
Niels Möller | 9308b7a | 2020-11-03 13:55:44 +0100 | [diff] [blame] | 66 | : time_us_(initial_time_us) {} |
Sebastian Jansson | 4de3115 | 2019-06-11 08:52:11 +0200 | [diff] [blame] | 67 | |
| 68 | SimulatedClock::SimulatedClock(Timestamp initial_time) |
Niels Möller | 9308b7a | 2020-11-03 13:55:44 +0100 | [diff] [blame] | 69 | : SimulatedClock(initial_time.us()) {} |
henrik.lundin@webrtc.org | 59336e8 | 2014-05-27 09:34:58 +0000 | [diff] [blame] | 70 | |
Karl Wiberg | 79eb1d9 | 2017-11-08 12:26:07 +0100 | [diff] [blame] | 71 | SimulatedClock::~SimulatedClock() {} |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 72 | |
Sebastian Jansson | 4de3115 | 2019-06-11 08:52:11 +0200 | [diff] [blame] | 73 | Timestamp SimulatedClock::CurrentTime() { |
Niels Möller | 9308b7a | 2020-11-03 13:55:44 +0100 | [diff] [blame] | 74 | return Timestamp::Micros(time_us_.load(std::memory_order_relaxed)); |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 75 | } |
| 76 | |
Paul Hallak | b59e904 | 2021-05-20 17:21:49 +0200 | [diff] [blame] | 77 | NtpTime SimulatedClock::ConvertTimestampToNtpTime(Timestamp timestamp) { |
| 78 | int64_t now_us = timestamp.us(); |
| 79 | uint32_t seconds = (now_us / 1'000'000) + kNtpJan1970; |
| 80 | uint32_t fractions = static_cast<uint32_t>( |
| 81 | (now_us % 1'000'000) * kMagicNtpFractionalUnit / 1'000'000); |
danilchap | 21dc189 | 2017-03-07 02:51:09 -0800 | [diff] [blame] | 82 | return NtpTime(seconds, fractions); |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 83 | } |
| 84 | |
stefan@webrtc.org | a678a3b | 2013-01-21 07:42:11 +0000 | [diff] [blame] | 85 | void SimulatedClock::AdvanceTimeMilliseconds(int64_t milliseconds) { |
Danil Chapovalov | 0c626af | 2020-02-10 11:16:00 +0100 | [diff] [blame] | 86 | AdvanceTime(TimeDelta::Millis(milliseconds)); |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 87 | } |
| 88 | |
stefan@webrtc.org | a678a3b | 2013-01-21 07:42:11 +0000 | [diff] [blame] | 89 | void SimulatedClock::AdvanceTimeMicroseconds(int64_t microseconds) { |
Danil Chapovalov | 0c626af | 2020-02-10 11:16:00 +0100 | [diff] [blame] | 90 | AdvanceTime(TimeDelta::Micros(microseconds)); |
Sebastian Jansson | 4de3115 | 2019-06-11 08:52:11 +0200 | [diff] [blame] | 91 | } |
| 92 | |
Niels Möller | 9308b7a | 2020-11-03 13:55:44 +0100 | [diff] [blame] | 93 | // TODO(bugs.webrtc.org(12102): It's desirable to let a single thread own |
| 94 | // advancement of the clock. We could then replace this read-modify-write |
| 95 | // operation with just a thread checker. But currently, that breaks a couple of |
| 96 | // tests, in particular, RepeatingTaskTest.ClockIntegration and |
| 97 | // CallStatsTest.LastProcessedRtt. |
Sebastian Jansson | 4de3115 | 2019-06-11 08:52:11 +0200 | [diff] [blame] | 98 | void SimulatedClock::AdvanceTime(TimeDelta delta) { |
Niels Möller | 9308b7a | 2020-11-03 13:55:44 +0100 | [diff] [blame] | 99 | time_us_.fetch_add(delta.us(), std::memory_order_relaxed); |
stefan@webrtc.org | 20ed36d | 2013-01-17 14:01:20 +0000 | [diff] [blame] | 100 | } |
| 101 | |
Nico Weber | 22f9925 | 2019-02-20 10:13:16 -0500 | [diff] [blame] | 102 | } // namespace webrtc |