[1/7] Preprocessor cleanup
[official-gcc.git] / libgo / go / runtime / lock_js.go
blobdf321e5196373c4c797da79683db2c613db07f85
1 // Copyright 2018 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // +build js,wasm
7 package runtime
9 import (
10 _ "unsafe"
13 // js/wasm has no support for threads yet. There is no preemption.
14 // Waiting for a mutex is implemented by allowing other goroutines
15 // to run until the mutex gets unlocked.
17 const (
18 mutex_unlocked = 0
19 mutex_locked = 1
21 note_cleared = 0
22 note_woken = 1
23 note_timeout = 2
25 active_spin = 4
26 active_spin_cnt = 30
27 passive_spin = 1
30 func lock(l *mutex) {
31 for l.key == mutex_locked {
32 mcall(gosched_m)
34 l.key = mutex_locked
37 func unlock(l *mutex) {
38 if l.key == mutex_unlocked {
39 throw("unlock of unlocked lock")
41 l.key = mutex_unlocked
44 // One-time notifications.
46 type noteWithTimeout struct {
47 gp *g
48 deadline int64
51 var (
52 notes = make(map[*note]*g)
53 notesWithTimeout = make(map[*note]noteWithTimeout)
56 func noteclear(n *note) {
57 n.key = note_cleared
60 func notewakeup(n *note) {
61 // gp := getg()
62 if n.key == note_woken {
63 throw("notewakeup - double wakeup")
65 cleared := n.key == note_cleared
66 n.key = note_woken
67 if cleared {
68 goready(notes[n], 1)
72 func notesleep(n *note) {
73 throw("notesleep not supported by js")
76 func notetsleep(n *note, ns int64) bool {
77 throw("notetsleep not supported by js")
78 return false
81 // same as runtimeĀ·notetsleep, but called on user g (not g0)
82 func notetsleepg(n *note, ns int64) bool {
83 gp := getg()
84 if gp == gp.m.g0 {
85 throw("notetsleepg on g0")
88 if ns >= 0 {
89 deadline := nanotime() + ns
90 delay := ns/1000000 + 1 // round up
91 if delay > 1<<31-1 {
92 delay = 1<<31 - 1 // cap to max int32
95 id := scheduleCallback(delay)
96 mp := acquirem()
97 notes[n] = gp
98 notesWithTimeout[n] = noteWithTimeout{gp: gp, deadline: deadline}
99 releasem(mp)
101 gopark(nil, nil, waitReasonSleep, traceEvNone, 1)
103 clearScheduledCallback(id) // note might have woken early, clear timeout
104 mp = acquirem()
105 delete(notes, n)
106 delete(notesWithTimeout, n)
107 releasem(mp)
109 return n.key == note_woken
112 for n.key != note_woken {
113 mp := acquirem()
114 notes[n] = gp
115 releasem(mp)
117 gopark(nil, nil, waitReasonZero, traceEvNone, 1)
119 mp = acquirem()
120 delete(notes, n)
121 releasem(mp)
123 return true
126 // checkTimeouts resumes goroutines that are waiting on a note which has reached its deadline.
127 func checkTimeouts() {
128 now := nanotime()
129 for n, nt := range notesWithTimeout {
130 if n.key == note_cleared && now > nt.deadline {
131 n.key = note_timeout
132 goready(nt.gp, 1)
137 var waitingForCallback *g
139 // sleepUntilCallback puts the current goroutine to sleep until a callback is triggered.
140 // It is currently only used by the callback routine of the syscall/js package.
141 //go:linkname sleepUntilCallback syscall/js.sleepUntilCallback
142 func sleepUntilCallback() {
143 waitingForCallback = getg()
144 gopark(nil, nil, waitReasonZero, traceEvNone, 1)
145 waitingForCallback = nil
148 // pauseSchedulerUntilCallback gets called from the scheduler and pauses the execution
149 // of Go's WebAssembly code until a callback is triggered. Then it checks for note timeouts
150 // and resumes goroutines that are waiting for a callback.
151 func pauseSchedulerUntilCallback() bool {
152 if waitingForCallback == nil && len(notesWithTimeout) == 0 {
153 return false
156 pause()
157 checkTimeouts()
158 if waitingForCallback != nil {
159 goready(waitingForCallback, 1)
161 return true
164 // pause pauses the execution of Go's WebAssembly code until a callback is triggered.
165 func pause()
167 // scheduleCallback tells the WebAssembly environment to trigger a callback after ms milliseconds.
168 // It returns a timer id that can be used with clearScheduledCallback.
169 func scheduleCallback(ms int64) int32
171 // clearScheduledCallback clears a callback scheduled by scheduleCallback.
172 func clearScheduledCallback(id int32)