]> Cypherpunks.ru repositories - gostls13.git/commitdiff
runtime: implement usleep in Go instead of assembly on Windows
authorqmuntal <quimmuntal@gmail.com>
Thu, 7 Sep 2023 12:59:58 +0000 (14:59 +0200)
committerQuim Muntal <quimmuntal@gmail.com>
Thu, 21 Sep 2023 15:56:43 +0000 (15:56 +0000)
Windows APIs are normally not arch-specific, so it's better to
implement them in Go instead of assembly.

It was previously implemented in assembly because it was the only way
to support calls without a valid g. This CL defines a new function,
stdcall_no_g, that can be used in such cases.

While here, I've also replaced the use of the deprecated syscall
NtWaitForSingleObject with WaitForSingleObject. The former may
give the illusion of being more accurate, as it takes a higher
resolution timeout, but it's not. Windows time resolution is 15.6ms,
and can be as high as 1ms when using a high resolution timer, which
WaitForSingleObject supports.

Change-Id: I903400220ade4d4ccc15685c8da47182430f8686
Reviewed-on: https://go-review.googlesource.com/c/go/+/526477
Reviewed-by: Bryan Mills <bcmills@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>

src/runtime/os_windows.go
src/runtime/sys_windows_386.s
src/runtime/sys_windows_amd64.s
src/runtime/sys_windows_arm.s
src/runtime/sys_windows_arm64.s

index 576988e107717458f0222a7d51455f48f5c7755f..b77efabe7004358fee67eaae16ab69e7089d8453 100644 (file)
@@ -138,7 +138,6 @@ var (
        // Load ntdll.dll manually during startup, otherwise Mingw
        // links wrong printf function to cgo executable (see issue
        // 12030 for details).
-       _NtWaitForSingleObject  stdFunction
        _RtlGetCurrentPeb       stdFunction
        _RtlGetNtVersionNumbers stdFunction
 
@@ -269,7 +268,6 @@ func loadOptionalSyscalls() {
        if n32 == 0 {
                throw("ntdll.dll not found")
        }
-       _NtWaitForSingleObject = windowsFindfunc(n32, []byte("NtWaitForSingleObject\000"))
        _RtlGetCurrentPeb = windowsFindfunc(n32, []byte("RtlGetCurrentPeb\000"))
        _RtlGetNtVersionNumbers = windowsFindfunc(n32, []byte("RtlGetNtVersionNumbers\000"))
 
@@ -1069,7 +1067,6 @@ func stdcall7(fn stdFunction, a0, a1, a2, a3, a4, a5, a6 uintptr) uintptr {
 }
 
 // These must run on the system stack only.
-func usleep2(dt int32)
 
 //go:nosplit
 func osyield_no_g() {
@@ -1085,23 +1082,27 @@ func osyield() {
 
 //go:nosplit
 func usleep_no_g(us uint32) {
-       dt := -10 * int32(us) // relative sleep (negative), 100ns units
-       usleep2(dt)
+       timeout := uintptr(us) / 1000 // ms units
+       args := [...]uintptr{_INVALID_HANDLE_VALUE, timeout}
+       stdcall_no_g(_WaitForSingleObject, len(args), uintptr(noescape(unsafe.Pointer(&args[0]))))
 }
 
 //go:nosplit
 func usleep(us uint32) {
        systemstack(func() {
-               dt := -10 * int64(us) // relative sleep (negative), 100ns units
+               var h, timeout uintptr
                // If the high-res timer is available and its handle has been allocated for this m, use it.
                // Otherwise fall back to the low-res one, which doesn't need a handle.
                if haveHighResTimer && getg().m.highResTimer != 0 {
-                       h := getg().m.highResTimer
+                       h = getg().m.highResTimer
+                       dt := -10 * int64(us) // relative sleep (negative), 100ns units
                        stdcall6(_SetWaitableTimer, h, uintptr(unsafe.Pointer(&dt)), 0, 0, 0, 0)
-                       stdcall3(_NtWaitForSingleObject, h, 0, 0)
+                       timeout = _INFINITE
                } else {
-                       usleep2(int32(dt))
+                       h = _INVALID_HANDLE_VALUE
+                       timeout = uintptr(us) / 1000 // ms units
                }
+               stdcall2(_WaitForSingleObject, h, timeout)
        })
 }
 
index c8d4bf93a7a5c8aa6c7a5a63a96b54ee8b3a17a6..e71fda78aee3532885933b5f65214b4f268acf1a 100644 (file)
@@ -234,23 +234,6 @@ TEXT runtime·setldt(SB),NOSPLIT,$0-12
        MOVL    DX, 0(CX)(FS)
        RET
 
-// Runs on OS stack.
-// duration (in -100ns units) is in dt+0(FP).
-// g may be nil.
-TEXT runtime·usleep2(SB),NOSPLIT,$20-4
-       MOVL    dt+0(FP), BX
-       MOVL    $-1, hi-4(SP)
-       MOVL    BX, lo-8(SP)
-       LEAL    lo-8(SP), BX
-       MOVL    BX, ptime-12(SP)
-       MOVL    $0, alertable-16(SP)
-       MOVL    $-1, handle-20(SP)
-       MOVL    SP, BP
-       MOVL    runtime·_NtWaitForSingleObject(SB), AX
-       CALL    AX
-       MOVL    BP, SP
-       RET
-
 TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
 loop:
        MOVL    (_INTERRUPT_TIME+time_hi1), AX
index af2b52735d9afe57ad8db53d531bef7b4f7435ad..6cc8e919520e3a949fb9d1dab3b9be95d37901ae 100644 (file)
@@ -243,25 +243,6 @@ TEXT runtime·settls(SB),NOSPLIT,$0
        MOVQ    DI, 0(CX)(GS)
        RET
 
-// Runs on OS stack.
-// duration (in -100ns units) is in dt+0(FP).
-// g may be nil.
-// The function leaves room for 4 syscall parameters
-// (as per windows amd64 calling convention).
-TEXT runtime·usleep2(SB),NOSPLIT,$48-4
-       MOVLQSX dt+0(FP), BX
-       MOVQ    SP, AX
-       ANDQ    $~15, SP        // alignment as per Windows requirement
-       MOVQ    AX, 40(SP)
-       LEAQ    32(SP), R8  // ptime
-       MOVQ    BX, (R8)
-       MOVQ    $-1, CX // handle
-       MOVQ    $0, DX // alertable
-       MOVQ    runtime·_NtWaitForSingleObject(SB), AX
-       CALL    AX
-       MOVQ    40(SP), SP
-       RET
-
 TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
        MOVQ    $_INTERRUPT_TIME, DI
        MOVQ    time_lo(DI), AX
index 4b941e40ae59bfc3223c74fc27cce5c25c6b9289..d194899d50898d3efd5bebfb5149b15cc1b0213c 100644 (file)
@@ -195,25 +195,6 @@ TEXT runtime·tstart_stdcall(SB),NOSPLIT|NOFRAME,$0
        MOVW    $0, R0
        MOVM.IA.W (R13), [R4-R11, R15]          // pop {r4-r11, pc}
 
-// Runs on OS stack.
-// duration (in -100ns units) is in dt+0(FP).
-// g may be nil.
-TEXT runtime·usleep2(SB),NOSPLIT|NOFRAME,$0-4
-       MOVW    dt+0(FP), R3
-       MOVM.DB.W [R4, R14], (R13)      // push {r4, lr}
-       MOVW    R13, R4                 // Save SP
-       SUB     $8, R13                 // R13 = R13 - 8
-       BIC     $0x7, R13               // Align SP for ABI
-       MOVW    $0, R1                  // R1 = FALSE (alertable)
-       MOVW    $-1, R0                 // R0 = handle
-       MOVW    R13, R2                 // R2 = pTime
-       MOVW    R3, 0(R2)               // time_lo
-       MOVW    R0, 4(R2)               // time_hi
-       MOVW    runtime·_NtWaitForSingleObject(SB), R3
-       BL      (R3)
-       MOVW    R4, R13                 // Restore SP
-       MOVM.IA.W (R13), [R4, R15]      // pop {R4, pc}
-
 TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
        B       runtime·armPublicationBarrier(SB)
 
index 4818994ed4882d9a72593d8a8146493bf34b66cc..1f6d411b07c3633a27f168e976aa32bae74942f6 100644 (file)
@@ -228,21 +228,6 @@ TEXT runtime·tstart_stdcall(SB),NOSPLIT,$96-0
        MOVD    $0, R0
        RET
 
-// Runs on OS stack.
-// duration (in -100ns units) is in dt+0(FP).
-// g may be nil.
-TEXT runtime·usleep2(SB),NOSPLIT,$32-4
-       MOVW    dt+0(FP), R0
-       MOVD    $16(RSP), R2            // R2 = pTime
-       MOVD    R0, 0(R2)               // *pTime = -dt
-       MOVD    $-1, R0                 // R0 = handle
-       MOVD    $0, R1                  // R1 = FALSE (alertable)
-       MOVD    runtime·_NtWaitForSingleObject(SB), R3
-       SUB     $16, RSP        // skip over saved frame pointer below RSP
-       BL      (R3)
-       ADD     $16, RSP
-       RET
-
 TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
        MOVD    $_INTERRUPT_TIME, R3
        MOVD    time_lo(R3), R0