github.com/metacubex/gvisor@v0.0.0-20240320004321-933faba989ec/pkg/tcpip/stdclock.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package tcpip 16 17 import ( 18 "fmt" 19 "time" 20 ) 21 22 // stdClock implements Clock with the time package. 23 // 24 // +stateify savable 25 type stdClock struct { 26 // baseTime holds the time when the clock was constructed. 27 // 28 // This value is used to calculate the monotonic time from the time package. 29 // As per https://golang.org/pkg/time/#hdr-Monotonic_Clocks, 30 // 31 // Operating systems provide both a “wall clock,” which is subject to 32 // changes for clock synchronization, and a “monotonic clock,” which is not. 33 // The general rule is that the wall clock is for telling time and the 34 // monotonic clock is for measuring time. Rather than split the API, in this 35 // package the Time returned by time.Now contains both a wall clock reading 36 // and a monotonic clock reading; later time-telling operations use the wall 37 // clock reading, but later time-measuring operations, specifically 38 // comparisons and subtractions, use the monotonic clock reading. 39 // 40 // ... 41 // 42 // If Times t and u both contain monotonic clock readings, the operations 43 // t.After(u), t.Before(u), t.Equal(u), and t.Sub(u) are carried out using 44 // the monotonic clock readings alone, ignoring the wall clock readings. If 45 // either t or u contains no monotonic clock reading, these operations fall 46 // back to using the wall clock readings. 47 // 48 // Given the above, we can safely conclude that time.Since(baseTime) will 49 // return monotonically increasing values if we use time.Now() to set baseTime 50 // at the time of clock construction. 51 // 52 // Note that time.Since(t) is shorthand for time.Now().Sub(t), as per 53 // https://golang.org/pkg/time/#Since. 54 baseTime time.Time `state:"nosave"` 55 56 // monotonicOffset is the offset applied to the calculated monotonic time. 57 // 58 // monotonicOffset is assigned after restore so that the monotonic time 59 // will continue from where it "left off" before saving as part of S/R. 60 monotonicOffset MonotonicTime 61 } 62 63 // NewStdClock returns an instance of a clock that uses the time package. 64 func NewStdClock() Clock { 65 return &stdClock{ 66 baseTime: time.Now(), 67 } 68 } 69 70 var _ Clock = (*stdClock)(nil) 71 72 // Now implements Clock.Now. 73 func (*stdClock) Now() time.Time { 74 return time.Now() 75 } 76 77 // NowMonotonic implements Clock.NowMonotonic. 78 func (s *stdClock) NowMonotonic() MonotonicTime { 79 sinceBase := time.Since(s.baseTime) 80 if sinceBase < 0 { 81 panic(fmt.Sprintf("got negative duration = %s since base time = %s", sinceBase, s.baseTime)) 82 } 83 84 return s.monotonicOffset.Add(sinceBase) 85 } 86 87 // AfterFunc implements Clock.AfterFunc. 88 func (*stdClock) AfterFunc(d time.Duration, f func()) Timer { 89 return &stdTimer{ 90 t: time.AfterFunc(d, f), 91 } 92 } 93 94 type stdTimer struct { 95 t *time.Timer 96 } 97 98 var _ Timer = (*stdTimer)(nil) 99 100 // Stop implements Timer.Stop. 101 func (st *stdTimer) Stop() bool { 102 return st.t.Stop() 103 } 104 105 // Reset implements Timer.Reset. 106 func (st *stdTimer) Reset(d time.Duration) { 107 st.t.Reset(d) 108 } 109 110 // NewStdTimer returns a Timer implemented with the time package. 111 func NewStdTimer(t *time.Timer) Timer { 112 return &stdTimer{t: t} 113 }