This CL moves the usleep2HighRes from assembly to good old Go.
This is safe because since CL 288793 usleep is always called with
a g, else one wold have to call usleep_no_g. This condition was
not enforced when high resolution timers were first implemented
on Windows (CL 248699), so the implementation was done in assembly.
Other than removing a bunch of obscure assembly code, this CL makes
high resolution timers work on windows arm/arm64 by free, as the
system calls are the same in all windows platforms.
Change-Id: I41ecf78026fd7e11e85258a411ae074a77e8c7fc
Reviewed-on: https://go-review.googlesource.com/c/go/+/471142
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
Auto-Submit: Michael Pratt <mpratt@google.com>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
_SYNCHRONIZE|_TIMER_QUERY_STATE|_TIMER_MODIFY_STATE)
}
-const highResTimerSupported = GOARCH == "386" || GOARCH == "amd64"
-
func initHighResTimer() {
- if !highResTimerSupported {
- // TODO: Not yet implemented.
- return
- }
h := createHighResTimer()
if h != 0 {
haveHighResTimer = true
// These must run on the system stack only.
func usleep2(dt int32)
-func usleep2HighRes(dt int32)
func switchtothread()
//go:nosplit
//go:nosplit
func usleep(us uint32) {
systemstack(func() {
- dt := -10 * int32(us) // relative sleep (negative), 100ns units
+ dt := -10 * int64(us) // relative sleep (negative), 100ns units
// 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 {
- usleep2HighRes(dt)
+ h := getg().m.highResTimer
+ stdcall6(_SetWaitableTimer, h, uintptr(unsafe.Pointer(&dt)), 0, 0, 0, 0)
+ stdcall3(_NtWaitForSingleObject, h, 0, 0)
} else {
- usleep2(dt)
+ usleep2(int32(dt))
}
})
}
MOVL BP, SP
RET
-// Runs on OS stack.
-// duration (in -100ns units) is in dt+0(FP).
-// g is valid.
-TEXT runtime·usleep2HighRes(SB),NOSPLIT,$36-4
- MOVL dt+0(FP), BX
- MOVL $-1, hi-4(SP)
- MOVL BX, lo-8(SP)
-
- get_tls(CX)
- MOVL g(CX), CX
- MOVL g_m(CX), CX
- MOVL (m_mOS+mOS_highResTimer)(CX), CX
- MOVL CX, saved_timer-12(SP)
-
- MOVL $0, fResume-16(SP)
- MOVL $0, lpArgToCompletionRoutine-20(SP)
- MOVL $0, pfnCompletionRoutine-24(SP)
- MOVL $0, lPeriod-28(SP)
- LEAL lo-8(SP), BX
- MOVL BX, lpDueTime-32(SP)
- MOVL CX, hTimer-36(SP)
- MOVL SP, BP
- MOVL runtime·_SetWaitableTimer(SB), AX
- CALL AX
- MOVL BP, SP
-
- MOVL $0, ptime-28(SP)
- MOVL $0, alertable-32(SP)
- MOVL saved_timer-12(SP), CX
- MOVL CX, handle-36(SP)
- MOVL SP, BP
- MOVL runtime·_NtWaitForSingleObject(SB), AX
- CALL AX
- MOVL BP, SP
-
- RET
-
// Runs on OS stack.
TEXT runtime·switchtothread(SB),NOSPLIT,$0
MOVL SP, BP
MOVQ 40(SP), SP
RET
-// Runs on OS stack. duration (in -100ns units) is in dt+0(FP).
-// g is valid.
-TEXT runtime·usleep2HighRes(SB),NOSPLIT,$72-4
- MOVLQSX dt+0(FP), BX
- get_tls(CX)
-
- MOVQ SP, AX
- ANDQ $~15, SP // alignment as per Windows requirement
- MOVQ AX, 64(SP)
-
- MOVQ g(CX), CX
- MOVQ g_m(CX), CX
- MOVQ (m_mOS+mOS_highResTimer)(CX), CX // hTimer
- MOVQ CX, 48(SP) // save hTimer for later
- LEAQ 56(SP), DX // lpDueTime
- MOVQ BX, (DX)
- MOVQ $0, R8 // lPeriod
- MOVQ $0, R9 // pfnCompletionRoutine
- MOVQ $0, AX
- MOVQ AX, 32(SP) // lpArgToCompletionRoutine
- MOVQ AX, 40(SP) // fResume
- MOVQ runtime·_SetWaitableTimer(SB), AX
- CALL AX
-
- MOVQ 48(SP), CX // handle
- MOVQ $0, DX // alertable
- MOVQ $0, R8 // ptime
- MOVQ runtime·_NtWaitForSingleObject(SB), AX
- CALL AX
-
- MOVQ 64(SP), SP
- RET
-
// Runs on OS stack.
TEXT runtime·switchtothread(SB),NOSPLIT,$0
MOVQ SP, AX
MOVW R4, R13 // Restore SP
MOVM.IA.W (R13), [R4, R15] // pop {R4, pc}
-// Runs on OS stack.
-// duration (in -100ns units) is in dt+0(FP).
-// g is valid.
-// TODO: needs to be implemented properly.
-TEXT runtime·usleep2HighRes(SB),NOSPLIT|NOFRAME,$0-4
- B runtime·abort(SB)
-
// Runs on OS stack.
TEXT runtime·switchtothread(SB),NOSPLIT|NOFRAME,$0
MOVM.DB.W [R4, R14], (R13) // push {R4, lr}
ADD $16, RSP
RET
-// Runs on OS stack.
-// duration (in -100ns units) is in dt+0(FP).
-// g is valid.
-// TODO: needs to be implemented properly.
-TEXT runtime·usleep2HighRes(SB),NOSPLIT|NOFRAME,$0-4
- B runtime·abort(SB)
-
// Runs on OS stack.
TEXT runtime·switchtothread(SB),NOSPLIT,$16-0
MOVD runtime·_SwitchToThread(SB), R0