1package platform
2
3import (
4 "sync/atomic"
5 "time"
6
7 "github.com/tetratelabs/wazero/sys"
8)
9
10const (
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
18func 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
29func 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.
38var FakeNanosleep = sys.Nanosleep(func(int64) {})
39
40// FakeOsyield implements sys.Osyield by returning without yielding.
41var 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.
50func 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.
57var 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.
63func 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.
69func Nanotime() int64 {
70 return nanotime()
71}
72
73// Nanosleep implements sys.Nanosleep with time.Sleep.
74func Nanosleep(ns int64) {
75 time.Sleep(time.Duration(ns))
76}