...
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 if l.key == mutex_locked {
30
31
32 throw("self deadlock")
33 }
34 gp := getg()
35 if gp.m.locks < 0 {
36 throw("lock count")
37 }
38 gp.m.locks++
39 l.key = mutex_locked
40 }
41
42 func unlock(l *mutex) {
43 if l.key == mutex_unlocked {
44 throw("unlock of unlocked lock")
45 }
46 gp := getg()
47 gp.m.locks--
48 if gp.m.locks < 0 {
49 throw("lock count")
50 }
51 l.key = mutex_unlocked
52 }
53
54
55
56 type noteWithTimeout struct {
57 gp *g
58 deadline int64
59 }
60
61 var (
62 notes = make(map[*note]*g)
63 notesWithTimeout = make(map[*note]noteWithTimeout)
64 )
65
66 func noteclear(n *note) {
67 n.key = note_cleared
68 }
69
70 func notewakeup(n *note) {
71
72 if n.key == note_woken {
73 throw("notewakeup - double wakeup")
74 }
75 cleared := n.key == note_cleared
76 n.key = note_woken
77 if cleared {
78 goready(notes[n], 1)
79 }
80 }
81
82 func notesleep(n *note) {
83 throw("notesleep not supported by js")
84 }
85
86 func notetsleep(n *note, ns int64) bool {
87 throw("notetsleep not supported by js")
88 return false
89 }
90
91
92 func notetsleepg(n *note, ns int64) bool {
93 gp := getg()
94 if gp == gp.m.g0 {
95 throw("notetsleepg on g0")
96 }
97
98 if ns >= 0 {
99 deadline := nanotime() + ns
100 delay := ns/1000000 + 1
101 if delay > 1<<31-1 {
102 delay = 1<<31 - 1
103 }
104
105 id := scheduleTimeoutEvent(delay)
106 mp := acquirem()
107 notes[n] = gp
108 notesWithTimeout[n] = noteWithTimeout{gp: gp, deadline: deadline}
109 releasem(mp)
110
111 gopark(nil, nil, waitReasonSleep, traceEvNone, 1)
112
113 clearTimeoutEvent(id)
114 mp = acquirem()
115 delete(notes, n)
116 delete(notesWithTimeout, n)
117 releasem(mp)
118
119 return n.key == note_woken
120 }
121
122 for n.key != note_woken {
123 mp := acquirem()
124 notes[n] = gp
125 releasem(mp)
126
127 gopark(nil, nil, waitReasonZero, traceEvNone, 1)
128
129 mp = acquirem()
130 delete(notes, n)
131 releasem(mp)
132 }
133 return true
134 }
135
136
137 func checkTimeouts() {
138 now := nanotime()
139 for n, nt := range notesWithTimeout {
140 if n.key == note_cleared && now >= nt.deadline {
141 n.key = note_timeout
142 goready(nt.gp, 1)
143 }
144 }
145 }
146
147 var returnedEventHandler *g
148
149 func init() {
150
151 initg := getg()
152 go func() {
153 returnedEventHandler = getg()
154 goready(initg, 1)
155
156 gopark(nil, nil, waitReasonZero, traceEvNone, 1)
157 returnedEventHandler = nil
158
159 pause(getcallersp() - 16)
160 }()
161 gopark(nil, nil, waitReasonZero, traceEvNone, 1)
162 }
163
164
165
166 func beforeIdle() bool {
167 if returnedEventHandler != nil {
168 goready(returnedEventHandler, 1)
169 return true
170 }
171 return false
172 }
173
174
175 func pause(newsp uintptr)
176
177
178
179 func scheduleTimeoutEvent(ms int64) int32
180
181
182 func clearTimeoutEvent(id int32)
183
184 func handleEvent() {
185 prevReturnedEventHandler := returnedEventHandler
186 returnedEventHandler = nil
187
188 checkTimeouts()
189 eventHandler()
190
191 returnedEventHandler = getg()
192 gopark(nil, nil, waitReasonZero, traceEvNone, 1)
193
194 returnedEventHandler = prevReturnedEventHandler
195
196 pause(getcallersp() - 16)
197 }
198
199 var eventHandler func()
200
201
202 func setEventHandler(fn func()) {
203 eventHandler = fn
204 }
205
View as plain text