github.com/wasilibs/wazerox@v0.0.0-20240124024944-4923be63ab5f/internal/platform/time.go (about)

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