diff options
Diffstat (limited to 'src/pkg/sync/mutex.go')
-rw-r--r-- | src/pkg/sync/mutex.go | 31 |
1 files changed, 12 insertions, 19 deletions
diff --git a/src/pkg/sync/mutex.go b/src/pkg/sync/mutex.go index 2a1270b9c..da565d38d 100644 --- a/src/pkg/sync/mutex.go +++ b/src/pkg/sync/mutex.go @@ -9,37 +9,30 @@ // 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,11 +46,11 @@ 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() { - switch v := xadd(&m.key, -1); { + switch v := atomic.AddInt32(&m.key, -1); { case v == 0: // changed from 1 to 0; no contention return - case int32(v) == -1: + case v == -1: // changed from 0 to -1: wasn't locked // (or there are 4 billion goroutines waiting) panic("sync: unlock of unlocked mutex") |