Skip to content

Commit 1758492

Browse files
committed
runtime: fix pseudo-randomness on some selects
Fixes #2152. R=golang-dev, dvyukov CC=golang-dev https://golang.org/cl/4888044
1 parent d7440ce commit 1758492

File tree

2 files changed

+35
-1
lines changed

2 files changed

+35
-1
lines changed

src/pkg/runtime/chan.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -904,7 +904,8 @@ selectgo(Select **selp)
904904

905905
// pass 2 - enqueue on all chans
906906
for(i=0; i<sel->ncase; i++) {
907-
cas = &sel->scase[i];
907+
o = sel->pollorder[i];
908+
cas = &sel->scase[o];
908909
c = cas->chan;
909910
sg = &cas->sg;
910911
sg->g = g;

src/pkg/runtime/chan_test.go

+33
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package runtime_test
66

77
import (
88
"runtime"
9+
"sync"
910
"sync/atomic"
1011
"testing"
1112
)
@@ -26,6 +27,38 @@ func TestChanSendInterface(t *testing.T) {
2627
}
2728
}
2829

30+
func TestPseudoRandomSend(t *testing.T) {
31+
n := 100
32+
c := make(chan int)
33+
l := make([]int, n)
34+
var m sync.Mutex
35+
m.Lock()
36+
go func() {
37+
for i := 0; i < n; i++ {
38+
runtime.Gosched()
39+
l[i] = <-c
40+
}
41+
m.Unlock()
42+
}()
43+
for i := 0; i < n; i++ {
44+
select {
45+
case c <- 0:
46+
case c <- 1:
47+
}
48+
}
49+
m.Lock() // wait
50+
n0 := 0
51+
n1 := 0
52+
for _, i := range l {
53+
n0 += (i + 1) % 2
54+
n1 += i
55+
if n0 > n/10 && n1 > n/10 {
56+
return
57+
}
58+
}
59+
t.Errorf("Want pseudo random, got %d zeros and %d ones", n0, n1)
60+
}
61+
2962
func BenchmarkSelectUncontended(b *testing.B) {
3063
const CallsPerSched = 1000
3164
procs := runtime.GOMAXPROCS(-1)

0 commit comments

Comments
 (0)