diff options
author | Russ Cox <rsc@golang.org> | 2014-12-05 11:18:10 -0500 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2014-12-05 11:18:10 -0500 |
commit | 6d3ba1914e289ed223f7bb69f34604c0e2ae5384 (patch) | |
tree | 3781a05c976360f88b736c71316dadc789e02062 /src/runtime | |
parent | d39e7f8f9d8d330acbcfeba7e8e254b131b05f39 (diff) | |
parent | 3ebebda3a7495402239db4369d59d73749c1bfa2 (diff) | |
download | go-dev.cc.tar.gz |
[dev.cc] all: merge default (8d42099cdc23) into dev.ccdev.cc
TBR=austin
CC=golang-codereviews
https://codereview.appspot.com/178700044
Diffstat (limited to 'src/runtime')
-rw-r--r-- | src/runtime/proc1.go | 23 | ||||
-rw-r--r-- | src/runtime/stack1.go | 8 |
2 files changed, 24 insertions, 7 deletions
diff --git a/src/runtime/proc1.go b/src/runtime/proc1.go index 81b211d0d..aeded0e77 100644 --- a/src/runtime/proc1.go +++ b/src/runtime/proc1.go @@ -371,6 +371,11 @@ func casgstatus(gp *g, oldval, newval uint32) { // 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 @@ -381,6 +386,24 @@ func casgstatus(gp *g, oldval, newval uint32) { } } +// 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 + } + } +} + // stopg ensures that gp is stopped at a GC safe point where its stack can be scanned // or in the context of a moving collector the pointers can be flipped from pointing // to old object to pointing to new objects. diff --git a/src/runtime/stack1.go b/src/runtime/stack1.go index ad83e5895..1fd61ce1a 100644 --- a/src/runtime/stack1.go +++ b/src/runtime/stack1.go @@ -563,13 +563,7 @@ func copystack(gp *g, newsize uintptr) { } memmove(unsafe.Pointer(new.hi-used), unsafe.Pointer(old.hi-used), used) - oldstatus := readgstatus(gp) - oldstatus &^= _Gscan - if oldstatus == _Gwaiting || oldstatus == _Grunnable { - casgstatus(gp, oldstatus, _Gcopystack) // oldstatus is Gwaiting or Grunnable - } else { - gothrow("copystack: bad status, not Gwaiting or Grunnable") - } + oldstatus := casgcopystack(gp) // cas from Gwaiting or Grunnable to Gcopystack, return old status // Swap out old stack for new one gp.stack = new |