wa-lang.org/wazero@v1.0.2/internal/platform/time.go (about)

     1  package platform
     2  
     3  import (
     4  	"context"
     5  	"sync/atomic"
     6  	"time"
     7  
     8  	"wa-lang.org/wazero/sys"
     9  )
    10  
    11  const (
    12  	ms = int64(time.Millisecond)
    13  	// FakeEpochNanos is midnight UTC 2022-01-01 and exposed for testing
    14  	FakeEpochNanos = 1640995200000 * ms
    15  )
    16  
    17  // NewFakeWalltime implements sys.Walltime with FakeEpochNanos that increases by 1ms each reading.
    18  // See /RATIONALE.md
    19  func NewFakeWalltime() *sys.Walltime {
    20  	// AddInt64 returns the new value. Adjust so the first reading will be FakeEpochNanos
    21  	t := FakeEpochNanos - ms
    22  	var wt sys.Walltime = func(context.Context) (sec int64, nsec int32) {
    23  		wt := atomic.AddInt64(&t, ms)
    24  		return wt / 1e9, int32(wt % 1e9)
    25  	}
    26  	return &wt
    27  }
    28  
    29  // NewFakeNanotime implements sys.Nanotime that increases by 1ms each reading.
    30  // See /RATIONALE.md
    31  func NewFakeNanotime() *sys.Nanotime {
    32  	// AddInt64 returns the new value. Adjust so the first reading will be zero.
    33  	t := int64(0) - ms
    34  	var nt sys.Nanotime = func(context.Context) int64 {
    35  		return atomic.AddInt64(&t, ms)
    36  	}
    37  	return &nt
    38  }
    39  
    40  // FakeNanosleep implements sys.Nanosleep by returning without sleeping.
    41  func FakeNanosleep(context.Context, int64) {
    42  }
    43  
    44  // Walltime implements sys.Walltime with time.Now.
    45  //
    46  // Note: This is only notably less efficient than it could be is reading
    47  // runtime.walltime(). time.Now defensively reads nanotime also, just in case
    48  // time.Since is used. This doubles the performance impact. However, wall time
    49  // is likely to be read less frequently than Nanotime. Also, doubling the cost
    50  // matters less on fast platforms that can return both in <=100ns.
    51  func Walltime(context.Context) (sec int64, nsec int32) {
    52  	t := time.Now()
    53  	return t.Unix(), int32(t.Nanosecond())
    54  }
    55  
    56  // nanoBase uses time.Now to ensure a monotonic clock reading on all platforms
    57  // via time.Since.
    58  var nanoBase = time.Now()
    59  
    60  // nanotimePortable implements sys.Nanotime with time.Since.
    61  //
    62  // Note: This is less efficient than it could be is reading runtime.nanotime(),
    63  // Just to do that requires CGO.
    64  func nanotimePortable() int64 {
    65  	return time.Since(nanoBase).Nanoseconds()
    66  }
    67  
    68  // Nanotime implements sys.Nanotime with runtime.nanotime() if CGO is available
    69  // and time.Since if not.
    70  func Nanotime(context.Context) int64 {
    71  	return nanotime()
    72  }
    73  
    74  // Nanosleep implements sys.Nanosleep with time.Sleep.
    75  func Nanosleep(_ context.Context, ns int64) {
    76  	time.Sleep(time.Duration(ns))
    77  }