Left: | ||
Right: |
OLD | NEW |
---|---|
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package sync | 5 package sync |
6 | 6 |
7 import "sync/atomic" | 7 import ( |
8 » "sync/atomic" | |
9 » "unsafe" | |
dvyukov
2012/09/19 22:11:59
Currently this breaks build because of the unexpec
rsc
2012/09/24 15:13:40
I don't understand what dependency we are talking
| |
10 ) | |
8 | 11 |
9 // An RWMutex is a reader/writer mutual exclusion lock. | 12 // An RWMutex is a reader/writer mutual exclusion lock. |
10 // The lock can be held by an arbitrary number of readers | 13 // The lock can be held by an arbitrary number of readers |
11 // or a single writer. | 14 // or a single writer. |
12 // RWMutexes can be created as part of other | 15 // RWMutexes can be created as part of other |
13 // structures; the zero value for a RWMutex is | 16 // structures; the zero value for a RWMutex is |
14 // an unlocked mutex. | 17 // an unlocked mutex. |
15 type RWMutex struct { | 18 type RWMutex struct { |
16 w Mutex // held if there are pending writers | 19 w Mutex // held if there are pending writers |
17 writerSem uint32 // semaphore for writers to wait for completing reade rs | 20 writerSem uint32 // semaphore for writers to wait for completing reade rs |
18 readerSem uint32 // semaphore for readers to wait for completing write rs | 21 readerSem uint32 // semaphore for readers to wait for completing write rs |
19 readerCount int32 // number of pending readers | 22 readerCount int32 // number of pending readers |
20 readerWait int32 // number of departing readers | 23 readerWait int32 // number of departing readers |
21 } | 24 } |
22 | 25 |
23 const rwmutexMaxReaders = 1 << 30 | 26 const rwmutexMaxReaders = 1 << 30 |
24 | 27 |
25 // RLock locks rw for reading. | 28 // RLock locks rw for reading. |
26 func (rw *RWMutex) RLock() { | 29 func (rw *RWMutex) RLock() { |
30 if raceenabled { | |
31 raceDisable() | |
32 } | |
27 if atomic.AddInt32(&rw.readerCount, 1) < 0 { | 33 if atomic.AddInt32(&rw.readerCount, 1) < 0 { |
28 // A writer is pending, wait for it. | 34 // A writer is pending, wait for it. |
29 runtime_Semacquire(&rw.readerSem) | 35 runtime_Semacquire(&rw.readerSem) |
30 } | 36 } |
37 if raceenabled { | |
dvyukov
2012/09/19 22:05:04
It seems for such simple instrumentation raceenabl
| |
38 raceEnable() | |
39 raceAcquire(unsafe.Pointer(&rw.readerSem)) | |
40 } | |
31 } | 41 } |
32 | 42 |
33 // RUnlock undoes a single RLock call; | 43 // RUnlock undoes a single RLock call; |
34 // it does not affect other simultaneous readers. | 44 // it does not affect other simultaneous readers. |
35 // It is a run-time error if rw is not locked for reading | 45 // It is a run-time error if rw is not locked for reading |
36 // on entry to RUnlock. | 46 // on entry to RUnlock. |
37 func (rw *RWMutex) RUnlock() { | 47 func (rw *RWMutex) RUnlock() { |
48 if raceenabled { | |
49 raceReleaseMerge(unsafe.Pointer(&rw.writerSem)) | |
50 raceDisable() | |
51 } | |
38 if atomic.AddInt32(&rw.readerCount, -1) < 0 { | 52 if atomic.AddInt32(&rw.readerCount, -1) < 0 { |
39 // A writer is pending. | 53 // A writer is pending. |
40 if atomic.AddInt32(&rw.readerWait, -1) == 0 { | 54 if atomic.AddInt32(&rw.readerWait, -1) == 0 { |
41 // The last reader unblocks the writer. | 55 // The last reader unblocks the writer. |
42 runtime_Semrelease(&rw.writerSem) | 56 runtime_Semrelease(&rw.writerSem) |
43 } | 57 } |
44 } | 58 } |
59 if raceenabled { | |
60 raceEnable() | |
61 } | |
45 } | 62 } |
46 | 63 |
47 // Lock locks rw for writing. | 64 // Lock locks rw for writing. |
48 // If the lock is already locked for reading or writing, | 65 // If the lock is already locked for reading or writing, |
49 // Lock blocks until the lock is available. | 66 // Lock blocks until the lock is available. |
50 // To ensure that the lock eventually becomes available, | 67 // To ensure that the lock eventually becomes available, |
51 // a blocked Lock call excludes new readers from acquiring | 68 // a blocked Lock call excludes new readers from acquiring |
52 // the lock. | 69 // the lock. |
53 func (rw *RWMutex) Lock() { | 70 func (rw *RWMutex) Lock() { |
71 if raceenabled { | |
72 raceDisable() | |
73 } | |
54 // First, resolve competition with other writers. | 74 // First, resolve competition with other writers. |
55 rw.w.Lock() | 75 rw.w.Lock() |
56 // Announce to readers there is a pending writer. | 76 // Announce to readers there is a pending writer. |
57 r := atomic.AddInt32(&rw.readerCount, -rwmutexMaxReaders) + rwmutexMaxRe aders | 77 r := atomic.AddInt32(&rw.readerCount, -rwmutexMaxReaders) + rwmutexMaxRe aders |
58 // Wait for active readers. | 78 // Wait for active readers. |
59 if r != 0 && atomic.AddInt32(&rw.readerWait, r) != 0 { | 79 if r != 0 && atomic.AddInt32(&rw.readerWait, r) != 0 { |
60 runtime_Semacquire(&rw.writerSem) | 80 runtime_Semacquire(&rw.writerSem) |
61 } | 81 } |
82 if raceenabled { | |
83 raceEnable() | |
84 raceAcquire(unsafe.Pointer(&rw.readerSem)) | |
85 raceAcquire(unsafe.Pointer(&rw.writerSem)) | |
86 } | |
62 } | 87 } |
63 | 88 |
64 // Unlock unlocks rw for writing. It is a run-time error if rw is | 89 // Unlock unlocks rw for writing. It is a run-time error if rw is |
65 // not locked for writing on entry to Unlock. | 90 // not locked for writing on entry to Unlock. |
66 // | 91 // |
67 // As with Mutexes, a locked RWMutex is not associated with a particular | 92 // As with Mutexes, a locked RWMutex is not associated with a particular |
68 // goroutine. One goroutine may RLock (Lock) an RWMutex and then | 93 // goroutine. One goroutine may RLock (Lock) an RWMutex and then |
69 // arrange for another goroutine to RUnlock (Unlock) it. | 94 // arrange for another goroutine to RUnlock (Unlock) it. |
70 func (rw *RWMutex) Unlock() { | 95 func (rw *RWMutex) Unlock() { |
96 if raceenabled { | |
97 raceRelease(unsafe.Pointer(&rw.readerSem)) | |
98 raceRelease(unsafe.Pointer(&rw.writerSem)) | |
99 raceDisable() | |
100 } | |
101 | |
71 // Announce to readers there is no active writer. | 102 // Announce to readers there is no active writer. |
72 r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders) | 103 r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders) |
73 // Unblock blocked readers, if any. | 104 // Unblock blocked readers, if any. |
74 for i := 0; i < int(r); i++ { | 105 for i := 0; i < int(r); i++ { |
75 runtime_Semrelease(&rw.readerSem) | 106 runtime_Semrelease(&rw.readerSem) |
76 } | 107 } |
77 // Allow other writers to proceed. | 108 // Allow other writers to proceed. |
78 rw.w.Unlock() | 109 rw.w.Unlock() |
110 if raceenabled { | |
111 raceEnable() | |
112 } | |
79 } | 113 } |
80 | 114 |
81 // RLocker returns a Locker interface that implements | 115 // RLocker returns a Locker interface that implements |
82 // the Lock and Unlock methods by calling rw.RLock and rw.RUnlock. | 116 // the Lock and Unlock methods by calling rw.RLock and rw.RUnlock. |
83 func (rw *RWMutex) RLocker() Locker { | 117 func (rw *RWMutex) RLocker() Locker { |
84 return (*rlocker)(rw) | 118 return (*rlocker)(rw) |
85 } | 119 } |
86 | 120 |
87 type rlocker RWMutex | 121 type rlocker RWMutex |
88 | 122 |
89 func (r *rlocker) Lock() { (*RWMutex)(r).RLock() } | 123 func (r *rlocker) Lock() { (*RWMutex)(r).RLock() } |
90 func (r *rlocker) Unlock() { (*RWMutex)(r).RUnlock() } | 124 func (r *rlocker) Unlock() { (*RWMutex)(r).RUnlock() } |
OLD | NEW |