diff options
Diffstat (limited to 'libgo/go/sync/mutex.go')
-rw-r--r-- | libgo/go/sync/mutex.go | 42 |
1 files changed, 20 insertions, 22 deletions
diff --git a/libgo/go/sync/mutex.go b/libgo/go/sync/mutex.go index 9a2bb2b..da565d3 100644 --- a/libgo/go/sync/mutex.go +++ b/libgo/go/sync/mutex.go @@ -3,43 +3,36 @@ // license that can be found in the LICENSE file. // The sync package provides basic synchronization primitives -// such as mutual exclusion locks. Other than the Once type, -// most are intended for use by low-level library routines. -// Higher-level synchronization is better done via channels -// and communication. +// such as mutual exclusion locks. Other than the Once and +// WaitGroup types, most are intended for use by low-level +// library routines. Higher-level synchronization is better +// done via channels and communication. package sync -import "runtime" - -func cas(val *uint32, old, new uint32) bool +import ( + "runtime" + "sync/atomic" +) // A Mutex is a mutual exclusion lock. // Mutexes can be created as part of other structures; // the zero value for a Mutex is an unlocked mutex. type Mutex struct { - key uint32 + key int32 sema uint32 } -// Add delta to *val, and return the new *val in a thread-safe way. If multiple -// goroutines call xadd on the same val concurrently, the changes will be -// serialized, and all the deltas will be added in an undefined order. -func xadd(val *uint32, delta int32) (new uint32) { - for { - v := *val - nv := v + uint32(delta) - if cas(val, v, nv) { - return nv - } - } - panic("unreached") +// A Locker represents an object that can be locked and unlocked. +type Locker interface { + Lock() + Unlock() } // Lock locks m. // If the lock is already in use, the calling goroutine // blocks until the mutex is available. func (m *Mutex) Lock() { - if xadd(&m.key, 1) == 1 { + if atomic.AddInt32(&m.key, 1) == 1 { // changed from 0 to 1; we hold lock return } @@ -53,9 +46,14 @@ 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 xadd(&m.key, -1) == 0 { + switch v := atomic.AddInt32(&m.key, -1); { + case v == 0: // changed from 1 to 0; no contention return + case v == -1: + // changed from 0 to -1: wasn't locked + // (or there are 4 billion goroutines waiting) + panic("sync: unlock of unlocked mutex") } runtime.Semrelease(&m.sema) } |