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