mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Fix flaky monotonic time.
This change ensures that even platforms with some TSC issues (e.g. KVM), can get reliable monotonic time by applied a lower bound on each read. PiperOrigin-RevId: 309773801
This commit is contained in:
committed by
gVisor bot
parent
56c64e4bb9
commit
2c986870e3
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user