Merge from mainline (167278:168000).
[official-gcc/graphite-test-results.git] / libgo / go / sync / mutex.go
blob9a2bb2bb4f548b6701dd361d68f01492e52308d0
1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // The sync package provides basic synchronization primitives
6 // such as mutual exclusion locks. Other than the Once type,
7 // most are intended for use by low-level library routines.
8 // Higher-level synchronization is better done via channels
9 // and communication.
10 package sync
12 import "runtime"
14 func cas(val *uint32, old, new uint32) bool
16 // A Mutex is a mutual exclusion lock.
17 // Mutexes can be created as part of other structures;
18 // the zero value for a Mutex is an unlocked mutex.
19 type Mutex struct {
20 key uint32
21 sema uint32
24 // Add delta to *val, and return the new *val in a thread-safe way. If multiple
25 // goroutines call xadd on the same val concurrently, the changes will be
26 // serialized, and all the deltas will be added in an undefined order.
27 func xadd(val *uint32, delta int32) (new uint32) {
28 for {
29 v := *val
30 nv := v + uint32(delta)
31 if cas(val, v, nv) {
32 return nv
35 panic("unreached")
38 // Lock locks m.
39 // If the lock is already in use, the calling goroutine
40 // blocks until the mutex is available.
41 func (m *Mutex) Lock() {
42 if xadd(&m.key, 1) == 1 {
43 // changed from 0 to 1; we hold lock
44 return
46 runtime.Semacquire(&m.sema)
49 // Unlock unlocks m.
50 // It is a run-time error if m is not locked on entry to Unlock.
52 // A locked Mutex is not associated with a particular goroutine.
53 // It is allowed for one goroutine to lock a Mutex and then
54 // arrange for another goroutine to unlock it.
55 func (m *Mutex) Unlock() {
56 if xadd(&m.key, -1) == 0 {
57 // changed from 1 to 0; no contention
58 return
60 runtime.Semrelease(&m.sema)