aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/sync/mutex.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/sync/mutex.go')
-rw-r--r--libgo/go/sync/mutex.go42
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)
}