...
Source file
src/sync/rwmutex.go
Documentation: sync
1
2
3
4
5 package sync
6
7 import (
8 "internal/race"
9 "sync/atomic"
10 "unsafe"
11 )
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 type RWMutex struct {
29 w Mutex
30 writerSem uint32
31 readerSem uint32
32 readerCount int32
33 readerWait int32
34 }
35
36 const rwmutexMaxReaders = 1 << 30
37
38
39
40
41
42
43 func (rw *RWMutex) RLock() {
44 if race.Enabled {
45 _ = rw.w.state
46 race.Disable()
47 }
48 if atomic.AddInt32(&rw.readerCount, 1) < 0 {
49
50 runtime_SemacquireMutex(&rw.readerSem, false)
51 }
52 if race.Enabled {
53 race.Enable()
54 race.Acquire(unsafe.Pointer(&rw.readerSem))
55 }
56 }
57
58
59
60
61
62 func (rw *RWMutex) RUnlock() {
63 if race.Enabled {
64 _ = rw.w.state
65 race.ReleaseMerge(unsafe.Pointer(&rw.writerSem))
66 race.Disable()
67 }
68 if r := atomic.AddInt32(&rw.readerCount, -1); r < 0 {
69 if r+1 == 0 || r+1 == -rwmutexMaxReaders {
70 race.Enable()
71 throw("sync: RUnlock of unlocked RWMutex")
72 }
73
74 if atomic.AddInt32(&rw.readerWait, -1) == 0 {
75
76 runtime_Semrelease(&rw.writerSem, false)
77 }
78 }
79 if race.Enabled {
80 race.Enable()
81 }
82 }
83
84
85
86
87 func (rw *RWMutex) Lock() {
88 if race.Enabled {
89 _ = rw.w.state
90 race.Disable()
91 }
92
93 rw.w.Lock()
94
95 r := atomic.AddInt32(&rw.readerCount, -rwmutexMaxReaders) + rwmutexMaxReaders
96
97 if r != 0 && atomic.AddInt32(&rw.readerWait, r) != 0 {
98 runtime_SemacquireMutex(&rw.writerSem, false)
99 }
100 if race.Enabled {
101 race.Enable()
102 race.Acquire(unsafe.Pointer(&rw.readerSem))
103 race.Acquire(unsafe.Pointer(&rw.writerSem))
104 }
105 }
106
107
108
109
110
111
112
113 func (rw *RWMutex) Unlock() {
114 if race.Enabled {
115 _ = rw.w.state
116 race.Release(unsafe.Pointer(&rw.readerSem))
117 race.Disable()
118 }
119
120
121 r := atomic.AddInt32(&rw.readerCount, rwmutexMaxReaders)
122 if r >= rwmutexMaxReaders {
123 race.Enable()
124 throw("sync: Unlock of unlocked RWMutex")
125 }
126
127 for i := 0; i < int(r); i++ {
128 runtime_Semrelease(&rw.readerSem, false)
129 }
130
131 rw.w.Unlock()
132 if race.Enabled {
133 race.Enable()
134 }
135 }
136
137
138
139 func (rw *RWMutex) RLocker() Locker {
140 return (*rlocker)(rw)
141 }
142
143 type rlocker RWMutex
144
145 func (r *rlocker) Lock() { (*RWMutex)(r).RLock() }
146 func (r *rlocker) Unlock() { (*RWMutex)(r).RUnlock() }
147
View as plain text