runtime: implement osyield 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.

Change-Id: I26a223b918c6c462b06ac256bdacf9ddb78752bc
Reviewed-on: https://go-review.googlesource.com/c/go/+/526476
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
This commit is contained in:
qmuntal 2023-09-07 12:41:37 +02:00 committed by Quim Muntal
parent c4af8abae1
commit d73a33f1c3
5 changed files with 33 additions and 41 deletions

View file

@ -955,6 +955,22 @@ func mdestroy(mp *m) {
}
}
// asmstdcall_trampoline calls asmstdcall converting from Go to C calling convention.
func asmstdcall_trampoline(args unsafe.Pointer)
// stdcall_no_g calls asmstdcall on os stack without using g.
//
//go:nosplit
func stdcall_no_g(fn stdFunction, n int, args uintptr) uintptr {
libcall := libcall{
fn: uintptr(unsafe.Pointer(fn)),
n: uintptr(n),
args: args,
}
asmstdcall_trampoline(noescape(unsafe.Pointer(&libcall)))
return libcall.r1
}
// Calling stdcall on os stack.
// May run during STW, so write barriers are not allowed.
//
@ -1054,16 +1070,17 @@ 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 switchtothread()
//go:nosplit
func osyield_no_g() {
switchtothread()
stdcall_no_g(_SwitchToThread, 0, 0)
}
//go:nosplit
func osyield() {
systemstack(switchtothread)
systemstack(func() {
stdcall0(_SwitchToThread)
})
}
//go:nosplit

View file

@ -11,6 +11,9 @@
#define TEB_TlsSlots 0xE10
#define TEB_ArbitraryPtr 0x14
TEXT runtime·asmstdcall_trampoline<ABIInternal>(SB),NOSPLIT,$0
JMP runtime·asmstdcall(SB)
// void runtime·asmstdcall(void *c);
TEXT runtime·asmstdcall(SB),NOSPLIT,$0
MOVL fn+0(FP), BX
@ -248,14 +251,6 @@ TEXT runtime·usleep2(SB),NOSPLIT,$20-4
MOVL BP, SP
RET
// Runs on OS stack.
TEXT runtime·switchtothread(SB),NOSPLIT,$0
MOVL SP, BP
MOVL runtime·_SwitchToThread(SB), AX
CALL AX
MOVL BP, SP
RET
TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
loop:
MOVL (_INTERRUPT_TIME+time_hi1), AX

View file

@ -12,6 +12,10 @@
#define TEB_TlsSlots 0x1480
#define TEB_ArbitraryPtr 0x28
TEXT runtime·asmstdcall_trampoline<ABIInternal>(SB),NOSPLIT,$0
MOVQ AX, CX
JMP runtime·asmstdcall(SB)
// void runtime·asmstdcall(void *c);
TEXT runtime·asmstdcall(SB),NOSPLIT,$16
MOVQ SP, AX
@ -258,18 +262,6 @@ TEXT runtime·usleep2(SB),NOSPLIT,$48-4
MOVQ 40(SP), SP
RET
// Runs on OS stack.
TEXT runtime·switchtothread(SB),NOSPLIT,$0
MOVQ SP, AX
ANDQ $~15, SP // alignment as per Windows requirement
SUBQ $(48), SP // room for SP and 4 args as per Windows requirement
// plus one extra word to keep stack 16 bytes aligned
MOVQ AX, 32(SP)
MOVQ runtime·_SwitchToThread(SB), AX
CALL AX
MOVQ 32(SP), SP
RET
TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
MOVQ $_INTERRUPT_TIME, DI
MOVQ time_lo(DI), AX

View file

@ -9,6 +9,9 @@
// Note: For system ABI, R0-R3 are args, R4-R11 are callee-save.
TEXT runtime·asmstdcall_trampoline<ABIInternal>(SB),NOSPLIT,$0
B runtime·asmstdcall(SB)
// void runtime·asmstdcall(void *c);
TEXT runtime·asmstdcall(SB),NOSPLIT|NOFRAME,$0
MOVM.DB.W [R4, R5, R14], (R13) // push {r4, r5, lr}
@ -211,16 +214,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.
TEXT runtime·switchtothread(SB),NOSPLIT|NOFRAME,$0
MOVM.DB.W [R4, R14], (R13) // push {R4, lr}
MOVW R13, R4
BIC $0x7, R13 // alignment for ABI
MOVW runtime·_SwitchToThread(SB), R0
BL (R0)
MOVW R4, R13 // restore stack pointer
MOVM.IA.W (R13), [R4, R15] // pop {R4, pc}
TEXT ·publicationBarrier(SB),NOSPLIT|NOFRAME,$0-0
B runtime·armPublicationBarrier(SB)

View file

@ -19,6 +19,9 @@
//
// load_g and save_g (in tls_arm64.s) clobber R27 (REGTMP) and R0.
TEXT runtime·asmstdcall_trampoline<ABIInternal>(SB),NOSPLIT,$0
B runtime·asmstdcall(SB)
// void runtime·asmstdcall(void *c);
TEXT runtime·asmstdcall(SB),NOSPLIT,$16
STP (R19, R20), 16(RSP) // save old R19, R20
@ -240,14 +243,6 @@ TEXT runtime·usleep2(SB),NOSPLIT,$32-4
ADD $16, RSP
RET
// Runs on OS stack.
TEXT runtime·switchtothread(SB),NOSPLIT,$16-0
MOVD runtime·_SwitchToThread(SB), R0
SUB $16, RSP // skip over saved frame pointer below RSP
BL (R0)
ADD $16, RSP
RET
TEXT runtime·nanotime1(SB),NOSPLIT,$0-8
MOVD $_INTERRUPT_TIME, R3
MOVD time_lo(R3), R0