github.com/glycerine/xcryptossh@v7.0.4+incompatible/mono.go (about) 1 package ssh 2 3 import ( 4 "time" 5 _ "unsafe" // required to use //go:linkname 6 ) 7 8 //go:noescape 9 //go:linkname nanotime runtime.nanotime 10 func nanotime() int64 11 12 // monoNow provides a read from a monotonic clock that has 13 // an arbitrary but consistent start point. 14 func monoNow() int64 { 15 return nanotime() 16 } 17 18 // subject to error due to clock adjustment 19 // in the past, but avoids error due to clock 20 // adjustment in the future. 21 func addMono(tm time.Time) time.Time { 22 if tm.IsZero() { 23 return tm // leave zero alone 24 } 25 if tm.Round(0) != tm { 26 return tm // already has monotonic part 27 } 28 now := time.Now() // has monotonic part, as of go1.9 29 unow := now.UnixNano() 30 then := tm.UnixNano() 31 diff := then - unow 32 return now.Add(time.Duration(diff)) 33 } 34 35 func getMono(tm time.Time) uint64 { 36 if tm.IsZero() { 37 panic("cannot call getMono on a zero time") 38 } 39 now := time.Now() 40 mnow := nanotime() 41 unow := now.UnixNano() 42 return uint64(mnow - (unow - tm.UnixNano())) 43 } 44 45 // monoToTime is only an approximation. It is 46 // only approximate down to ~ 1 usec because Go doesn't 47 // expose the monotonic timestamp directly, so we 48 // have to get it approximately by assuming two 49 // sequential calls to nanotime() and time.Now() 50 // return the same. 51 // 52 func monoToTime(x int64) time.Time { 53 now := time.Now() 54 mnow := nanotime() 55 return now.Add(time.Duration(mnow - int64(x))) 56 } 57 58 func stripMono(tm time.Time) time.Time { 59 return tm.Round(0) 60 }