mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime: wrap procyield assembly and check for 0
procyield will currently loop infinitely if passed 0 on several platforms. This change sidesteps this bug by renaming procyield to procyieldAsm, and adding a wrapper named procyield that checks for cycles == 0. The benefit of this structure is that procyield called with a constant cycle count of 0 will be inlined and constant folded away, the expected behavior of a procyield of 0 cycles. A follow-up change will fix the assembly to not have this footgun anymore. Change-Id: I7068abfeb961bc0fa475e216836f7c0e46b38373 Reviewed-on: https://go-review.googlesource.com/c/go/+/712663 Reviewed-by: Michael Pratt <mpratt@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Cherry Mui <cherryyz@google.com> Auto-Submit: Michael Knyszek <mknyszek@google.com>
This commit is contained in:
parent
ee4d2c312d
commit
f838faffe2
12 changed files with 29 additions and 13 deletions
|
|
@ -597,7 +597,7 @@ CALLFN(·call268435456, 268435456)
|
|||
CALLFN(·call536870912, 536870912)
|
||||
CALLFN(·call1073741824, 1073741824)
|
||||
|
||||
TEXT runtime·procyield(SB),NOSPLIT,$0-0
|
||||
TEXT runtime·procyieldAsm(SB),NOSPLIT,$0-0
|
||||
MOVL cycles+0(FP), AX
|
||||
again:
|
||||
PAUSE
|
||||
|
|
|
|||
|
|
@ -815,7 +815,7 @@ CALLFN(·call268435456, 268435456)
|
|||
CALLFN(·call536870912, 536870912)
|
||||
CALLFN(·call1073741824, 1073741824)
|
||||
|
||||
TEXT runtime·procyield(SB),NOSPLIT,$0-0
|
||||
TEXT runtime·procyieldAsm(SB),NOSPLIT,$0-0
|
||||
MOVL cycles+0(FP), AX
|
||||
again:
|
||||
PAUSE
|
||||
|
|
|
|||
|
|
@ -839,7 +839,7 @@ TEXT runtime·memhash32(SB),NOSPLIT|NOFRAME,$0-12
|
|||
TEXT runtime·memhash64(SB),NOSPLIT|NOFRAME,$0-12
|
||||
JMP runtime·memhash64Fallback(SB)
|
||||
|
||||
TEXT runtime·procyield(SB),NOSPLIT|NOFRAME,$0
|
||||
TEXT runtime·procyieldAsm(SB),NOSPLIT|NOFRAME,$0
|
||||
MOVW cycles+0(FP), R1
|
||||
MOVW $0, R0
|
||||
yieldloop:
|
||||
|
|
|
|||
|
|
@ -1036,7 +1036,7 @@ aesloop:
|
|||
VMOV V0.D[0], R0
|
||||
RET
|
||||
|
||||
TEXT runtime·procyield(SB),NOSPLIT,$0-0
|
||||
TEXT runtime·procyieldAsm(SB),NOSPLIT,$0-0
|
||||
MOVWU cycles+0(FP), R0
|
||||
again:
|
||||
YIELD
|
||||
|
|
|
|||
|
|
@ -505,7 +505,7 @@ CALLFN(·call268435456, 268435456)
|
|||
CALLFN(·call536870912, 536870912)
|
||||
CALLFN(·call1073741824, 1073741824)
|
||||
|
||||
TEXT runtime·procyield(SB),NOSPLIT,$0-0
|
||||
TEXT runtime·procyieldAsm(SB),NOSPLIT,$0-0
|
||||
RET
|
||||
|
||||
// Save state of caller into g->sched.
|
||||
|
|
|
|||
|
|
@ -408,7 +408,7 @@ CALLFN(·call268435456, 268435456)
|
|||
CALLFN(·call536870912, 536870912)
|
||||
CALLFN(·call1073741824, 1073741824)
|
||||
|
||||
TEXT runtime·procyield(SB),NOSPLIT,$0-0
|
||||
TEXT runtime·procyieldAsm(SB),NOSPLIT,$0-0
|
||||
RET
|
||||
|
||||
// Save state of caller into g->sched,
|
||||
|
|
|
|||
|
|
@ -406,7 +406,7 @@ CALLFN(·call268435456, 268435456)
|
|||
CALLFN(·call536870912, 536870912)
|
||||
CALLFN(·call1073741824, 1073741824)
|
||||
|
||||
TEXT runtime·procyield(SB),NOSPLIT,$0-4
|
||||
TEXT runtime·procyieldAsm(SB),NOSPLIT,$0-4
|
||||
RET
|
||||
|
||||
// Save state of caller into g->sched,
|
||||
|
|
|
|||
|
|
@ -612,7 +612,7 @@ CALLFN(·call268435456, 268435456)
|
|||
CALLFN(·call536870912, 536870912)
|
||||
CALLFN(·call1073741824, 1073741824)
|
||||
|
||||
TEXT runtime·procyield(SB),NOSPLIT|NOFRAME,$0-4
|
||||
TEXT runtime·procyieldAsm(SB),NOSPLIT|NOFRAME,$0-4
|
||||
MOVW cycles+0(FP), R7
|
||||
// POWER does not have a pause/yield instruction equivalent.
|
||||
// Instead, we can lower the program priority by setting the
|
||||
|
|
|
|||
|
|
@ -367,8 +367,8 @@ TEXT gogo<>(SB), NOSPLIT|NOFRAME, $0
|
|||
MOV gobuf_pc(T0), T0
|
||||
JALR ZERO, T0
|
||||
|
||||
// func procyield(cycles uint32)
|
||||
TEXT runtime·procyield(SB),NOSPLIT,$0-0
|
||||
// func procyieldAsm(cycles uint32)
|
||||
TEXT runtime·procyieldAsm(SB),NOSPLIT,$0-0
|
||||
RET
|
||||
|
||||
// Switch to m->g0's stack, call fn(g).
|
||||
|
|
|
|||
|
|
@ -506,7 +506,7 @@ CALLFN(·call1073741824, 1073741824)
|
|||
TEXT callfnMVC<>(SB),NOSPLIT|NOFRAME,$0-0
|
||||
MVC $1, 0(R4), 0(R6)
|
||||
|
||||
TEXT runtime·procyield(SB),NOSPLIT,$0-0
|
||||
TEXT runtime·procyieldAsm(SB),NOSPLIT,$0-0
|
||||
RET
|
||||
|
||||
// Save state of caller into g->sched,
|
||||
|
|
|
|||
|
|
@ -200,7 +200,7 @@ TEXT runtime·asminit(SB), NOSPLIT, $0-0
|
|||
TEXT ·publicationBarrier(SB), NOSPLIT, $0-0
|
||||
RET
|
||||
|
||||
TEXT runtime·procyield(SB), NOSPLIT, $0-0 // FIXME
|
||||
TEXT runtime·procyieldAsm(SB), NOSPLIT, $0-0 // FIXME
|
||||
RET
|
||||
|
||||
TEXT runtime·breakpoint(SB), NOSPLIT, $0-0
|
||||
|
|
|
|||
|
|
@ -274,7 +274,23 @@ func reflectcall(stackArgsType *_type, fn, stackArgs unsafe.Pointer, stackArgsSi
|
|||
// See go.dev/issue/67401.
|
||||
//
|
||||
//go:linkname procyield
|
||||
func procyield(cycles uint32)
|
||||
//go:nosplit
|
||||
func procyield(cycles uint32) {
|
||||
if cycles == 0 {
|
||||
return
|
||||
}
|
||||
procyieldAsm(cycles)
|
||||
}
|
||||
|
||||
// procyieldAsm is the assembly implementation of procyield.
|
||||
//
|
||||
// It may loop infinitely if called with cycles == 0. Prefer
|
||||
// procyield, which will compile down to nothing in such cases,
|
||||
// instead.
|
||||
//
|
||||
// FIXME: The implementation really should not loop infinitely if
|
||||
// the number of cycles is 0.
|
||||
func procyieldAsm(cycles uint32)
|
||||
|
||||
type neverCallThisFunction struct{}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue