]> Cypherpunks repositories - gostls13.git/commitdiff
race: sync changes
authorDmitriy Vyukov <dvyukov@google.com>
Sun, 7 Oct 2012 18:07:03 +0000 (22:07 +0400)
committerDmitriy Vyukov <dvyukov@google.com>
Sun, 7 Oct 2012 18:07:03 +0000 (22:07 +0400)
This is a part of a bigger change that adds data race detection feature:
https://golang.org/cl/6456044

R=rsc, minux.ma
CC=gobot, golang-dev
https://golang.org/cl/6529053

src/pkg/go/build/deps_test.go
src/pkg/sync/cond.go
src/pkg/sync/mutex.go
src/pkg/sync/race.go [new file with mode: 0644]
src/pkg/sync/race0.go [new file with mode: 0644]
src/pkg/sync/rwmutex.go
src/pkg/sync/waitgroup.go

index e1f4f8c63e4bdd470669f64e67a72494db37df34..efed739dd216ee9482fc6c8ec587fdba104b9f59 100644 (file)
@@ -30,7 +30,7 @@ var pkgDeps = map[string][]string{
        "errors":      {},
        "io":          {"errors", "sync"},
        "runtime":     {"unsafe"},
-       "sync":        {"sync/atomic"},
+       "sync":        {"sync/atomic", "unsafe"},
        "sync/atomic": {"unsafe"},
        "unsafe":      {},
 
index 1fc3deaf1e0c40013cc9b53cc210bf8f551dd6b6..491b985691975cb7a3f7704b4ce1480fa261564d 100644 (file)
@@ -56,6 +56,9 @@ func NewCond(l Locker) *Cond {
 //    c.L.Unlock()
 //
 func (c *Cond) Wait() {
+       if raceenabled {
+               raceDisable()
+       }
        c.m.Lock()
        if c.newSema == nil {
                c.newSema = new(uint32)
@@ -63,6 +66,9 @@ func (c *Cond) Wait() {
        s := c.newSema
        c.newWaiters++
        c.m.Unlock()
+       if raceenabled {
+               raceEnable()
+       }
        c.L.Unlock()
        runtime_Semacquire(s)
        c.L.Lock()
@@ -73,6 +79,9 @@ func (c *Cond) Wait() {
 // It is allowed but not required for the caller to hold c.L
 // during the call.
 func (c *Cond) Signal() {
+       if raceenabled {
+               raceDisable()
+       }
        c.m.Lock()
        if c.oldWaiters == 0 && c.newWaiters > 0 {
                // Retire old generation; rename new to old.
@@ -86,6 +95,9 @@ func (c *Cond) Signal() {
                runtime_Semrelease(c.oldSema)
        }
        c.m.Unlock()
+       if raceenabled {
+               raceEnable()
+       }
 }
 
 // Broadcast wakes all goroutines waiting on c.
@@ -93,6 +105,9 @@ func (c *Cond) Signal() {
 // It is allowed but not required for the caller to hold c.L
 // during the call.
 func (c *Cond) Broadcast() {
+       if raceenabled {
+               raceDisable()
+       }
        c.m.Lock()
        // Wake both generations.
        if c.oldWaiters > 0 {
@@ -109,4 +124,7 @@ func (c *Cond) Broadcast() {
                c.newSema = nil
        }
        c.m.Unlock()
+       if raceenabled {
+               raceEnable()
+       }
 }
index 9494cc3f82679f6cf364d91bb519727c7cfb54a2..b4629ebca539bb976aff1ecd1d85b16a6d55e3b9 100644 (file)
 // Values containing the types defined in this package should not be copied.
 package sync
 
-import "sync/atomic"
+import (
+       "sync/atomic"
+       "unsafe"
+)
 
 // A Mutex is a mutual exclusion lock.
 // Mutexes can be created as part of other structures;
@@ -38,6 +41,9 @@ const (
 func (m *Mutex) Lock() {
        // Fast path: grab unlocked mutex.
        if atomic.CompareAndSwapInt32(&m.state, 0, mutexLocked) {
+               if raceenabled {
+                       raceAcquire(unsafe.Pointer(m))
+               }
                return
        }
 
@@ -61,6 +67,10 @@ func (m *Mutex) Lock() {
                        awoke = true
                }
        }
+
+       if raceenabled {
+               raceAcquire(unsafe.Pointer(m))
+       }
 }
 
 // Unlock unlocks m.
@@ -70,6 +80,10 @@ func (m *Mutex) Lock() {
 // It is allowed for one goroutine to lock a Mutex and then
 // arrange for another goroutine to unlock it.
 func (m *Mutex) Unlock() {
+       if raceenabled {
+               raceRelease(unsafe.Pointer(m))
+       }
+
        // Fast path: drop lock bit.
        new := atomic.AddInt32(&m.state, -mutexLocked)
        if (new+mutexLocked)&mutexLocked == 0 {
diff --git a/src/pkg/sync/race.go b/src/pkg/sync/race.go
new file mode 100644 (file)
index 0000000..d9431af
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2012 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.
+
+// +build race
+
+package sync
+
+import (
+       "runtime"
+       "unsafe"
+)
+
+const raceenabled = true
+
+func raceAcquire(addr unsafe.Pointer) {
+       runtime.RaceAcquire(addr)
+}
+
+func raceRelease(addr unsafe.Pointer) {
+       runtime.RaceRelease(addr)
+}
+
+func raceReleaseMerge(addr unsafe.Pointer) {
+       runtime.RaceReleaseMerge(addr)
+}
+
+func raceDisable() {
+       runtime.RaceDisable()
+}
+
+func raceEnable() {
+       runtime.RaceEnable()
+}
diff --git a/src/pkg/sync/race0.go b/src/pkg/sync/race0.go
new file mode 100644 (file)
index 0000000..bef14f9
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2012 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.
+
+// +build !race
+
+package sync
+
+import (
+       "unsafe"
+)
+
+const raceenabled = false
+
+func raceAcquire(addr unsafe.Pointer) {
+}
+
+func raceRelease(addr unsafe.Pointer) {
+}
+
+func raceReleaseMerge(addr unsafe.Pointer) {
+}
+
+func raceDisable() {
+}
+
+func raceEnable() {
+}
index 782a9c319682b9bade8a0204363b9cbce8f27edc..b494c64355e2c3fc59d7115e3c233da9f6f9dc3b 100644 (file)
@@ -4,7 +4,10 @@
 
 package sync
 
-import "sync/atomic"
+import (
+       "sync/atomic"
+       "unsafe"
+)
 
 // An RWMutex is a reader/writer mutual exclusion lock.
 // The lock can be held by an arbitrary number of readers
@@ -24,10 +27,17 @@ const rwmutexMaxReaders = 1 << 30
 
 // RLock locks rw for reading.
 func (rw *RWMutex) RLock() {
+       if raceenabled {
+               raceDisable()
+       }
        if atomic.AddInt32(&rw.readerCount, 1) < 0 {
                // A writer is pending, wait for it.
                runtime_Semacquire(&rw.readerSem)
        }
+       if raceenabled {
+               raceEnable()
+               raceAcquire(unsafe.Pointer(&rw.readerSem))
+       }
 }
 
 // RUnlock undoes a single RLock call;
@@ -35,6 +45,10 @@ func (rw *RWMutex) RLock() {
 // It is a run-time error if rw is not locked for reading
 // on entry to RUnlock.
 func (rw *RWMutex) RUnlock() {
+       if raceenabled {
+               raceReleaseMerge(unsafe.Pointer(&rw.writerSem))
+               raceDisable()
+       }
        if atomic.AddInt32(&rw.readerCount, -1) < 0 {
                // A writer is pending.
                if atomic.AddInt32(&rw.readerWait, -1) == 0 {
@@ -42,6 +56,9 @@ func (rw *RWMutex) RUnlock() {
                        runtime_Semrelease(&rw.writerSem)
                }
        }
+       if raceenabled {
+               raceEnable()
+       }
 }
 
 // Lock locks rw for writing.
@@ -51,6 +68,9 @@ func (rw *RWMutex) RUnlock() {
 // a blocked Lock call excludes new readers from acquiring
 // the lock.
 func (rw *RWMutex) Lock() {
+       if raceenabled {
+               raceDisable()
+       }
        // First, resolve competition with other writers.
        rw.w.Lock()
        // Announce to readers there is a pending writer.
@@ -59,6 +79,11 @@ func (rw *RWMutex) Lock() {
        if r != 0 && atomic.AddInt32(&rw.readerWait, r) != 0 {
                runtime_Semacquire(&rw.writerSem)
        }
+       if raceenabled {
+               raceEnable()
+               raceAcquire(unsafe.Pointer(&rw.readerSem))
+               raceAcquire(unsafe.Pointer(&rw.writerSem))
+       }
 }
 
 // Unlock unlocks rw for writing.  It is a run-time error if rw is
@@ -68,6 +93,12 @@ func (rw *RWMutex) Lock() {
 // goroutine.  One goroutine may RLock (Lock) an RWMutex and then
 // arrange for another goroutine to RUnlock (Unlock) it.
 func (rw *RWMutex) Unlock() {
+       if raceenabled {
+               raceRelease(unsafe.Pointer(&rw.readerSem))
+               raceRelease(unsafe.Pointer(&rw.writerSem))
+               raceDisable()
+       }
+
        // Announce to readers there is no active writer.
        r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders)
        // Unblock blocked readers, if any.
@@ -76,6 +107,9 @@ func (rw *RWMutex) Unlock() {
        }
        // Allow other writers to proceed.
        rw.w.Unlock()
+       if raceenabled {
+               raceEnable()
+       }
 }
 
 // RLocker returns a Locker interface that implements
index bc9e738e784ce31593574b00755a72bd9b58a6df..9b0ffec58b34b6af2bc8c198606e9c6234a0faa6 100644 (file)
@@ -4,7 +4,10 @@
 
 package sync
 
-import "sync/atomic"
+import (
+       "sync/atomic"
+       "unsafe"
+)
 
 // A WaitGroup waits for a collection of goroutines to finish.
 // The main goroutine calls Add to set the number of
@@ -34,6 +37,11 @@ type WaitGroup struct {
 // If the counter becomes zero, all goroutines blocked on Wait() are released.
 // If the counter goes negative, Add panics.
 func (wg *WaitGroup) Add(delta int) {
+       if raceenabled {
+               raceReleaseMerge(unsafe.Pointer(wg))
+               raceDisable()
+               defer raceEnable()
+       }
        v := atomic.AddInt32(&wg.counter, int32(delta))
        if v < 0 {
                panic("sync: negative WaitGroup counter")
@@ -57,7 +65,14 @@ func (wg *WaitGroup) Done() {
 
 // Wait blocks until the WaitGroup counter is zero.
 func (wg *WaitGroup) Wait() {
+       if raceenabled {
+               raceDisable()
+       }
        if atomic.LoadInt32(&wg.counter) == 0 {
+               if raceenabled {
+                       raceEnable()
+                       raceAcquire(unsafe.Pointer(wg))
+               }
                return
        }
        wg.m.Lock()
@@ -68,7 +83,15 @@ func (wg *WaitGroup) Wait() {
        // to avoid missing an Add.
        if atomic.LoadInt32(&wg.counter) == 0 {
                atomic.AddInt32(&wg.waiters, -1)
+               if raceenabled {
+                       raceEnable()
+                       raceAcquire(unsafe.Pointer(wg))
+                       raceDisable()
+               }
                wg.m.Unlock()
+               if raceenabled {
+                       raceEnable()
+               }
                return
        }
        if wg.sema == nil {
@@ -77,4 +100,8 @@ func (wg *WaitGroup) Wait() {
        s := wg.sema
        wg.m.Unlock()
        runtime_Semacquire(s)
+       if raceenabled {
+               raceEnable()
+               raceAcquire(unsafe.Pointer(wg))
+       }
 }