@@ -721,9 +721,13 @@ func casgstatus(gp *g, oldval, newval uint32) {
721
721
throw ("casgstatus" )
722
722
}
723
723
724
+ // See http://golang.org/cl/21503 for justification of the yield delay.
725
+ const yieldDelay = 5 * 1000
726
+ var nextYield int64
727
+
724
728
// loop if gp->atomicstatus is in a scan state giving
725
729
// GC time to finish and change the state to oldval.
726
- for ! atomic .Cas (& gp .atomicstatus , oldval , newval ) {
730
+ for i := 0 ; ! atomic .Cas (& gp .atomicstatus , oldval , newval ); i ++ {
727
731
if oldval == _Gwaiting && gp .atomicstatus == _Grunnable {
728
732
systemstack (func () {
729
733
throw ("casgstatus: waiting for Gwaiting but is Grunnable" )
@@ -736,6 +740,18 @@ func casgstatus(gp *g, oldval, newval uint32) {
736
740
// gcphasework(gp)
737
741
// })
738
742
// }
743
+ // But meanwhile just yield.
744
+ if i == 0 {
745
+ nextYield = nanotime () + yieldDelay
746
+ }
747
+ if nanotime () < nextYield {
748
+ for x := 0 ; x < 10 && gp .atomicstatus != oldval ; x ++ {
749
+ procyield (1 )
750
+ }
751
+ } else {
752
+ osyield ()
753
+ nextYield = nanotime () + yieldDelay / 2
754
+ }
739
755
}
740
756
if newval == _Grunning {
741
757
gp .gcscanvalid = false
@@ -773,12 +789,17 @@ func scang(gp *g) {
773
789
774
790
gp .gcscandone = false
775
791
792
+ // See http://golang.org/cl/21503 for justification of the yield delay.
793
+ const yieldDelay = 10 * 1000
794
+ var nextYield int64
795
+
776
796
// Endeavor to get gcscandone set to true,
777
797
// either by doing the stack scan ourselves or by coercing gp to scan itself.
778
798
// gp.gcscandone can transition from false to true when we're not looking
779
799
// (if we asked for preemption), so any time we lock the status using
780
800
// castogscanstatus we have to double-check that the scan is still not done.
781
- for ! gp .gcscandone {
801
+ loop:
802
+ for i := 0 ; ! gp .gcscandone ; i ++ {
782
803
switch s := readgstatus (gp ); s {
783
804
default :
784
805
dumpgstatus (gp )
@@ -787,6 +808,7 @@ func scang(gp *g) {
787
808
case _Gdead :
788
809
// No stack.
789
810
gp .gcscandone = true
811
+ break loop
790
812
791
813
case _Gcopystack :
792
814
// Stack being switched. Go around again.
@@ -802,6 +824,7 @@ func scang(gp *g) {
802
824
gp .gcscandone = true
803
825
}
804
826
restartg (gp )
827
+ break loop
805
828
}
806
829
807
830
case _Gscanwaiting :
@@ -827,6 +850,16 @@ func scang(gp *g) {
827
850
casfrom_Gscanstatus (gp , _Gscanrunning , _Grunning )
828
851
}
829
852
}
853
+
854
+ if i == 0 {
855
+ nextYield = nanotime () + yieldDelay
856
+ }
857
+ if nanotime () < nextYield {
858
+ procyield (10 )
859
+ } else {
860
+ osyield ()
861
+ nextYield = nanotime () + yieldDelay / 2
862
+ }
830
863
}
831
864
832
865
gp .preemptscan = false // cancel scan request if no longer needed
0 commit comments