diff --git a/src/runtime/baremetal.go b/src/runtime/baremetal.go index ce69e338..5abd1371 100644 --- a/src/runtime/baremetal.go +++ b/src/runtime/baremetal.go @@ -52,3 +52,24 @@ func syscall_Exit(code int) { } const baremetal = true + +// timeOffset is how long the monotonic clock started after the Unix epoch. It +// should be a positive integer under normal operation or zero when it has not +// been set. +var timeOffset int64 + +//go:linkname now time.now +func now() (sec int64, nsec int32, mono int64) { + mono = nanotime() + sec = (mono + timeOffset) / (1000 * 1000 * 1000) + nsec = int32((mono + timeOffset) - sec*(1000*1000*1000)) + return +} + +// AdjustTimeOffset adds the given offset to the built-in time offset. A +// positive value adds to the time (skipping some time), a negative value moves +// the clock into the past. +func AdjustTimeOffset(offset int64) { + // TODO: do this atomically? + timeOffset += offset +} diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go index ac31b67d..be878909 100644 --- a/src/runtime/os_darwin.go +++ b/src/runtime/os_darwin.go @@ -11,3 +11,9 @@ const ( flag_MAP_PRIVATE = 0x2 flag_MAP_ANONYMOUS = 0x1000 // MAP_ANON ) + +// Source: https://opensource.apple.com/source/Libc/Libc-1439.100.3/include/time.h.auto.html +const ( + clock_REALTIME = 0 + clock_MONOTONIC_RAW = 4 +) diff --git a/src/runtime/os_linux.go b/src/runtime/os_linux.go index 7613134e..aa056173 100644 --- a/src/runtime/os_linux.go +++ b/src/runtime/os_linux.go @@ -11,3 +11,9 @@ const ( flag_MAP_PRIVATE = 0x2 flag_MAP_ANONYMOUS = 0x20 ) + +// Source: https://github.com/torvalds/linux/blob/master/include/uapi/linux/time.h +const ( + clock_REALTIME = 0 + clock_MONOTONIC_RAW = 4 +) diff --git a/src/runtime/runtime.go b/src/runtime/runtime.go index 7b1b4f5a..55102411 100644 --- a/src/runtime/runtime.go +++ b/src/runtime/runtime.go @@ -68,27 +68,6 @@ func nanotime() int64 { return ticksToNanoseconds(ticks()) } -// timeOffset is how long the monotonic clock started after the Unix epoch. It -// should be a positive integer under normal operation or zero when it has not -// been set. -var timeOffset int64 - -//go:linkname now time.now -func now() (sec int64, nsec int32, mono int64) { - mono = nanotime() - sec = (mono + timeOffset) / (1000 * 1000 * 1000) - nsec = int32((mono + timeOffset) - sec*(1000*1000*1000)) - return -} - -// AdjustTimeOffset adds the given offset to the built-in time offset. A -// positive value adds to the time (skipping some time), a negative value moves -// the clock into the past. -func AdjustTimeOffset(offset int64) { - // TODO: do this atomically? - timeOffset += offset -} - // Copied from the Go runtime source code. //go:linkname os_sigpipe os.sigpipe func os_sigpipe() { diff --git a/src/runtime/runtime_tinygowasm.go b/src/runtime/runtime_tinygowasm.go index 989fbb80..80eaa8d3 100644 --- a/src/runtime/runtime_tinygowasm.go +++ b/src/runtime/runtime_tinygowasm.go @@ -50,6 +50,14 @@ func putchar(c byte) { } } +//go:linkname now time.now +func now() (sec int64, nsec int32, mono int64) { + mono = nanotime() + sec = mono / (1000 * 1000 * 1000) + nsec = int32(mono - sec*(1000*1000*1000)) + return +} + // Abort executes the wasm 'unreachable' instruction. func abort() { trap() diff --git a/src/runtime/runtime_unix.go b/src/runtime/runtime_unix.go index c185c4ab..464d8dfe 100644 --- a/src/runtime/runtime_unix.go +++ b/src/runtime/runtime_unix.go @@ -38,8 +38,6 @@ type timespec struct { tv_nsec int // long: on Linux and macOS, follows the platform bitness } -const CLOCK_MONOTONIC_RAW = 4 - var stackTop uintptr func postinit() {} @@ -138,19 +136,31 @@ func sleepTicks(d timeUnit) { usleep(uint(d) / 1000) } -// Return monotonic time in nanoseconds. -// -// TODO: noescape -func monotime() uint64 { +func getTime(clock int32) uint64 { ts := timespec{} - clock_gettime(CLOCK_MONOTONIC_RAW, &ts) + clock_gettime(clock, &ts) return uint64(ts.tv_sec)*1000*1000*1000 + uint64(ts.tv_nsec) } +// Return monotonic time in nanoseconds. +func monotime() uint64 { + return getTime(clock_MONOTONIC_RAW) +} + func ticks() timeUnit { return timeUnit(monotime()) } +//go:linkname now time.now +func now() (sec int64, nsec int32, mono int64) { + ts := timespec{} + clock_gettime(clock_REALTIME, &ts) + sec = int64(ts.tv_sec) + nsec = int32(ts.tv_nsec) + mono = nanotime() + return +} + //go:linkname syscall_Exit syscall.Exit func syscall_Exit(code int) { exit(code)