blob: e2287e9137a0ce58e9382c286e13f09d56d4907b [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
vasilvv89713d02020-02-11 14:33:26 -08005#include "net/third_party/quiche/src/quic/core/quic_clock.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -05006
7#include <limits>
8
dmcardlec97eba62020-01-06 10:39:01 -08009#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050010
11namespace quic {
12
13QuicClock::QuicClock()
14 : is_calibrated_(false), calibration_offset_(QuicTime::Delta::Zero()) {}
15
16QuicClock::~QuicClock() {}
17
18QuicTime::Delta QuicClock::ComputeCalibrationOffset() const {
19 // In the ideal world, all we need to do is to return the difference of
20 // WallNow() and Now(). In the real world, things like context switch may
21 // happen between the calls to WallNow() and Now(), causing their difference
22 // to be arbitrarily large, so we repeat the calculation many times and use
23 // the one with the minimum difference as the true offset.
24 int64_t min_offset_us = std::numeric_limits<int64_t>::max();
25
26 for (int i = 0; i < 128; ++i) {
27 int64_t now_in_us = (Now() - QuicTime::Zero()).ToMicroseconds();
28 int64_t wallnow_in_us =
29 static_cast<int64_t>(WallNow().ToUNIXMicroseconds());
30
31 int64_t offset_us = wallnow_in_us - now_in_us;
32 if (offset_us < min_offset_us) {
33 min_offset_us = offset_us;
34 }
35 }
36
37 return QuicTime::Delta::FromMicroseconds(min_offset_us);
38}
39
40void QuicClock::SetCalibrationOffset(QuicTime::Delta offset) {
41 DCHECK(!is_calibrated_) << "A clock should only be calibrated once";
42 calibration_offset_ = offset;
43 is_calibrated_ = true;
44}
45
46QuicTime QuicClock::ConvertWallTimeToQuicTime(
47 const QuicWallTime& walltime) const {
48 if (is_calibrated_) {
49 int64_t time_in_us = static_cast<int64_t>(walltime.ToUNIXMicroseconds()) -
50 calibration_offset_.ToMicroseconds();
51 return QuicTime::Zero() + QuicTime::Delta::FromMicroseconds(time_in_us);
52 }
53
54 // ..........................
55 // | | |
56 // unix epoch |walltime| WallNow()
57 // ..........................
58 // | | |
59 // clock epoch | Now()
60 // result
61 //
62 // result = Now() - (WallNow() - walltime)
63 return Now() - QuicTime::Delta::FromMicroseconds(
64 WallNow()
65 .Subtract(QuicTime::Delta::FromMicroseconds(
66 walltime.ToUNIXMicroseconds()))
67 .ToUNIXMicroseconds());
68}
69
70} // namespace quic