diff options
author | Russ Cox <rsc@golang.org> | 2015-07-11 11:53:58 -0400 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2015-07-13 19:10:22 +0000 |
commit | 8c3533c89bae3493df8a0aad23e56c84f8d25714 (patch) | |
tree | fbb1bb3e3bfc4202e28b9bb39a5c7e2ae177ddf0 /src/runtime/chanbarrier_test.go | |
parent | 242ec168c1394038cee17935f92e28fc24baac8e (diff) | |
download | go-8c3533c89bae3493df8a0aad23e56c84f8d25714.tar.gz go-8c3533c89bae3493df8a0aad23e56c84f8d25714.zip |
runtime: add memory barrier for sync send in select
Missed select case when adding the barrier last time.
All the more reason to refactor this code in Go 1.6.
Fixes #11643.
Change-Id: Ib0d19d6e0939296c0a3e06dda5e9b76f813bbc7e
Reviewed-on: https://go-review.googlesource.com/12086
Reviewed-by: Austin Clements <austin@google.com>
Diffstat (limited to 'src/runtime/chanbarrier_test.go')
-rw-r--r-- | src/runtime/chanbarrier_test.go | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/runtime/chanbarrier_test.go b/src/runtime/chanbarrier_test.go new file mode 100644 index 0000000000..c48fd3c965 --- /dev/null +++ b/src/runtime/chanbarrier_test.go @@ -0,0 +1,80 @@ +// Copyright 2015 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package runtime_test + +import ( + "runtime" + "sync" + "testing" +) + +type response struct { +} + +type myError struct { +} + +func (myError) Error() string { return "" } + +func doRequest(useSelect bool) (*response, error) { + type async struct { + resp *response + err error + } + ch := make(chan *async, 0) + done := make(chan struct{}, 0) + + if useSelect { + go func() { + select { + case ch <- &async{resp: nil, err: myError{}}: + case <-done: + } + }() + } else { + go func() { + ch <- &async{resp: nil, err: myError{}} + }() + } + + r := <-ch + runtime.Gosched() + return r.resp, r.err +} + +func TestChanSendSelectBarrier(t *testing.T) { + testChanSendBarrier(true) +} + +func TestChanSendBarrier(t *testing.T) { + testChanSendBarrier(false) +} + +func testChanSendBarrier(useSelect bool) { + var wg sync.WaitGroup + outer := 100 + inner := 100000 + if testing.Short() { + outer = 10 + inner = 1000 + } + for i := 0; i < outer; i++ { + wg.Add(1) + go func() { + defer wg.Done() + var garbage []byte + for j := 0; j < inner; j++ { + _, err := doRequest(useSelect) + _, ok := err.(myError) + if !ok { + panic(1) + } + garbage = make([]byte, 1<<10) + } + global = garbage + }() + } + wg.Wait() +} |