mirror of
https://github.com/golang/go
synced 2024-11-16 23:04:44 -07:00
runtime: implement high resolution timer on windows arm/arm64
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>
This commit is contained in:
parent
b561ebab46
commit
b6f29d2365
@ -440,13 +440,7 @@ func createHighResTimer() uintptr {
|
||||
_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
|
||||
@ -1130,7 +1124,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)
|
||||
func usleep2HighRes(dt int32)
|
||||
func switchtothread()
|
||||
|
||||
//go:nosplit
|
||||
@ -1152,13 +1145,15 @@ func usleep_no_g(us uint32) {
|
||||
//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))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -241,43 +241,6 @@ TEXT runtime·usleep2(SB),NOSPLIT,$20-4
|
||||
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
|
||||
|
@ -251,39 +251,6 @@ TEXT runtime·usleep2(SB),NOSPLIT,$48-4
|
||||
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
|
||||
|
@ -211,13 +211,6 @@ TEXT runtime·usleep2(SB),NOSPLIT|NOFRAME,$0-4
|
||||
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}
|
||||
|
@ -239,13 +239,6 @@ TEXT runtime·usleep2(SB),NOSPLIT,$32-4
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user