aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/sync/waitgroup.go
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-09-16 15:47:21 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-09-16 15:47:21 +0000
commitadb0401dac41c81571722312d4586b2693f95aa6 (patch)
treeea2b52e3c258d6b6d9356977c683c7f72a4a5fd5 /libgo/go/sync/waitgroup.go
parent5548ca3540bccbc908a45942896d635ea5f1c23f (diff)
downloadgcc-adb0401dac41c81571722312d4586b2693f95aa6.zip
gcc-adb0401dac41c81571722312d4586b2693f95aa6.tar.gz
gcc-adb0401dac41c81571722312d4586b2693f95aa6.tar.bz2
Update Go library to r60.
From-SVN: r178910
Diffstat (limited to 'libgo/go/sync/waitgroup.go')
-rw-r--r--libgo/go/sync/waitgroup.go41
1 files changed, 26 insertions, 15 deletions
diff --git a/libgo/go/sync/waitgroup.go b/libgo/go/sync/waitgroup.go
index 05478c6..a4c9b7e 100644
--- a/libgo/go/sync/waitgroup.go
+++ b/libgo/go/sync/waitgroup.go
@@ -4,7 +4,10 @@
package sync
-import "runtime"
+import (
+ "runtime"
+ "sync/atomic"
+)
// A WaitGroup waits for a collection of goroutines to finish.
// The main goroutine calls Add to set the number of
@@ -28,8 +31,8 @@ import "runtime"
//
type WaitGroup struct {
m Mutex
- counter int
- waiters int
+ counter int32
+ waiters int32
sema *uint32
}
@@ -48,19 +51,19 @@ type WaitGroup struct {
// Add adds delta, which may be negative, to the WaitGroup counter.
// If the counter becomes zero, all goroutines blocked on Wait() are released.
func (wg *WaitGroup) Add(delta int) {
- wg.m.Lock()
- if delta < -wg.counter {
- wg.m.Unlock()
+ v := atomic.AddInt32(&wg.counter, int32(delta))
+ if v < 0 {
panic("sync: negative WaitGroup count")
}
- wg.counter += delta
- if wg.counter == 0 && wg.waiters > 0 {
- for i := 0; i < wg.waiters; i++ {
- runtime.Semrelease(wg.sema)
- }
- wg.waiters = 0
- wg.sema = nil
+ if v > 0 || atomic.LoadInt32(&wg.waiters) == 0 {
+ return
}
+ wg.m.Lock()
+ for i := int32(0); i < wg.waiters; i++ {
+ runtime.Semrelease(wg.sema)
+ }
+ wg.waiters = 0
+ wg.sema = nil
wg.m.Unlock()
}
@@ -71,12 +74,20 @@ func (wg *WaitGroup) Done() {
// Wait blocks until the WaitGroup counter is zero.
func (wg *WaitGroup) Wait() {
+ if atomic.LoadInt32(&wg.counter) == 0 {
+ return
+ }
wg.m.Lock()
- if wg.counter == 0 {
+ atomic.AddInt32(&wg.waiters, 1)
+ // This code is racing with the unlocked path in Add above.
+ // The code above modifies counter and then reads waiters.
+ // We must modify waiters and then read counter (the opposite order)
+ // to avoid missing an Add.
+ if atomic.LoadInt32(&wg.counter) == 0 {
+ atomic.AddInt32(&wg.waiters, -1)
wg.m.Unlock()
return
}
- wg.waiters++
if wg.sema == nil {
wg.sema = new(uint32)
}