From 195d1335c0223eaab6f6237e16f187416ec6c5c7 Mon Sep 17 00:00:00 2001 From: doujiang24 Date: Sun, 12 Jun 2022 20:08:05 +0800 Subject: [PATCH] change to emit create event in exitsyscall. --- src/runtime/cgocall.go | 9 ++++++ src/runtime/proc.go | 61 +++++++++++++++++++++++++++++------------ src/runtime/runtime2.go | 1 + src/runtime/trace.go | 7 +---- 4 files changed, 55 insertions(+), 23 deletions(-) diff --git a/src/runtime/cgocall.go b/src/runtime/cgocall.go index a0c9560fd0f65..0b3166f0e995f 100644 --- a/src/runtime/cgocall.go +++ b/src/runtime/cgocall.go @@ -227,6 +227,9 @@ func cgocallbackg(fn, frame unsafe.Pointer, ctxt uintptr) { savedpc := gp.syscallpc exitsyscall() // coming out of cgo call gp.m.incgo = false + if gp.m.isextra { + gp.m.cgolevel++ + } osPreemptExtExit(gp.m) @@ -237,6 +240,12 @@ func cgocallbackg(fn, frame unsafe.Pointer, ctxt uintptr) { // This is enforced by checking incgo in the schedule function. gp.m.incgo = true + if gp.m.isextra { + gp.m.cgolevel-- + if gp.m.cgolevel < 0 { + throw("unexpected negative cgolevel") + } + } if gp.m != checkm { throw("m changed unexpectedly in cgocallbackg") diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 95988b7eba033..ee295034843f2 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -1917,11 +1917,6 @@ func oneNewExtraM() { if raceenabled { gp.racectx = racegostart(abi.FuncPCABIInternal(newextram) + sys.PCQuantum) } - if trace.enabled { - traceGoCreate(gp, 0) // no start pc - gp.traceseq++ - traceEvent(traceEvGoInSyscall, -1, uint64(gp.goid)) - } // put on allg for garbage collector allgadd(gp) @@ -2515,9 +2510,13 @@ func execute(gp *g, inheritTime bool) { } if trace.enabled { - // GoSysExit has to happen when we have a P, but before GoStart. - // So we emit it here. - if gp.syscallsp != 0 && gp.sysblocktraced { + if gp.m.isextra && gp.m.cgolevel == 0 { + // GoCreate happen in needm, but there is no P. + // So we emit it here. + traceGoCreate(gp, 0) // no start pc for locked g in extra M + } else if gp.syscallsp != 0 && gp.sysblocktraced { + // GoSysExit has to happen when we have a P, but before GoStart. + // So we emit it here. traceGoSysExit(gp.sysexitticks) } traceGoStart() @@ -3615,7 +3614,14 @@ func reentersyscall(pc, sp uintptr) { } if trace.enabled { - systemstack(traceGoSysCall) + if _g_.m.isextra && _g_.m.cgolevel == 0 { + systemstack(func() { + traceGoEnd() + traceProcStop(_g_.m.p.ptr()) + }) + } else { + systemstack(traceGoSysCall) + } // systemstack itself clobbers g.sched.{pc,sp} and we might // need them later when the G is genuinely blocked in a // syscall @@ -3639,10 +3645,19 @@ func reentersyscall(pc, sp uintptr) { pp.m = 0 _g_.m.oldp.set(pp) _g_.m.p = 0 - atomic.Store(&pp.status, _Psyscall) - if sched.gcwaiting != 0 { - systemstack(entersyscall_gcwait) + + if _g_.m.isextra && _g_.m.cgolevel == 0 { + atomic.Store(&pp.status, _Pidle) + systemstack(func() { + handoffp(pp) + }) save(pc, sp) + } else { + atomic.Store(&pp.status, _Psyscall) + if sched.gcwaiting != 0 { + systemstack(entersyscall_gcwait) + save(pc, sp) + } } _g_.m.locks-- @@ -3851,7 +3866,13 @@ func exitsyscallfast(oldp *p) bool { osyield() } } - traceGoSysExit(0) + if _g_.m.isextra && _g_.m.cgolevel == 0 { + // GoCreate happen in needm, but there is no P. + // So we emit it here. + traceGoCreate(_g_, 0) // no start pc for locked g in extra M + } else { + traceGoSysExit(0) + } } }) if ok { @@ -3874,10 +3895,16 @@ func exitsyscallfast_reacquired() { // traceGoSysBlock for this syscall was already emitted, // but here we effectively retake the p from the new syscall running on the same p. systemstack(func() { - // Denote blocking of the new syscall. - traceGoSysBlock(_g_.m.p.ptr()) - // Denote completion of the current syscall. - traceGoSysExit(0) + if _g_.m.isextra && _g_.m.cgolevel == 0 { + // GoCreate happen in needm, but there is no P. + // So we emit it here. + traceGoCreate(_g_, 0) // no start pc for locked g in extra M + } else { + // Denote blocking of the new syscall. + traceGoSysBlock(_g_.m.p.ptr()) + // Denote completion of the current syscall. + traceGoSysExit(0) + } }) } _g_.m.p.ptr().syscalltick++ diff --git a/src/runtime/runtime2.go b/src/runtime/runtime2.go index d308e455e7d81..8e665d277cf24 100644 --- a/src/runtime/runtime2.go +++ b/src/runtime/runtime2.go @@ -540,6 +540,7 @@ type m struct { printlock int8 incgo bool // m is executing a cgo call isextra bool // m is an extra m + cgolevel int32 // level of cgo call freeWait uint32 // if == 0, safe to free g0 and delete m (atomic) fastrand uint64 needextram bool diff --git a/src/runtime/trace.go b/src/runtime/trace.go index 12200a5063da0..6ec54a402949a 100644 --- a/src/runtime/trace.go +++ b/src/runtime/trace.go @@ -225,17 +225,12 @@ func StartTrace() error { // World is stopped, no need to lock. forEachGRace(func(gp *g) { status := readgstatus(gp) - if status != _Gdead || (gp.m != nil && gp.m.isextra) { + if status != _Gdead { gp.traceseq = 0 gp.tracelastp = getg().m.p // +PCQuantum because traceFrameForPC expects return PCs and subtracts PCQuantum. id := trace.stackTab.put([]uintptr{startPCforTrace(gp.startpc) + sys.PCQuantum}) traceEvent(traceEvGoCreate, -1, uint64(gp.goid), uint64(id), stackID) - - if status == _Gdead { - gp.traceseq++ - traceEvent(traceEvGoInSyscall, -1, uint64(gp.goid)) - } } if status == _Gwaiting { // traceEvGoWaiting is implied to have seq=1.