Skip to content

Commit b6ae112

Browse files
committed
runtime: implement usleep in Go instead of assembly on Windows
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 <[email protected]> Reviewed-by: Cherry Mui <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Alex Brainman <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Run-TryBot: Quim Muntal <[email protected]>
1 parent ace1494 commit b6ae112

File tree

5 files changed

+10
-79
lines changed

5 files changed

+10
-79
lines changed

src/runtime/os_windows.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,6 @@ var (
138138
// Load ntdll.dll manually during startup, otherwise Mingw
139139
// links wrong printf function to cgo executable (see issue
140140
// 12030 for details).
141-
_NtWaitForSingleObject stdFunction
142141
_RtlGetCurrentPeb stdFunction
143142
_RtlGetNtVersionNumbers stdFunction
144143

@@ -269,7 +268,6 @@ func loadOptionalSyscalls() {
269268
if n32 == 0 {
270269
throw("ntdll.dll not found")
271270
}
272-
_NtWaitForSingleObject = windowsFindfunc(n32, []byte("NtWaitForSingleObject\000"))
273271
_RtlGetCurrentPeb = windowsFindfunc(n32, []byte("RtlGetCurrentPeb\000"))
274272
_RtlGetNtVersionNumbers = windowsFindfunc(n32, []byte("RtlGetNtVersionNumbers\000"))
275273

@@ -1069,7 +1067,6 @@ func stdcall7(fn stdFunction, a0, a1, a2, a3, a4, a5, a6 uintptr) uintptr {
10691067
}
10701068

10711069
// These must run on the system stack only.
1072-
func usleep2(dt int32)
10731070

10741071
//go:nosplit
10751072
func osyield_no_g() {
@@ -1085,23 +1082,27 @@ func osyield() {
10851082

10861083
//go:nosplit
10871084
func usleep_no_g(us uint32) {
1088-
dt := -10 * int32(us) // relative sleep (negative), 100ns units
1089-
usleep2(dt)
1085+
timeout := uintptr(us) / 1000 // ms units
1086+
args := [...]uintptr{_INVALID_HANDLE_VALUE, timeout}
1087+
stdcall_no_g(_WaitForSingleObject, len(args), uintptr(noescape(unsafe.Pointer(&args[0]))))
10901088
}
10911089

10921090
//go:nosplit
10931091
func usleep(us uint32) {
10941092
systemstack(func() {
1095-
dt := -10 * int64(us) // relative sleep (negative), 100ns units
1093+
var h, timeout uintptr
10961094
// If the high-res timer is available and its handle has been allocated for this m, use it.
10971095
// Otherwise fall back to the low-res one, which doesn't need a handle.
10981096
if haveHighResTimer && getg().m.highResTimer != 0 {
1099-
h := getg().m.highResTimer
1097+
h = getg().m.highResTimer
1098+
dt := -10 * int64(us) // relative sleep (negative), 100ns units
11001099
stdcall6(_SetWaitableTimer, h, uintptr(unsafe.Pointer(&dt)), 0, 0, 0, 0)
1101-
stdcall3(_NtWaitForSingleObject, h, 0, 0)
1100+
timeout = _INFINITE
11021101
} else {
1103-
usleep2(int32(dt))
1102+
h = _INVALID_HANDLE_VALUE
1103+
timeout = uintptr(us) / 1000 // ms units
11041104
}
1105+
stdcall2(_WaitForSingleObject, h, timeout)
11051106
})
11061107
}
11071108

src/runtime/sys_windows_386.s

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -234,23 +234,6 @@ TEXT runtime·setldt(SB),NOSPLIT,$0-12
234234
MOVL DX, 0(CX)(FS)
235235
RET
236236

237-
// Runs on OS stack.
238-
// duration (in -100ns units) is in dt+0(FP).
239-
// g may be nil.
240-
TEXT runtime·usleep2(SB),NOSPLIT,$20-4
241-
MOVL dt+0(FP), BX
242-
MOVL $-1, hi-4(SP)
243-
MOVL BX, lo-8(SP)
244-
LEAL lo-8(SP), BX
245-
MOVL BX, ptime-12(SP)
246-
MOVL $0, alertable-16(SP)
247-
MOVL $-1, handle-20(SP)
248-
MOVL SP, BP
249-
MOVL runtime·_NtWaitForSingleObject(SB), AX
250-
CALL AX
251-
MOVL BP, SP
252-
RET
253-
254237
TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
255238
loop:
256239
MOVL (_INTERRUPT_TIME+time_hi1), AX

src/runtime/sys_windows_amd64.s

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -243,25 +243,6 @@ TEXT runtime·settls(SB),NOSPLIT,$0
243243
MOVQ DI, 0(CX)(GS)
244244
RET
245245

246-
// Runs on OS stack.
247-
// duration (in -100ns units) is in dt+0(FP).
248-
// g may be nil.
249-
// The function leaves room for 4 syscall parameters
250-
// (as per windows amd64 calling convention).
251-
TEXT runtime·usleep2(SB),NOSPLIT,$48-4
252-
MOVLQSX dt+0(FP), BX
253-
MOVQ SP, AX
254-
ANDQ $~15, SP // alignment as per Windows requirement
255-
MOVQ AX, 40(SP)
256-
LEAQ 32(SP), R8 // ptime
257-
MOVQ BX, (R8)
258-
MOVQ $-1, CX // handle
259-
MOVQ $0, DX // alertable
260-
MOVQ runtime·_NtWaitForSingleObject(SB), AX
261-
CALL AX
262-
MOVQ 40(SP), SP
263-
RET
264-
265246
TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
266247
MOVQ $_INTERRUPT_TIME, DI
267248
MOVQ time_lo(DI), AX

src/runtime/sys_windows_arm.s

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -195,25 +195,6 @@ TEXT runtime·tstart_stdcall(SB),NOSPLIT|NOFRAME,$0
195195
MOVW $0, R0
196196
MOVM.IA.W (R13), [R4-R11, R15] // pop {r4-r11, pc}
197197

198-
// Runs on OS stack.
199-
// duration (in -100ns units) is in dt+0(FP).
200-
// g may be nil.
201-
TEXT runtime·usleep2(SB),NOSPLIT|NOFRAME,$0-4
202-
MOVW dt+0(FP), R3
203-
MOVM.DB.W [R4, R14], (R13) // push {r4, lr}
204-
MOVW R13, R4 // Save SP
205-
SUB $8, R13 // R13 = R13 - 8
206-
BIC $0x7, R13 // Align SP for ABI
207-
MOVW $0, R1 // R1 = FALSE (alertable)
208-
MOVW $-1, R0 // R0 = handle
209-
MOVW R13, R2 // R2 = pTime
210-
MOVW R3, 0(R2) // time_lo
211-
MOVW R0, 4(R2) // time_hi
212-
MOVW runtime·_NtWaitForSingleObject(SB), R3
213-
BL (R3)
214-
MOVW R4, R13 // Restore SP
215-
MOVM.IA.W (R13), [R4, R15] // pop {R4, pc}
216-
217198
TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
218199
B runtime·armPublicationBarrier(SB)
219200

src/runtime/sys_windows_arm64.s

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -228,21 +228,6 @@ TEXT runtime·tstart_stdcall(SB),NOSPLIT,$96-0
228228
MOVD $0, R0
229229
RET
230230

231-
// Runs on OS stack.
232-
// duration (in -100ns units) is in dt+0(FP).
233-
// g may be nil.
234-
TEXT runtime·usleep2(SB),NOSPLIT,$32-4
235-
MOVW dt+0(FP), R0
236-
MOVD $16(RSP), R2 // R2 = pTime
237-
MOVD R0, 0(R2) // *pTime = -dt
238-
MOVD $-1, R0 // R0 = handle
239-
MOVD $0, R1 // R1 = FALSE (alertable)
240-
MOVD runtime·_NtWaitForSingleObject(SB), R3
241-
SUB $16, RSP // skip over saved frame pointer below RSP
242-
BL (R3)
243-
ADD $16, RSP
244-
RET
245-
246231
TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
247232
MOVD $_INTERRUPT_TIME, R3
248233
MOVD time_lo(R3), R0

0 commit comments

Comments
 (0)