github.com/SagerNet/gvisor@v0.0.0-20210707092255-7731c139d75c/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 "github.com/SagerNet/gvisor/pkg/sync" 22 ) 23 24 // stdClock implements Clock with the time package. 25 // 26 // +stateify savable 27 type stdClock struct { 28 // baseTime holds the time when the clock was constructed. 29 // 30 // This value is used to calculate the monotonic time from the time package. 31 // As per https://golang.org/pkg/time/#hdr-Monotonic_Clocks, 32 // 33 // Operating systems provide both a “wall clock,” which is subject to 34 // changes for clock synchronization, and a “monotonic clock,” which is not. 35 // The general rule is that the wall clock is for telling time and the 36 // monotonic clock is for measuring time. Rather than split the API, in this 37 // package the Time returned by time.Now contains both a wall clock reading 38 // and a monotonic clock reading; later time-telling operations use the wall 39 // clock reading, but later time-measuring operations, specifically 40 // comparisons and subtractions, use the monotonic clock reading. 41 // 42 // ... 43 // 44 // If Times t and u both contain monotonic clock readings, the operations 45 // t.After(u), t.Before(u), t.Equal(u), and t.Sub(u) are carried out using 46 // the monotonic clock readings alone, ignoring the wall clock readings. If 47 // either t or u contains no monotonic clock reading, these operations fall 48 // back to using the wall clock readings. 49 // 50 // Given the above, we can safely conclude that time.Since(baseTime) will 51 // return monotonically increasing values if we use time.Now() to set baseTime 52 // at the time of clock construction. 53 // 54 // Note that time.Since(t) is shorthand for time.Now().Sub(t), as per 55 // https://golang.org/pkg/time/#Since. 56 baseTime time.Time `state:"nosave"` 57 58 // monotonicOffset is the offset applied to the calculated monotonic time. 59 // 60 // monotonicOffset is assigned maxMonotonic after restore so that the 61 // monotonic time will continue from where it "left off" before saving as part 62 // of S/R. 63 monotonicOffset MonotonicTime `state:"nosave"` 64 65 // monotonicMU protects maxMonotonic. 66 monotonicMU sync.Mutex `state:"nosave"` 67 maxMonotonic MonotonicTime 68 } 69 70 // NewStdClock returns an instance of a clock that uses the time package. 71 func NewStdClock() Clock { 72 return &stdClock{ 73 baseTime: time.Now(), 74 } 75 } 76 77 var _ Clock = (*stdClock)(nil) 78 79 // Now implements Clock.Now. 80 func (*stdClock) Now() time.Time { 81 return time.Now() 82 } 83 84 // NowMonotonic implements Clock.NowMonotonic. 85 func (s *stdClock) NowMonotonic() MonotonicTime { 86 sinceBase := time.Since(s.baseTime) 87 if sinceBase < 0 { 88 panic(fmt.Sprintf("got negative duration = %s since base time = %s", sinceBase, s.baseTime)) 89 } 90 91 monotonicValue := s.monotonicOffset.Add(sinceBase) 92 93 s.monotonicMU.Lock() 94 defer s.monotonicMU.Unlock() 95 96 // Monotonic time values must never decrease. 97 if s.maxMonotonic.Before(monotonicValue) { 98 s.maxMonotonic = monotonicValue 99 } 100 101 return s.maxMonotonic 102 } 103 104 // AfterFunc implements Clock.AfterFunc. 105 func (*stdClock) AfterFunc(d time.Duration, f func()) Timer { 106 return &stdTimer{ 107 t: time.AfterFunc(d, f), 108 } 109 } 110 111 type stdTimer struct { 112 t *time.Timer 113 } 114 115 var _ Timer = (*stdTimer)(nil) 116 117 // Stop implements Timer.Stop. 118 func (st *stdTimer) Stop() bool { 119 return st.t.Stop() 120 } 121 122 // Reset implements Timer.Reset. 123 func (st *stdTimer) Reset(d time.Duration) { 124 st.t.Reset(d) 125 } 126 127 // NewStdTimer returns a Timer implemented with the time package. 128 func NewStdTimer(t *time.Timer) Timer { 129 return &stdTimer{t: t} 130 }