Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(1003)

Side by Side Diff: src/pkg/sync/rwmutex.go

Issue 6529053: code review 6529053: race: sync changes (Closed)
Patch Set: diff -r 998714a0082d https://dvyukov%40google.com@code.google.com/p/go/ Created 11 years, 6 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/pkg/sync/race0.go ('k') | src/pkg/sync/waitgroup.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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() }
OLDNEW
« no previous file with comments | « src/pkg/sync/race0.go ('k') | src/pkg/sync/waitgroup.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b