]> Cypherpunks repositories - gostls13.git/commitdiff
runtime: fix pseudo-randomness on some selects
authorGustavo Niemeyer <gustavo@niemeyer.net>
Mon, 15 Aug 2011 06:51:51 +0000 (03:51 -0300)
committerGustavo Niemeyer <gustavo@niemeyer.net>
Mon, 15 Aug 2011 06:51:51 +0000 (03:51 -0300)
Fixes #2152.

R=golang-dev, dvyukov
CC=golang-dev
https://golang.org/cl/4888044

src/pkg/runtime/chan.c
src/pkg/runtime/chan_test.go

index 65feacb78b4858ba36723cc7483e468b8aa3b018..ffb32616fd1df1357d00a511321baa97a30306a7 100644 (file)
@@ -904,7 +904,8 @@ loop:
 
        // pass 2 - enqueue on all chans
        for(i=0; i<sel->ncase; i++) {
-               cas = &sel->scase[i];
+               o = sel->pollorder[i];
+               cas = &sel->scase[o];
                c = cas->chan;
                sg = &cas->sg;
                sg->g = g;
index 71c9e2fd785491c07369dddc7821c08908980d25..46ddfd7e88f52e9b206e63f0f4a291dedc72a99b 100644 (file)
@@ -6,6 +6,7 @@ package runtime_test
 
 import (
        "runtime"
+       "sync"
        "sync/atomic"
        "testing"
 )
@@ -26,6 +27,38 @@ func TestChanSendInterface(t *testing.T) {
        }
 }
 
+func TestPseudoRandomSend(t *testing.T) {
+       n := 100
+       c := make(chan int)
+       l := make([]int, n)
+       var m sync.Mutex
+       m.Lock()
+       go func() {
+               for i := 0; i < n; i++ {
+                       runtime.Gosched()
+                       l[i] = <-c
+               }
+               m.Unlock()
+       }()
+       for i := 0; i < n; i++ {
+               select {
+               case c <- 0:
+               case c <- 1:
+               }
+       }
+       m.Lock() // wait
+       n0 := 0
+       n1 := 0
+       for _, i := range l {
+               n0 += (i + 1) % 2
+               n1 += i
+               if n0 > n/10 && n1 > n/10 {
+                       return
+               }
+       }
+       t.Errorf("Want pseudo random, got %d zeros and %d ones", n0, n1)
+}
+
 func BenchmarkSelectUncontended(b *testing.B) {
        const CallsPerSched = 1000
        procs := runtime.GOMAXPROCS(-1)