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  }