]> Cypherpunks.ru repositories - gostls13.git/commitdiff
[dev.garbage] all: merge dev.cc (81884b89bd88) into dev.garbage
authorRuss Cox <rsc@golang.org>
Fri, 5 Dec 2014 16:40:41 +0000 (11:40 -0500)
committerRuss Cox <rsc@golang.org>
Fri, 5 Dec 2014 16:40:41 +0000 (11:40 -0500)
TBR=rlh
CC=golang-codereviews
https://golang.org/cl/181100044

1  2 
src/runtime/proc1.go
src/runtime/stack1.go

index be01f26718fa2ed1b3ddd5bfd742fd066db1e63e,aeded0e77308861bd8f02ff481a5f2ba72bcd3de..5a898ff41bf43927ce2a22908e03f45445b9198d
@@@ -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 gp.preemptscan && !gp.gcworkdone && (oldval == _Grunning || oldval == _Gsyscall) {
 -                      gp.preemptscan = false
 -                      systemstack(func() {
 -                              gcphasework(gp)
 -                      })
 -              }
+               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)
++              //      })
++              // }
+       }
+ }
+ // 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
+               }
        }
  }
  
index c14347dbdfc80ad71aca2512168e3469e42099cf,1fd61ce1a28d84c2f77e1437bf47d24e6e5a4754..28000864d6560856a78d2d41ff20caefe43a1164
@@@ -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.