forked from tetratelabs/wazero
-
Notifications
You must be signed in to change notification settings - Fork 0
/
clock.go
116 lines (106 loc) · 4 KB
/
clock.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package wasi_snapshot_preview1
import (
"context"
"syscall"
"github.com/tetratelabs/wazero/api"
"github.com/tetratelabs/wazero/internal/wasip1"
"github.com/tetratelabs/wazero/internal/wasm"
)
// clockResGet is the WASI function named ClockResGetName that returns the
// resolution of time values returned by clockTimeGet.
//
// # Parameters
//
// - id: clock ID to use
// - resultResolution: offset to write the resolution to api.Memory
// - the resolution is an uint64 little-endian encoding
//
// Result (Errno)
//
// The return value is 0 except the following error conditions:
// - syscall.ENOTSUP: the clock ID is not supported.
// - syscall.EINVAL: the clock ID is invalid.
// - syscall.EFAULT: there is not enough memory to write results
//
// For example, if the resolution is 100ns, this function writes the below to
// api.Memory:
//
// uint64le
// +-------------------------------------+
// | |
// []byte{?, 0x64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ?}
// resultResolution --^
//
// Note: This is similar to `clock_getres` in POSIX.
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-clock_res_getid-clockid---errno-timestamp
// See https://linux.die.net/man/3/clock_getres
var clockResGet = newHostFunc(wasip1.ClockResGetName, clockResGetFn, []api.ValueType{i32, i32}, "id", "result.resolution")
func clockResGetFn(_ context.Context, mod api.Module, params []uint64) syscall.Errno {
sysCtx := mod.(*wasm.ModuleInstance).Sys
id, resultResolution := uint32(params[0]), uint32(params[1])
var resolution uint64 // ns
switch id {
case wasip1.ClockIDRealtime:
resolution = uint64(sysCtx.WalltimeResolution())
case wasip1.ClockIDMonotonic:
resolution = uint64(sysCtx.NanotimeResolution())
default:
return syscall.EINVAL
}
if !mod.Memory().WriteUint64Le(resultResolution, resolution) {
return syscall.EFAULT
}
return 0
}
// clockTimeGet is the WASI function named ClockTimeGetName that returns
// the time value of a name (time.Now).
//
// # Parameters
//
// - id: clock ID to use
// - precision: maximum lag (exclusive) that the returned time value may have,
// compared to its actual value
// - resultTimestamp: offset to write the timestamp to api.Memory
// - the timestamp is epoch nanos encoded as a little-endian uint64
//
// Result (Errno)
//
// The return value is 0 except the following error conditions:
// - syscall.ENOTSUP: the clock ID is not supported.
// - syscall.EINVAL: the clock ID is invalid.
// - syscall.EFAULT: there is not enough memory to write results
//
// For example, if time.Now returned exactly midnight UTC 2022-01-01
// (1640995200000000000), and parameters resultTimestamp=1, this function
// writes the below to api.Memory:
//
// uint64le
// +------------------------------------------+
// | |
// []byte{?, 0x0, 0x0, 0x1f, 0xa6, 0x70, 0xfc, 0xc5, 0x16, ?}
// resultTimestamp --^
//
// Note: This is similar to `clock_gettime` in POSIX.
// See https://github.com/WebAssembly/WASI/blob/snapshot-01/phases/snapshot/docs.md#-clock_time_getid-clockid-precision-timestamp---errno-timestamp
// See https://linux.die.net/man/3/clock_gettime
var clockTimeGet = newHostFunc(wasip1.ClockTimeGetName, clockTimeGetFn, []api.ValueType{i32, i64, i32}, "id", "precision", "result.timestamp")
func clockTimeGetFn(_ context.Context, mod api.Module, params []uint64) syscall.Errno {
sysCtx := mod.(*wasm.ModuleInstance).Sys
id := uint32(params[0])
// TODO: precision is currently ignored.
// precision = params[1]
resultTimestamp := uint32(params[2])
var val int64
switch id {
case wasip1.ClockIDRealtime:
val = sysCtx.WalltimeNanos()
case wasip1.ClockIDMonotonic:
val = sysCtx.Nanotime()
default:
return syscall.EINVAL
}
if !mod.Memory().WriteUint64Le(resultTimestamp, uint64(val)) {
return syscall.EFAULT
}
return 0
}