github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/platform/time.go (about) 1 package platform 2 3 import ( 4 "sync/atomic" 5 "time" 6 7 "github.com/wasilibs/wazerox/sys" 8 ) 9 10 const ( 11 ms = int64(time.Millisecond) 12 // FakeEpochNanos is midnight UTC 2022-01-01 and exposed for testing 13 FakeEpochNanos = 1640995200000 * ms 14 ) 15 16 // NewFakeWalltime implements sys.Walltime with FakeEpochNanos that increases by 1ms each reading. 17 // See /RATIONALE.md 18 func NewFakeWalltime() sys.Walltime { 19 // AddInt64 returns the new value. Adjust so the first reading will be FakeEpochNanos 20 t := FakeEpochNanos - ms 21 return func() (sec int64, nsec int32) { 22 wt := atomic.AddInt64(&t, ms) 23 return wt / 1e9, int32(wt % 1e9) 24 } 25 } 26 27 // NewFakeNanotime implements sys.Nanotime that increases by 1ms each reading. 28 // See /RATIONALE.md 29 func NewFakeNanotime() sys.Nanotime { 30 // AddInt64 returns the new value. Adjust so the first reading will be zero. 31 t := int64(0) - ms 32 return func() int64 { 33 return atomic.AddInt64(&t, ms) 34 } 35 } 36 37 // FakeNanosleep implements sys.Nanosleep by returning without sleeping. 38 var FakeNanosleep = sys.Nanosleep(func(int64) {}) 39 40 // FakeOsyield implements sys.Osyield by returning without yielding. 41 var FakeOsyield = sys.Osyield(func() {}) 42 43 // Walltime implements sys.Walltime with time.Now. 44 // 45 // Note: This is only notably less efficient than it could be is reading 46 // runtime.walltime(). time.Now defensively reads nanotime also, just in case 47 // time.Since is used. This doubles the performance impact. However, wall time 48 // is likely to be read less frequently than Nanotime. Also, doubling the cost 49 // matters less on fast platforms that can return both in <=100ns. 50 func Walltime() (sec int64, nsec int32) { 51 t := time.Now() 52 return t.Unix(), int32(t.Nanosecond()) 53 } 54 55 // nanoBase uses time.Now to ensure a monotonic clock reading on all platforms 56 // via time.Since. 57 var nanoBase = time.Now() 58 59 // nanotimePortable implements sys.Nanotime with time.Since. 60 // 61 // Note: This is less efficient than it could be is reading runtime.nanotime(), 62 // Just to do that requires CGO. 63 func nanotimePortable() int64 { 64 return time.Since(nanoBase).Nanoseconds() 65 } 66 67 // Nanotime implements sys.Nanotime with runtime.nanotime() if CGO is available 68 // and time.Since if not. 69 func Nanotime() int64 { 70 return nanotime() 71 } 72 73 // Nanosleep implements sys.Nanosleep with time.Sleep. 74 func Nanosleep(ns int64) { 75 time.Sleep(time.Duration(ns)) 76 }