semacquire(&worldsema, false)
gp := getg()
- gp.m.gcing = 1
+ gp.m.preemptoff = "GOMAXPROCS"
systemstack(stoptheworld)
// newprocs will be processed by starttheworld
newprocs = int32(n)
- gp.m.gcing = 0
+ gp.m.preemptoff = ""
semrelease(&worldsema)
systemstack(starttheworld)
return ret
func notetsleep(n *note, ns int64) bool {
gp := getg()
- if gp != gp.m.g0 && gp.m.gcing == 0 {
+ if gp != gp.m.g0 && gp.m.preemptoff != "" {
throw("notetsleep not on g0")
}
func notetsleep(n *note, ns int64) bool {
gp := getg()
- if gp != gp.m.g0 && gp.m.gcing == 0 {
+ if gp != gp.m.g0 && gp.m.preemptoff != "" {
throw("notetsleep not on g0")
}
if gp.m.waitsema == 0 {
// Ok, we're doing it! Stop everybody else
mp := acquirem()
- mp.gcing = 1
+ mp.preemptoff = "gcing"
releasem(mp)
gctimer.count++
if force == 0 {
}
// all done
- mp.gcing = 0
+ mp.preemptoff = ""
if force == 0 {
gctimer.cycle.sweep = nanotime()
// a pending garbage collection already calling it.
semacquire(&worldsema, false)
gp := getg()
- gp.m.gcing = 1
+ gp.m.preemptoff = "read mem stats"
systemstack(stoptheworld)
systemstack(func() {
readmemstats_m(m)
})
- gp.m.gcing = 0
+ gp.m.preemptoff = ""
gp.m.locks++
semrelease(&worldsema)
systemstack(starttheworld)
func runtime_debug_WriteHeapDump(fd uintptr) {
semacquire(&worldsema, false)
gp := getg()
- gp.m.gcing = 1
+ gp.m.preemptoff = "write heap dump"
systemstack(stoptheworld)
systemstack(func() {
writeheapdump_m(fd)
})
- gp.m.gcing = 0
+ gp.m.preemptoff = ""
gp.m.locks++
semrelease(&worldsema)
systemstack(starttheworld)
// The procedure is:
//
// semacquire(&worldsema);
-// m.gcing = 1;
+// m.preemptoff = "reason";
// stoptheworld();
//
// ... do stuff ...
//
-// m.gcing = 0;
+// m.preemptoff = "";
// semrelease(&worldsema);
// starttheworld();
//
if n <= len(p) {
gp := getg()
semacquire(&worldsema, false)
- gp.m.gcing = 1
+ gp.m.preemptoff = "profile"
systemstack(stoptheworld)
n = NumGoroutine()
}
}
- gp.m.gcing = 0
+ gp.m.preemptoff = ""
semrelease(&worldsema)
systemstack(starttheworld)
}
if all {
semacquire(&worldsema, false)
gp := getg()
- gp.m.gcing = 1
+ gp.m.preemptoff = "stack trace"
systemstack(stoptheworld)
}
if all {
gp := getg()
- gp.m.gcing = 0
+ gp.m.preemptoff = ""
semrelease(&worldsema)
systemstack(starttheworld)
}
print("\n")
throw("panic during malloc")
}
- if gp.m.gcing != 0 {
+ if gp.m.preemptoff != "" {
print("panic: ")
printany(e)
print("\n")
- throw("panic during gc")
+ print("preempt off reason: ")
+ print(gp.m.preemptoff)
+ print("\n")
+ throw("panic during preemptoff")
}
if gp.m.locks != 0 {
print("panic: ")
if gp == nil || gp != _m_.curg {
return false
}
- if _m_.locks-_m_.softfloat != 0 || _m_.mallocing != 0 || _m_.throwing != 0 || _m_.gcing != 0 || _m_.dying != 0 {
+ if _m_.locks-_m_.softfloat != 0 || _m_.mallocing != 0 || _m_.throwing != 0 || _m_.preemptoff != "" || _m_.dying != 0 {
return false
}
status := readgstatus(gp)
pc = (*uint8)(unsafe.Pointer(uintptr(funcPC(_ExternalCode) + _PCQuantum)))
}
stk[0] = uintptr(unsafe.Pointer(pc))
- if mp.gcing != 0 || mp.helpgc != 0 {
+ if mp.preemptoff != "" || mp.helpgc != 0 {
stk[1] = funcPC(_GC) + _PCQuantum
} else {
stk[1] = funcPC(_System) + _PCQuantum
if lockedg != nil {
id3 = lockedg.goid
}
- print(" M", mp.id, ": p=", id1, " curg=", id2, " mallocing=", mp.mallocing, " throwing=", mp.throwing, " gcing=", mp.gcing, ""+" locks=", mp.locks, " dying=", mp.dying, " helpgc=", mp.helpgc, " spinning=", mp.spinning, " blocked=", getg().m.blocked, " lockedg=", id3, "\n")
+ print(" M", mp.id, ": p=", id1, " curg=", id2, " mallocing=", mp.mallocing, " throwing=", mp.throwing, " preemptoff=", mp.preemptoff, ""+" locks=", mp.locks, " dying=", mp.dying, " helpgc=", mp.helpgc, " spinning=", mp.spinning, " blocked=", getg().m.blocked, " lockedg=", id3, "\n")
}
lock(&allglock)
id int32
mallocing int32
throwing int32
- gcing int32
+ preemptoff string // if != "", keep curg running on this m
locks int32
softfloat int32
dying int32
}
var x gclinkptr
c := thisg.m.mcache
- if c == nil || thisg.m.gcing != 0 || thisg.m.helpgc != 0 {
+ if c == nil || thisg.m.preemptoff != "" || thisg.m.helpgc != 0 {
// c == nil can happen in the guts of exitsyscall or
// procresize. Just get a stack from the global pool.
// Also don't touch stackcache during gc
}
x := gclinkptr(v)
c := gp.m.mcache
- if c == nil || gp.m.gcing != 0 || gp.m.helpgc != 0 {
+ if c == nil || gp.m.preemptoff != "" || gp.m.helpgc != 0 {
lock(&stackpoolmu)
stackpoolfree(x, order)
unlock(&stackpoolmu)
// Be conservative about where we preempt.
// We are interested in preempting user Go code, not runtime code.
- // If we're holding locks, mallocing, or GCing, don't preempt.
+ // If we're holding locks, mallocing, or preemption is disabled, don't
+ // preempt.
// This check is very early in newstack so that even the status change
// from Grunning to Gwaiting and back doesn't happen in this case.
// That status change by itself can be viewed as a small preemption,
// it needs a lock held by the goroutine), that small preemption turns
// into a real deadlock.
if preempt {
- if thisg.m.locks != 0 || thisg.m.mallocing != 0 || thisg.m.gcing != 0 || thisg.m.p.status != _Prunning {
+ if thisg.m.locks != 0 || thisg.m.mallocing != 0 || thisg.m.preemptoff != "" || thisg.m.p.status != _Prunning {
// Let the goroutine keep running for now.
// gp->preempt is set, so it will be preempted next time.
gp.stackguard0 = gp.stack.lo + _StackGuard
// of all goroutines at the beginning of the trace.
semacquire(&worldsema, false)
_g_ := getg()
- _g_.m.gcing = 1
+ _g_.m.preemptoff = "start tracing"
systemstack(stoptheworld)
// We are in stop-the-world, but syscalls can finish and write to trace concurrently.
if trace.enabled || trace.shutdown {
unlock(&trace.bufLock)
- _g_.m.gcing = 0
+ _g_.m.preemptoff = ""
semrelease(&worldsema)
systemstack(starttheworld)
return errorString("tracing is already enabled")
unlock(&trace.bufLock)
- _g_.m.gcing = 0
+ _g_.m.preemptoff = ""
semrelease(&worldsema)
systemstack(starttheworld)
return nil
// and also to avoid races with traceEvent.
semacquire(&worldsema, false)
_g_ := getg()
- _g_.m.gcing = 1
+ _g_.m.preemptoff = "stop tracing"
systemstack(stoptheworld)
// See the comment in StartTrace.
if !trace.enabled {
unlock(&trace.bufLock)
- _g_.m.gcing = 0
+ _g_.m.preemptoff = ""
semrelease(&worldsema)
systemstack(starttheworld)
return
unlock(&trace.bufLock)
- _g_.m.gcing = 0
+ _g_.m.preemptoff = ""
semrelease(&worldsema)
systemstack(starttheworld)