diff options
author | gVisor bot <gvisor-bot@google.com> | 2020-05-04 17:45:41 +0000 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2020-05-04 17:45:41 +0000 |
commit | 95cb42d3ad61bc1827f6be769ea66981414d5527 (patch) | |
tree | fa19695260fb21a37d35b9f3a68a168d4720213f /pkg | |
parent | 7156bf24df58463592cfb8c0868741c9ce07c212 (diff) | |
parent | 2c986870e35f967c88ebc1b7df7b576aad2c46d4 (diff) |
Merge release-20200422.0-15-g2c98687 (automated)
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/sentry/kernel/timekeeper.go | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/pkg/sentry/kernel/timekeeper.go b/pkg/sentry/kernel/timekeeper.go index dc99301de..da0ea7bb5 100644 --- a/pkg/sentry/kernel/timekeeper.go +++ b/pkg/sentry/kernel/timekeeper.go @@ -16,6 +16,7 @@ package kernel import ( "fmt" + "sync/atomic" "time" "gvisor.dev/gvisor/pkg/log" @@ -48,6 +49,9 @@ type Timekeeper struct { // It is set only once, by SetClocks. monotonicOffset int64 `state:"nosave"` + // monotonicLowerBound is the lowerBound for monotonic time. + monotonicLowerBound int64 `state:"nosave"` + // restored, if non-nil, indicates that this Timekeeper was restored // from a state file. The clocks are not set until restored is closed. restored chan struct{} `state:"nosave"` @@ -271,6 +275,21 @@ func (t *Timekeeper) GetTime(c sentrytime.ClockID) (int64, error) { now, err := t.clocks.GetTime(c) if err == nil && c == sentrytime.Monotonic { now += t.monotonicOffset + for { + // It's possible that the clock is shaky. This may be due to + // platform issues, e.g. the KVM platform relies on the guest + // TSC and host TSC, which may not be perfectly in sync. To + // work around this issue, ensure that the monotonic time is + // always bounded by the last time read. + oldLowerBound := atomic.LoadInt64(&t.monotonicLowerBound) + if now < oldLowerBound { + now = oldLowerBound + break + } + if atomic.CompareAndSwapInt64(&t.monotonicLowerBound, oldLowerBound, now) { + break + } + } } return now, err } |