9a2bb2bb4f548b6701dd361d68f01492e52308d0
[platform/upstream/gcc.git] / libgo / go / sync / mutex.go
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.
4
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
11
12 import "runtime"
13
14 func cas(val *uint32, old, new uint32) bool
15
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
22 }
23
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
33                 }
34         }
35         panic("unreached")
36 }
37
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
45         }
46         runtime.Semacquire(&m.sema)
47 }
48
49 // Unlock unlocks m.
50 // It is a run-time error if m is not locked on entry to Unlock.
51 //
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
59         }
60         runtime.Semrelease(&m.sema)
61 }