From: Russ Cox Date: Fri, 5 Dec 2014 16:40:41 +0000 (-0500) Subject: [dev.garbage] all: merge dev.cc (81884b89bd88) into dev.garbage X-Git-Tag: go1.5beta1~2684^2~3 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=444839014bce7046165358bb6e920ad35c3463c2;p=gostls13.git [dev.garbage] all: merge dev.cc (81884b89bd88) into dev.garbage TBR=rlh CC=golang-codereviews https://golang.org/cl/181100044 --- 444839014bce7046165358bb6e920ad35c3463c2 diff --cc src/runtime/proc1.go index be01f26718,aeded0e773..5a898ff41b --- a/src/runtime/proc1.go +++ b/src/runtime/proc1.go @@@ -375,6 -371,36 +375,36 @@@ func casgstatus(gp *g, oldval, newval u // loop if gp->atomicstatus is in a scan state giving // GC time to finish and change the state to oldval. for !cas(&gp.atomicstatus, oldval, newval) { + if oldval == _Gwaiting && gp.atomicstatus == _Grunnable { + systemstack(func() { + gothrow("casgstatus: waiting for Gwaiting but is Grunnable") + }) + } + // Help GC if needed. - if gp.preemptscan && !gp.gcworkdone && (oldval == _Grunning || oldval == _Gsyscall) { - gp.preemptscan = false - systemstack(func() { - gcphasework(gp) - }) - } ++ // if gp.preemptscan && !gp.gcworkdone && (oldval == _Grunning || oldval == _Gsyscall) { ++ // gp.preemptscan = false ++ // systemstack(func() { ++ // gcphasework(gp) ++ // }) ++ // } + } + } + + // casgstatus(gp, oldstatus, Gcopystack), assuming oldstatus is Gwaiting or Grunnable. + // Returns old status. Cannot call casgstatus directly, because we are racing with an + // async wakeup that might come in from netpoll. If we see Gwaiting from the readgstatus, + // it might have become Grunnable by the time we get to the cas. If we called casgstatus, + // it would loop waiting for the status to go back to Gwaiting, which it never will. + //go:nosplit + func casgcopystack(gp *g) uint32 { + for { + oldstatus := readgstatus(gp) &^ _Gscan + if oldstatus != _Gwaiting && oldstatus != _Grunnable { + gothrow("copystack: bad status, not Gwaiting or Grunnable") + } + if cas(&gp.atomicstatus, oldstatus, _Gcopystack) { + return oldstatus + } } } diff --cc src/runtime/stack1.go index c14347dbdf,1fd61ce1a2..28000864d6 --- a/src/runtime/stack1.go +++ b/src/runtime/stack1.go @@@ -718,12 -708,8 +718,10 @@@ func newstack() gothrow("stack overflow") } - oldstatus := readgstatus(gp) - oldstatus &^= _Gscan - casgstatus(gp, oldstatus, _Gcopystack) // oldstatus is Gwaiting or Grunnable - // Note that the concurrent GC might be scanning the stack as we try to replace it. - // copystack takes care of the appropriate coordination with the stack scanner. ++ casgstatus(gp, _Gwaiting, _Gcopystack) + + // The concurrent GC will not scan the stack while we are doing the copy since + // the gp is in a Gcopystack status. copystack(gp, uintptr(newsize)) if stackDebug >= 1 { print("stack grow done\n") @@@ -788,18 -777,7 +786,10 @@@ func shrinkstack(gp *g) if stackDebug > 0 { print("shrinking stack ", oldsize, "->", newsize, "\n") } + - // This is being done in a Gscan state and was initiated by the GC so no need to move to - // the Gcopystate. - // The world is stopped, so the goroutine must be Gwaiting or Grunnable, - // and what it is is not changing underfoot. - oldstatus := readgstatus(gp) &^ _Gscan - if oldstatus != _Gwaiting && oldstatus != _Grunnable { - gothrow("status is not Gwaiting or Grunnable") - } - casgstatus(gp, oldstatus, _Gcopystack) ++ oldstatus := casgcopystack(gp) copystack(gp, newsize) + casgstatus(gp, _Gcopystack, oldstatus) } // Do any delayed stack freeing that was queued up during GC.