github.com/bananabytelabs/wazero@v0.0.0-20240105073314-54b22a776da8/imports/wasi_snapshot_preview1/clock.go (about)

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