mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-12 06:53:40 +00:00
d01a932201
* runtime,syscall,internal/poll,os: wasip1 poll_oneoff scheduler integration + net.FileListener On wasip1 today every syscall.Read/Write blocks the entire wasm module — the cooperative scheduler invokes poll_oneoff only for sleep/timer wakeups, and there's no path from the net package to a working TCP server. This change fixes both: it threads poll_oneoff through the scheduler's idle path so a goroutine doing FD I/O parks instead of blocking the module, and it provides enough internal/poll / os / syscall surface that upstream Go's net.FileListener / net.FileConn works on a host-pre-opened TCP socket. * runtime: keep scheduler_cooperative idle-wait calls direct TestBinarySize/hifive1b/examples/echo regressed by 32 bytes after the previous commit routed the scheduler's idle wait through a schedulerIdleWait helper. The extra call frame + branch landed on every non-wasip1 cooperative target, where the original direct sleepTicks / waitForEvents calls compile to a single inlined call.
33 lines
1.2 KiB
Go
33 lines
1.2 KiB
Go
//go:build wasip1 && (scheduler.tasks || scheduler.asyncify)
|
|
|
|
package runtime
|
|
|
|
// sleepTicks is the cooperative scheduler's "wait until the next deadline"
|
|
// primitive on wasip1. It is only called by the scheduler when the run queue
|
|
// is empty and there's a sleeping task or pending timer due in d ticks.
|
|
//
|
|
// If any FD waiters are registered via netpollAddWait, this routes through
|
|
// pollIO so the same poll_oneoff call observes both the clock subscription
|
|
// and the FD subscriptions. With no FD waiters it falls back to the cheap
|
|
// single-clock-subscription path.
|
|
func sleepTicks(d timeUnit) {
|
|
if pollCount > 0 {
|
|
pollIO(ticksToNanoseconds(d))
|
|
return
|
|
}
|
|
sleepTicksSubscription.u.u.timeout = uint64(d)
|
|
poll_oneoff(&sleepTicksSubscription, &sleepTicksResult, 1, &sleepTicksNEvents)
|
|
}
|
|
|
|
// waitForEvents is the cooperative scheduler's "wait until something external
|
|
// happens" primitive. It is only called when both the run queue and the
|
|
// timer/sleep queues are empty. With no FD waiters this is a genuine
|
|
// deadlock; with FD waiters we block until any of them is ready.
|
|
func waitForEvents() {
|
|
if pollCount > 0 {
|
|
pollIO(-1)
|
|
return
|
|
}
|
|
runtimePanic("deadlocked: no event source")
|
|
}
|