You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
It has been a month since this issue was reported. Is there any work in progress?
I am new here but I have experience tracing/tweaking RISC-V context handling in Linux kernel. Now PPC64 and MIPS* async-preemption support are fine references, so I'll start from their ports. Any other hints are welcomed.
Basically riscv64 can apply pushCall() from arm64 with slight changes and have a straightforward context saving/restoring runtime.asyncPreempt(). I then test this simple setup with src/runtime/testdata/testprog/preempt.go. Precisely speaking, I disable the dummy function test and the frameless test for simplicity, leaving only the infinite loop for this test.
The infinite loop can be successfully preempted and thus release the main goroutine, but when it reached the end of this test case, the runtime.GC() cannot finish without panic, due to the way riscv64 port treats sp offset, which is not available for NOFRAME functions such as runtime.asyncPreempt. Some work has to be done here. On the other hand, in preprocess(), arm64 and ppc64 do recognize NOFRAME functions with zero stack size (textstksiz), but they don't purely rely on that to calculate Spadj.
The other issue is choosing which register to be clobbered. arm64 and MIPS choose REGTMP, and mark non-atomic call sequence to be not safe for async-preemption. I don't think choosing REGTMP (t6 in riscv64) is as good as previous supports, because there are many other cases that non-atomically use t6. I plan to just use REG_LR (ra in riscv64) here. ra is critical only when an RET instruction or the prologue in a function is async-preempted. For now I am not sure if it will be easier/cleaner than using REGTMP.
I expect to send this patch in a few weeks, hopefully not months.
I'm not sure LR is a good choice. For frameless leaf functions LR is live throughout the entire function. We don't want the whole function be non-preemptible.
On the other hand, the TMP register is only live across sequences of a small number of instructions. It is used for synthesize large offsets, etc. In particular, it won't make an entire loop non-preemptible. It looks to me the usage of REGTMP on RISCV is pretty much the same as on MIPS or ARM64. (Note that we only care code generated by the Go compiler, not assembly code.)
Activity
networkimprov commentedon Jan 23, 2020
@aclements, item for #36365 ?
NonerKao commentedon Feb 29, 2020
It has been a month since this issue was reported. Is there any work in progress?
I am new here but I have experience tracing/tweaking RISC-V context handling in Linux kernel. Now PPC64 and MIPS* async-preemption support are fine references, so I'll start from their ports. Any other hints are welcomed.
NonerKao commentedon Mar 28, 2020
Basically
riscv64
can applypushCall()
fromarm64
with slight changes and have a straightforward context saving/restoringruntime.asyncPreempt()
. I then test this simple setup withsrc/runtime/testdata/testprog/preempt.go
. Precisely speaking, I disable the dummy function test and the frameless test for simplicity, leaving only the infinite loop for this test.The infinite loop can be successfully preempted and thus release the main goroutine, but when it reached the end of this test case, the
runtime.GC()
cannot finish without panic, due to the way riscv64 port treats sp offset, which is not available forNOFRAME
functions such asruntime.asyncPreempt
. Some work has to be done here. On the other hand, inpreprocess()
,arm64
andppc64
do recognizeNOFRAME
functions with zero stack size (textstksiz
), but they don't purely rely on that to calculateSpadj
.The other issue is choosing which register to be clobbered.
arm64
andMIPS
chooseREGTMP
, and mark non-atomic call sequence to be not safe for async-preemption. I don't think choosingREGTMP
(t6
inriscv64
) is as good as previous supports, because there are many other cases that non-atomically uset6
. I plan to just useREG_LR
(ra
inriscv64
) here.ra
is critical only when anRET
instruction or the prologue in a function is async-preempted. For now I am not sure if it will be easier/cleaner than usingREGTMP
.I expect to send this patch in a few weeks, hopefully not months.
cherrymui commentedon Mar 28, 2020
I'm not sure LR is a good choice. For frameless leaf functions LR is live throughout the entire function. We don't want the whole function be non-preemptible.
On the other hand, the TMP register is only live across sequences of a small number of instructions. It is used for synthesize large offsets, etc. In particular, it won't make an entire loop non-preemptible. It looks to me the usage of REGTMP on RISCV is pretty much the same as on MIPS or ARM64. (Note that we only care code generated by the Go compiler, not assembly code.)
NonerKao commentedon Mar 29, 2020
OK, I will check MIPS (69dcdbd) and ARM64 (4736088) to see how they mark REGTMP sequences.
gopherbot commentedon Mar 29, 2020
Change https://golang.org/cl/226206 mentions this issue:
runtime: add async preemption support on riscv64