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 // +stateify savable
95 type stdTimer struct {
96 t *time.Timer
97 }
98 99 var _ Timer = (*stdTimer)(nil)
100 101 // Stop implements Timer.Stop.
102 func (st *stdTimer) Stop() bool {
103 return st.t.Stop()
104 }
105 106 // Reset implements Timer.Reset.
107 func (st *stdTimer) Reset(d time.Duration) {
108 st.t.Reset(d)
109 }
110 111 // NewStdTimer returns a Timer implemented with the time package.
112 func NewStdTimer(t *time.Timer) Timer {
113 return &stdTimer{t: t}
114 }
115