...
Source file
src/runtime/rwmutex.go
Documentation: runtime
1
2
3
4
5 package runtime
6
7 import (
8 "runtime/internal/atomic"
9 )
10
11
12
13
14
15
16
17
18 type rwmutex struct {
19 rLock mutex
20 readers muintptr
21 readerPass uint32
22
23 wLock mutex
24 writer muintptr
25
26 readerCount uint32
27 readerWait uint32
28 }
29
30 const rwmutexMaxReaders = 1 << 30
31
32
33 func (rw *rwmutex) rlock() {
34
35
36
37
38 acquirem()
39 if int32(atomic.Xadd(&rw.readerCount, 1)) < 0 {
40
41 systemstack(func() {
42 lockWithRank(&rw.rLock, lockRankRwmutexR)
43 if rw.readerPass > 0 {
44
45 rw.readerPass -= 1
46 unlock(&rw.rLock)
47 } else {
48
49
50 m := getg().m
51 m.schedlink = rw.readers
52 rw.readers.set(m)
53 unlock(&rw.rLock)
54 notesleep(&m.park)
55 noteclear(&m.park)
56 }
57 })
58 }
59 }
60
61
62 func (rw *rwmutex) runlock() {
63 if r := int32(atomic.Xadd(&rw.readerCount, -1)); r < 0 {
64 if r+1 == 0 || r+1 == -rwmutexMaxReaders {
65 throw("runlock of unlocked rwmutex")
66 }
67
68 if atomic.Xadd(&rw.readerWait, -1) == 0 {
69
70 lockWithRank(&rw.rLock, lockRankRwmutexR)
71 w := rw.writer.ptr()
72 if w != nil {
73 notewakeup(&w.park)
74 }
75 unlock(&rw.rLock)
76 }
77 }
78 releasem(getg().m)
79 }
80
81
82 func (rw *rwmutex) lock() {
83
84 lockWithRank(&rw.wLock, lockRankRwmutexW)
85 m := getg().m
86
87 r := int32(atomic.Xadd(&rw.readerCount, -rwmutexMaxReaders)) + rwmutexMaxReaders
88
89 lockWithRank(&rw.rLock, lockRankRwmutexR)
90 if r != 0 && atomic.Xadd(&rw.readerWait, r) != 0 {
91
92 systemstack(func() {
93 rw.writer.set(m)
94 unlock(&rw.rLock)
95 notesleep(&m.park)
96 noteclear(&m.park)
97 })
98 } else {
99 unlock(&rw.rLock)
100 }
101 }
102
103
104 func (rw *rwmutex) unlock() {
105
106 r := int32(atomic.Xadd(&rw.readerCount, rwmutexMaxReaders))
107 if r >= rwmutexMaxReaders {
108 throw("unlock of unlocked rwmutex")
109 }
110
111 lockWithRank(&rw.rLock, lockRankRwmutexR)
112 for rw.readers.ptr() != nil {
113 reader := rw.readers.ptr()
114 rw.readers = reader.schedlink
115 reader.schedlink.set(nil)
116 notewakeup(&reader.park)
117 r -= 1
118 }
119
120
121 rw.readerPass += uint32(r)
122 unlock(&rw.rLock)
123
124 unlock(&rw.wLock)
125 }
126
View as plain text