// pointers are adjusted correctly by stack shrinking.
c := make(chan *int)
d := make(chan *int)
- ready := make(chan bool)
- go func() {
+ ready1 := make(chan bool)
+ ready2 := make(chan bool)
+
+ f := func(ready chan bool, dup bool) {
// Temporarily grow the stack to 10K.
stackGrowthRecursive((10 << 10) / (128 * 8))
val := 42
var cx *int
cx = &val
+
+ var c2 chan *int
+ var d2 chan *int
+ if dup {
+ c2 = c
+ d2 = d
+ }
+
// Receive from d. cx won't be affected.
select {
case cx = <-c:
+ case <-c2:
case <-d:
+ case <-d2:
}
// Check that pointer in cx was adjusted correctly.
}
}
ready <- true
- }()
+ }
+
+ go f(ready1, false)
+ go f(ready2, true)
- // Let the goroutine get into the select.
- <-ready
+ // Let the goroutines get into the select.
+ <-ready1
+ <-ready2
time.Sleep(10 * time.Millisecond)
// Force concurrent GC a few times.
done:
selectSink = nil
- // Wake select.
- d <- nil
- <-ready
+ // Wake selects.
+ close(d)
+ <-ready1
+ <-ready2
}
func BenchmarkChanNonblocking(b *testing.B) {
// copystack; otherwise, gp may be in the middle of
// putting itself on wait queues and this would
// self-deadlock.
+ var lastc *hchan
for sg := gp.waiting; sg != nil; sg = sg.waitlink {
- lock(&sg.c.lock)
+ if sg.c != lastc {
+ lock(&sg.c.lock)
+ }
+ lastc = sg.c
}
// Adjust sudogs.
}
// Unlock channels.
+ lastc = nil
for sg := gp.waiting; sg != nil; sg = sg.waitlink {
- unlock(&sg.c.lock)
+ if sg.c != lastc {
+ unlock(&sg.c.lock)
+ }
+ lastc = sg.c
}
return sgsize