Files
wazero/internal/platform/time.go
Crypt Keeper 3d72f2cb90 wasi: implements sched_yield with sys.Osyield (#1131)
This implements WASI `sched_yield` with `sys.Osyield` that defaults to
return immediately. This is intentionally left without a built-in
alternative as common platforms such as darwin implement
`runtime.osyield` by sleeping for a microsecond. If we implemented that,
user code would be slowed down without a clear reason why.

Signed-off-by: Adrian Cole <adrian@tetrate.io>
2023-02-15 15:57:24 -10:00

79 lines
2.3 KiB
Go

package platform
import (
"sync/atomic"
"time"
"github.com/tetratelabs/wazero/sys"
)
const (
ms = int64(time.Millisecond)
// FakeEpochNanos is midnight UTC 2022-01-01 and exposed for testing
FakeEpochNanos = 1640995200000 * ms
)
// NewFakeWalltime implements sys.Walltime with FakeEpochNanos that increases by 1ms each reading.
// See /RATIONALE.md
func NewFakeWalltime() *sys.Walltime {
// AddInt64 returns the new value. Adjust so the first reading will be FakeEpochNanos
t := FakeEpochNanos - ms
var wt sys.Walltime = func() (sec int64, nsec int32) {
wt := atomic.AddInt64(&t, ms)
return wt / 1e9, int32(wt % 1e9)
}
return &wt
}
// NewFakeNanotime implements sys.Nanotime that increases by 1ms each reading.
// See /RATIONALE.md
func NewFakeNanotime() *sys.Nanotime {
// AddInt64 returns the new value. Adjust so the first reading will be zero.
t := int64(0) - ms
var nt sys.Nanotime = func() int64 {
return atomic.AddInt64(&t, ms)
}
return &nt
}
// FakeNanosleep implements sys.Nanosleep by returning without sleeping.
func FakeNanosleep(int64) {}
// FakeOsyield implements sys.Osyield by returning without yielding.
func FakeOsyield() {}
// Walltime implements sys.Walltime with time.Now.
//
// Note: This is only notably less efficient than it could be is reading
// runtime.walltime(). time.Now defensively reads nanotime also, just in case
// time.Since is used. This doubles the performance impact. However, wall time
// is likely to be read less frequently than Nanotime. Also, doubling the cost
// matters less on fast platforms that can return both in <=100ns.
func Walltime() (sec int64, nsec int32) {
t := time.Now()
return t.Unix(), int32(t.Nanosecond())
}
// nanoBase uses time.Now to ensure a monotonic clock reading on all platforms
// via time.Since.
var nanoBase = time.Now()
// nanotimePortable implements sys.Nanotime with time.Since.
//
// Note: This is less efficient than it could be is reading runtime.nanotime(),
// Just to do that requires CGO.
func nanotimePortable() int64 {
return time.Since(nanoBase).Nanoseconds()
}
// Nanotime implements sys.Nanotime with runtime.nanotime() if CGO is available
// and time.Since if not.
func Nanotime() int64 {
return nanotime()
}
// Nanosleep implements sys.Nanosleep with time.Sleep.
func Nanosleep(ns int64) {
time.Sleep(time.Duration(ns))
}