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.
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.
31 for 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 {
52 notes
= make(map[*note
]*g
)
53 notesWithTimeout
= make(map[*note
]noteWithTimeout
)
56 func noteclear(n
*note
) {
60 func notewakeup(n
*note
) {
62 if n
.key
== note_woken
{
63 throw("notewakeup - double wakeup")
65 cleared
:= n
.key
== note_cleared
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")
81 // same as runtimeĀ·notetsleep, but called on user g (not g0)
82 func notetsleepg(n
*note
, ns
int64) bool {
85 throw("notetsleepg on g0")
89 deadline
:= nanotime() + ns
90 delay
:= ns
/1000000 + 1 // round up
92 delay
= 1<<31 - 1 // cap to max int32
95 id
:= scheduleCallback(delay
)
98 notesWithTimeout
[n
] = noteWithTimeout
{gp
: gp
, deadline
: deadline
}
101 gopark(nil, nil, waitReasonSleep
, traceEvNone
, 1)
103 clearScheduledCallback(id
) // note might have woken early, clear timeout
106 delete(notesWithTimeout
, n
)
109 return n
.key
== note_woken
112 for n
.key
!= note_woken
{
117 gopark(nil, nil, waitReasonZero
, traceEvNone
, 1)
126 // checkTimeouts resumes goroutines that are waiting on a note which has reached its deadline.
127 func checkTimeouts() {
129 for n
, nt
:= range notesWithTimeout
{
130 if n
.key
== note_cleared
&& now
> nt
.deadline
{
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 {
158 if waitingForCallback
!= nil {
159 goready(waitingForCallback
, 1)
164 // pause pauses the execution of Go's WebAssembly code until a callback is triggered.
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)