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

     1  //go:build windows
     2  
     3  package platform
     4  
     5  import (
     6  	"math/bits"
     7  	"time"
     8  	"unsafe"
     9  )
    10  
    11  var (
    12  	_QueryPerformanceCounter   = kernel32.NewProc("QueryPerformanceCounter")
    13  	_QueryPerformanceFrequency = kernel32.NewProc("QueryPerformanceFrequency")
    14  )
    15  
    16  var qpcfreq uint64
    17  
    18  func init() {
    19  	_, _, _ = _QueryPerformanceFrequency.Call(uintptr(unsafe.Pointer(&qpcfreq)))
    20  }
    21  
    22  // On Windows, time.Time handled in time package cannot have the nanosecond precision.
    23  // The reason is that by default, it doesn't use QueryPerformanceCounter[1], but instead, use "interrupt time"
    24  // which doesn't support nanoseconds precision (though it is a monotonic) [2, 3, 4, 5].
    25  //
    26  // [1] https://learn.microsoft.com/en-us/windows/win32/api/profileapi/nf-profileapi-queryperformancecounter
    27  // [2] https://github.com/golang/go/blob/0cd309e12818f988693bf8e4d9f1453331dcf9f2/src/runtime/sys_windows_amd64.s#L297-L298
    28  // [3] https://github.com/golang/go/blob/0cd309e12818f988693bf8e4d9f1453331dcf9f2/src/runtime/os_windows.go#L549-L551
    29  // [4] https://github.com/golang/go/blob/master/src/runtime/time_windows.h#L7-L13
    30  // [5] http://web.archive.org/web/20210411000829/https://wrkhpi.wordpress.com/2007/08/09/getting-os-information-the-kuser_shared_data-structure/
    31  //
    32  // Therefore, on Windows, we directly invoke the syscall for QPC instead of time.Now or runtime.nanotime.
    33  // See https://github.com/golang/go/issues/31160 for example.
    34  func nanotime() int64 {
    35  	var counter uint64
    36  	_, _, _ = _QueryPerformanceCounter.Call(uintptr(unsafe.Pointer(&counter)))
    37  	hi, lo := bits.Mul64(counter, uint64(time.Second))
    38  	nanos, _ := bits.Div64(hi, lo, qpcfreq)
    39  	return int64(nanos)
    40  }