scanblock(uintptr(unsafe.Pointer(&gp.sched.ctxt)), goarch.PtrSize, &oneptrmask[0], gcw, &state)
}
+ // Scan conservatively the extended register state.
+ if gp.asyncSafePoint {
+ xRegScan(gp, gcw, &state)
+ }
+
// Scan the stack. Accumulate a list of stack objects.
var u unwinder
for u.init(gp, 0); u.valid(); u.next() {
// While asynchronous preemption stores general-purpose (GP) registers on the
// preempted goroutine's own stack, extended register state can be used to save
// non-GP state off the stack. In particular, this is meant for large vector
-// register files. Currently, we assume this contains only scalar data, though
-// we could change this constraint by conservatively scanning this memory.
+// register files. This memory is conservatively scanned to enable using
+// non-GP registers for operations that may involve pointers.
//
// For an architecture to support extended register state, it must provide a Go
// definition of an xRegState type for storing the state, and its asyncPreempt
package runtime
import (
+ "internal/abi"
"internal/runtime/sys"
"unsafe"
)
unlock(&xRegAlloc.lock)
}
}
+
+// xRegScan conservatively scans the extended register state.
+//
+// This is supposed to be called only by scanstack when it handles async preemption.
+func xRegScan(gp *g, gcw *gcWork, state *stackScanState) {
+ // Regular async preemption always provides the extended register state.
+ if gp.xRegs.state == nil {
+ var u unwinder
+ for u.init(gp, 0); u.valid(); u.next() {
+ if u.frame.fn.valid() && u.frame.fn.funcID == abi.FuncID_debugCallV2 {
+ return
+ }
+ }
+ println("runtime: gp=", gp, ", goid=", gp.goid)
+ throw("gp.xRegs.state == nil on a scanstack attempt during async preemption")
+ }
+ b := uintptr(unsafe.Pointer(&gp.xRegs.state.regs))
+ n := uintptr(unsafe.Sizeof(gp.xRegs.state.regs))
+ if debugScanConservative {
+ print("begin scan xRegs of goroutine ", gp.goid, " at [", hex(b), ",", hex(b+n), ")\n")
+ }
+ scanConservative(b, n, nil, gcw, state)
+ if debugScanConservative {
+ print("end scan xRegs of goroutine ", gp.goid, "\n")
+ }
+}