aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/runtime/asm_amd64p32.s6
-rw-r--r--src/runtime/mgcmark.go25
-rw-r--r--src/runtime/traceback.go2
3 files changed, 28 insertions, 5 deletions
diff --git a/src/runtime/asm_amd64p32.s b/src/runtime/asm_amd64p32.s
index e393431f26..e8b14912b9 100644
--- a/src/runtime/asm_amd64p32.s
+++ b/src/runtime/asm_amd64p32.s
@@ -592,6 +592,12 @@ TEXT runtime·cgocallback(SB),NOSPLIT,$0-12
MOVL 0, AX
RET
+// cgocallback_gofunc(FuncVal*, void *frame, uintptr framesize)
+// Not implemented.
+TEXT ·cgocallback_gofunc(SB),NOSPLIT,$0-12
+ MOVL 0, AX
+ RET
+
// void setg(G*); set g. for use by needm.
// Not implemented.
TEXT runtime·setg(SB), NOSPLIT, $0-4
diff --git a/src/runtime/mgcmark.go b/src/runtime/mgcmark.go
index 42aacb63a6..650d03862e 100644
--- a/src/runtime/mgcmark.go
+++ b/src/runtime/mgcmark.go
@@ -388,9 +388,10 @@ func scanstack(gp *g) {
// frame because on LR machines this LR is not
// on the stack.
if gcphase == _GCscan && n != 0 {
- gcInstallStackBarrier(gp, frame)
- barrierOffset *= 2
- nextBarrier = sp + barrierOffset
+ if gcInstallStackBarrier(gp, frame) {
+ barrierOffset *= 2
+ nextBarrier = sp + barrierOffset
+ }
} else if gcphase == _GCmarktermination {
// We just scanned a frame containing
// a return to a stack barrier. Since
@@ -509,12 +510,25 @@ func gcMaxStackBarriers(stackSize int) (n int) {
// gcInstallStackBarrier installs a stack barrier over the return PC of frame.
//go:nowritebarrier
-func gcInstallStackBarrier(gp *g, frame *stkframe) {
+func gcInstallStackBarrier(gp *g, frame *stkframe) bool {
if frame.lr == 0 {
if debugStackBarrier {
print("not installing stack barrier with no LR, goid=", gp.goid, "\n")
}
- return
+ return false
+ }
+
+ if frame.fn.entry == cgocallback_gofuncPC {
+ // cgocallback_gofunc doesn't return to its LR;
+ // instead, its return path puts LR in g.sched.pc and
+ // switches back to the system stack on which
+ // cgocallback_gofunc was originally called. We can't
+ // have a stack barrier in g.sched.pc, so don't
+ // install one in this frame.
+ if debugStackBarrier {
+ print("not installing stack barrier over LR of cgocallback_gofunc, goid=", gp.goid, "\n")
+ }
+ return false
}
// Save the return PC and overwrite it with stackBarrier.
@@ -538,6 +552,7 @@ func gcInstallStackBarrier(gp *g, frame *stkframe) {
stkbar.savedLRPtr = lrUintptr
stkbar.savedLRVal = uintptr(*lrPtr)
*lrPtr = uintreg(stackBarrierPC)
+ return true
}
// gcRemoveStackBarriers removes all stack barriers installed in gp's stack.
diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go
index 1025032aee..544ce273ee 100644
--- a/src/runtime/traceback.go
+++ b/src/runtime/traceback.go
@@ -48,6 +48,7 @@ var (
systemstack_switchPC uintptr
systemstackPC uintptr
stackBarrierPC uintptr
+ cgocallback_gofuncPC uintptr
gogoPC uintptr
@@ -75,6 +76,7 @@ func tracebackinit() {
systemstack_switchPC = funcPC(systemstack_switch)
systemstackPC = funcPC(systemstack)
stackBarrierPC = funcPC(stackBarrier)
+ cgocallback_gofuncPC = funcPC(cgocallback_gofunc)
// used by sigprof handler
gogoPC = funcPC(gogo)