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