mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-16 02:33:28 +00:00
runtime,syscall,internal/poll,os: wasip1 poll_oneoff scheduler integration + net.FileListener (#5386)
* 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.
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
//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")
|
||||
}
|
||||
Reference in New Issue
Block a user