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 func checkTimeouts() {
148 now := nanotime()
149 for n, nt := range notesWithTimeout {
150 if n.key == note_cleared && now >= nt.deadline {
151 n.key = note_timeout
152 goready(nt.gp, 1)
153 }
154 }
155 }
156
157
158 var events []*event
159
160 type event struct {
161
162
163 gp *g
164
165
166
167 returned bool
168 }
169
170
171 var idleID int32
172
173
174
175
176
177
178 func beforeIdle(now, pollUntil int64) (gp *g, otherReady bool) {
179 delay := int64(-1)
180 if pollUntil != 0 {
181 delay = pollUntil - now
182 }
183
184 if delay > 0 {
185 clearIdleID()
186 if delay < 1e6 {
187 delay = 1
188 } else if delay < 1e15 {
189 delay = delay / 1e6
190 } else {
191
192
193 delay = 1e9
194 }
195 idleID = scheduleTimeoutEvent(delay)
196 }
197
198 if len(events) == 0 {
199 go handleAsyncEvent()
200 return nil, true
201 }
202
203 e := events[len(events)-1]
204 if e.returned {
205 return e.gp, false
206 }
207 return nil, false
208 }
209
210 func handleAsyncEvent() {
211 pause(getcallersp() - 16)
212 }
213
214
215 func clearIdleID() {
216 if idleID != 0 {
217 clearTimeoutEvent(idleID)
218 idleID = 0
219 }
220 }
221
222
223 func pause(newsp uintptr)
224
225
226
227 func scheduleTimeoutEvent(ms int64) int32
228
229
230 func clearTimeoutEvent(id int32)
231
232
233
234
235
236 func handleEvent() {
237 e := &event{
238 gp: getg(),
239 returned: false,
240 }
241 events = append(events, e)
242
243 eventHandler()
244
245 clearIdleID()
246
247
248 e.returned = true
249 gopark(nil, nil, waitReasonZero, traceEvNone, 1)
250
251 events[len(events)-1] = nil
252 events = events[:len(events)-1]
253
254
255 pause(getcallersp() - 16)
256 }
257
258 var eventHandler func()
259
260
261 func setEventHandler(fn func()) {
262 eventHandler = fn
263 }
264
View as plain text