Source file
src/runtime/lock_sema_tristate.go
1
2
3
4
5
6
7 package runtime
8
9 import (
10 "internal/runtime/atomic"
11 "unsafe"
12 )
13
14
15
16
17
18
19
20
21
22
23
24
25
26 const (
27 active_spin = 4
28 active_spin_cnt = 30
29 passive_spin = 1
30 )
31
32
33
34
35
36
37
38
39 type mWaitList struct {
40 next muintptr
41 }
42
43 func lockVerifyMSize() {}
44
45 func mutexContended(l *mutex) bool {
46 return atomic.Loaduintptr(&l.key) > locked
47 }
48
49 func lock(l *mutex) {
50 lockWithRank(l, getLockRank(l))
51 }
52
53 func lock2(l *mutex) {
54 gp := getg()
55 if gp.m.locks < 0 {
56 throw("runtimeĀ·lock: lock count")
57 }
58 gp.m.locks++
59
60
61 if atomic.Casuintptr(&l.key, 0, locked) {
62 return
63 }
64 semacreate(gp.m)
65
66 timer := &lockTimer{lock: l}
67 timer.begin()
68
69
70 spin := 0
71 if ncpu > 1 {
72 spin = active_spin
73 }
74 Loop:
75 for i := 0; ; i++ {
76 v := atomic.Loaduintptr(&l.key)
77 if v&locked == 0 {
78
79 if atomic.Casuintptr(&l.key, v, v|locked) {
80 timer.end()
81 return
82 }
83 i = 0
84 }
85 if i < spin {
86 procyield(active_spin_cnt)
87 } else if i < spin+passive_spin {
88 osyield()
89 } else {
90
91
92
93
94 for {
95 gp.m.mWaitList.next = muintptr(v &^ locked)
96 if atomic.Casuintptr(&l.key, v, uintptr(unsafe.Pointer(gp.m))|locked) {
97 break
98 }
99 v = atomic.Loaduintptr(&l.key)
100 if v&locked == 0 {
101 continue Loop
102 }
103 }
104 if v&locked != 0 {
105
106 semasleep(-1)
107 i = 0
108 }
109 }
110 }
111 }
112
113 func unlock(l *mutex) {
114 unlockWithRank(l)
115 }
116
117
118
119
120 func unlock2(l *mutex) {
121 gp := getg()
122 var mp *m
123 for {
124 v := atomic.Loaduintptr(&l.key)
125 if v == locked {
126 if atomic.Casuintptr(&l.key, locked, 0) {
127 break
128 }
129 } else {
130
131
132 mp = muintptr(v &^ locked).ptr()
133 if atomic.Casuintptr(&l.key, v, uintptr(mp.mWaitList.next)) {
134
135 semawakeup(mp)
136 break
137 }
138 }
139 }
140 gp.m.mLockProfile.recordUnlock(l)
141 gp.m.locks--
142 if gp.m.locks < 0 {
143 throw("runtimeĀ·unlock: lock count")
144 }
145 if gp.m.locks == 0 && gp.preempt {
146 gp.stackguard0 = stackPreempt
147 }
148 }
149
View as plain text