Source file
src/runtime/lock_js.go
Documentation: runtime
1
2
3
4
5
6
7
8 package runtime
9
10 import (
11 _ "unsafe"
12 )
13
14
15
16 const (
17 mutex_unlocked = 0
18 mutex_locked = 1
19
20 note_cleared = 0
21 note_woken = 1
22 note_timeout = 2
23
24 active_spin = 4
25 active_spin_cnt = 30
26 passive_spin = 1
27 )
28
29 func lock(l *mutex) {
30 lockWithRank(l, getLockRank(l))
31 }
32
33 func lock2(l *mutex) {
34 if l.key == mutex_locked {
35
36
37 throw("self deadlock")
38 }
39 gp := getg()
40 if gp.m.locks < 0 {
41 throw("lock count")
42 }
43 gp.m.locks++
44 l.key = mutex_locked
45 }
46
47 func unlock(l *mutex) {
48 unlockWithRank(l)
49 }
50
51 func unlock2(l *mutex) {
52 if l.key == mutex_unlocked {
53 throw("unlock of unlocked lock")
54 }
55 gp := getg()
56 gp.m.locks--
57 if gp.m.locks < 0 {
58 throw("lock count")
59 }
60 l.key = mutex_unlocked
61 }
62
63
64
65 type noteWithTimeout struct {
66 gp *g
67 deadline int64
68 }
69
70 var (
71 notes = make(map[*note]*g)
72 notesWithTimeout = make(map[*note]noteWithTimeout)
73 )
74
75 func noteclear(n *note) {
76 n.key = note_cleared
77 }
78
79 func notewakeup(n *note) {
80
81 if n.key == note_woken {
82 throw("notewakeup - double wakeup")
83 }
84 cleared := n.key == note_cleared
85 n.key = note_woken
86 if cleared {
87 goready(notes[n], 1)
88 }
89 }
90
91 func notesleep(n *note) {
92 throw("notesleep not supported by js")
93 }
94
95 func notetsleep(n *note, ns int64) bool {
96 throw("notetsleep not supported by js")
97 return false
98 }
99
100
101 func notetsleepg(n *note, ns int64) bool {
102 gp := getg()
103 if gp == gp.m.g0 {
104 throw("notetsleepg on g0")
105 }
106
107 if ns >= 0 {
108 deadline := nanotime() + ns
109 delay := ns/1000000 + 1
110 if delay > 1<<31-1 {
111 delay = 1<<31 - 1
112 }
113
114 id := scheduleTimeoutEvent(delay)
115 mp := acquirem()
116 notes[n] = gp
117 notesWithTimeout[n] = noteWithTimeout{gp: gp, deadline: deadline}
118 releasem(mp)
119
120 gopark(nil, nil, waitReasonSleep, traceEvNone, 1)
121
122 clearTimeoutEvent(id)
123 clearIdleID()
124
125 mp = acquirem()
126 delete(notes, n)
127 delete(notesWithTimeout, n)
128 releasem(mp)
129
130 return n.key == note_woken
131 }
132
133 for n.key != note_woken {
134 mp := acquirem()
135 notes[n] = gp
136 releasem(mp)
137
138 gopark(nil, nil, waitReasonZero, traceEvNone, 1)
139
140 mp = acquirem()
141 delete(notes, n)
142 releasem(mp)
143 }
144 return true
145 }
146
147
148 func checkTimeouts() {
149 now := nanotime()
150 for n, nt := range notesWithTimeout {
151 if n.key == note_cleared && now >= nt.deadline {
152 n.key = note_timeout
153 goready(nt.gp, 1)
154 }
155 }
156 }
157
158
159 var events []*event
160
161 type event struct {
162
163
164 gp *g
165
166
167
168 returned bool
169 }
170
171
172 var idleID int32
173
174
175
176
177
178
179 func beforeIdle(now, pollUntil int64) (gp *g, otherReady bool) {
180 delay := int64(-1)
181 if pollUntil != 0 {
182 delay = pollUntil - now
183 }
184
185 if delay > 0 {
186 clearIdleID()
187 if delay < 1e6 {
188 delay = 1
189 } else if delay < 1e15 {
190 delay = delay / 1e6
191 } else {
192
193
194 delay = 1e9
195 }
196 idleID = scheduleTimeoutEvent(delay)
197 }
198
199 if len(events) == 0 {
200 go handleAsyncEvent()
201 return nil, true
202 }
203
204 e := events[len(events)-1]
205 if e.returned {
206 return e.gp, false
207 }
208 return nil, false
209 }
210
211 func handleAsyncEvent() {
212 pause(getcallersp() - 16)
213 }
214
215
216 func clearIdleID() {
217 if idleID != 0 {
218 clearTimeoutEvent(idleID)
219 idleID = 0
220 }
221 }
222
223
224 func pause(newsp uintptr)
225
226
227
228 func scheduleTimeoutEvent(ms int64) int32
229
230
231 func clearTimeoutEvent(id int32)
232
233
234
235
236
237 func handleEvent() {
238 e := &event{
239 gp: getg(),
240 returned: false,
241 }
242 events = append(events, e)
243
244 eventHandler()
245
246 clearIdleID()
247
248
249 e.returned = true
250 gopark(nil, nil, waitReasonZero, traceEvNone, 1)
251
252 events[len(events)-1] = nil
253 events = events[:len(events)-1]
254
255
256 pause(getcallersp() - 16)
257 }
258
259 var eventHandler func()
260
261
262 func setEventHandler(fn func()) {
263 eventHandler = fn
264 }
265
View as plain text