Commit 28b51184 authored by Austin Clements's avatar Austin Clements

runtime: rename m.gcing to m.preemptoff and make it a string

m.gcing has become overloaded to mean "don't preempt this g" in
general.  Once the garbage collector is preemptible, the one thing it
*won't* mean is that we're in the garbage collector.

So, rename gcing to "preemptoff" and make it a string giving a reason
that preemption is disabled.  gcing was never set to anything but 0 or
1, so we don't have to worry about there being a stack of reasons.

Change-Id: I4337c29e8e942e7aa4f106fc29597e1b5de4ef46
Reviewed-on: https://go-review.googlesource.com/3660Reviewed-by: default avatarRuss Cox <rsc@golang.org>
parent f95becad
......@@ -24,13 +24,13 @@ func GOMAXPROCS(n int) int {
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
......
......@@ -180,7 +180,7 @@ func notetsleep_internal(n *note, ns int64) bool {
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")
}
......
......@@ -240,7 +240,7 @@ func notetsleep_internal(n *note, ns int64, gp *g, deadline int64) bool {
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 {
......
......@@ -362,7 +362,7 @@ func gcwork(force int32) {
// Ok, we're doing it! Stop everybody else
mp := acquirem()
mp.gcing = 1
mp.preemptoff = "gcing"
releasem(mp)
gctimer.count++
if force == 0 {
......@@ -443,7 +443,7 @@ func gcwork(force int32) {
}
// all done
mp.gcing = 0
mp.preemptoff = ""
if force == 0 {
gctimer.cycle.sweep = nanotime()
......
......@@ -81,14 +81,14 @@ func ReadMemStats(m *MemStats) {
// 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)
......@@ -99,14 +99,14 @@ func ReadMemStats(m *MemStats) {
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)
......
......@@ -143,12 +143,12 @@ var gcpercent int32
// The procedure is:
//
// semacquire(&worldsema);
// m.gcing = 1;
// m.preemptoff = "reason";
// stoptheworld();
//
// ... do stuff ...
//
// m.gcing = 0;
// m.preemptoff = "";
// semrelease(&worldsema);
// starttheworld();
//
......
......@@ -522,7 +522,7 @@ func GoroutineProfile(p []StackRecord) (n int, ok bool) {
if n <= len(p) {
gp := getg()
semacquire(&worldsema, false)
gp.m.gcing = 1
gp.m.preemptoff = "profile"
systemstack(stoptheworld)
n = NumGoroutine()
......@@ -544,7 +544,7 @@ func GoroutineProfile(p []StackRecord) (n int, ok bool) {
}
}
gp.m.gcing = 0
gp.m.preemptoff = ""
semrelease(&worldsema)
systemstack(starttheworld)
}
......@@ -567,7 +567,7 @@ func Stack(buf []byte, all bool) int {
if all {
semacquire(&worldsema, false)
gp := getg()
gp.m.gcing = 1
gp.m.preemptoff = "stack trace"
systemstack(stoptheworld)
}
......@@ -591,7 +591,7 @@ func Stack(buf []byte, all bool) int {
if all {
gp := getg()
gp.m.gcing = 0
gp.m.preemptoff = ""
semrelease(&worldsema)
systemstack(starttheworld)
}
......
......@@ -353,11 +353,14 @@ func gopanic(e interface{}) {
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: ")
......
......@@ -135,7 +135,7 @@ func canpanic(gp *g) bool {
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)
......
......@@ -2462,7 +2462,7 @@ func sigprof(pc *uint8, sp *uint8, lr *uint8, gp *g, mp *m) {
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
......@@ -3021,7 +3021,7 @@ func schedtrace(detailed bool) {
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)
......
......@@ -244,7 +244,7 @@ type m struct {
id int32
mallocing int32
throwing int32
gcing int32
preemptoff string // if != "", keep curg running on this m
locks int32
softfloat int32
dying int32
......
......@@ -208,7 +208,7 @@ func stackalloc(n uint32) stack {
}
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
......@@ -271,7 +271,7 @@ func stackfree(stk stack) {
}
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)
......@@ -648,7 +648,8 @@ func newstack() {
// 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,
......@@ -658,7 +659,7 @@ func newstack() {
// 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
......
......@@ -121,7 +121,7 @@ func StartTrace() error {
// 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.
......@@ -133,7 +133,7 @@ func StartTrace() error {
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")
......@@ -162,7 +162,7 @@ func StartTrace() error {
unlock(&trace.bufLock)
_g_.m.gcing = 0
_g_.m.preemptoff = ""
semrelease(&worldsema)
systemstack(starttheworld)
return nil
......@@ -175,7 +175,7 @@ func StopTrace() {
// 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.
......@@ -183,7 +183,7 @@ func StopTrace() {
if !trace.enabled {
unlock(&trace.bufLock)
_g_.m.gcing = 0
_g_.m.preemptoff = ""
semrelease(&worldsema)
systemstack(starttheworld)
return
......@@ -224,7 +224,7 @@ func StopTrace() {
unlock(&trace.bufLock)
_g_.m.gcing = 0
_g_.m.preemptoff = ""
semrelease(&worldsema)
systemstack(starttheworld)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment