Skip to content

adopt CM#705 sync-call scheduling: exclusive-thread resumability, candidate sets, backpressure STARTING #249

Open

Description

@lannbot

CM#705 (merged upstream; migration map polyengine#173) changed the sync-call mini-scheduler's semantics beyond the may_enter removal: the exclusive thread is no longer excluded from the resume candidate set, and callback-task threads parked on the exclusive lock become resumable during a sync call. polyengine's driveSyncLift (runtime/src/task/scheduler.ts) implements the pinned (pre-#705) form — candidates exclude inst.exclusiveThread — and the adjacent backpressure behavior produces pre-#705 subtask codes.

New/changed corpus rows pinning the merged semantics (xfailed under class cm705-sync-sched until this issue closes):

  • test/async/during-sync-call-exclusive-resume.wast (new; replaces the deleted during-sync-call-no-exclusive-resume.wast with inverted semantics): a parked callback-task thread holding/waiting on the exclusive lock must be resumable mid-sync-call.
  • test/async/during-sync-scheduling-candidates.wast (new, 484 lines): candidate-set membership per thread kind; §3 (parked callback-task threads, incl. driven from a sibling), §4 (callback thread blocked mid-frame holding the lock), §5 (sync-lifted async-typed function's thread blocked mid-frame) expect resumability the current scheduler refuses.
  • test/async/during-sync-call-may-block-if-other-ready-threads.wast (rewritten): appended third component needs mid-sync-call resumption of a parked callback-task thread.
  • test/async/during-sync-call-no-sibling-resume.wast: the pinned rule (only same-instance threads) is unchanged, but the expected trap is now "cannot block a synchronous task before returning" where we produce the deadlock message — verify/align the trap site.
  • test/async/sync-streams.wast (changed by the #705 commit): an async-lowered call into a callee whose exclusive lock is held now returns STARTING (queued by automatic backpressure) instead of STARTED, and the rendezvous completion codes swap (COMPLETED|4 / DROPPED|4). Requires the queuing behavior, not just the candidate set.

Scope of the fix:

  1. Drop the t !== task.inst.exclusiveThread exclusion in driveSyncLift; align the candidate set with merged canon_lift (all ready threads of the callee instance).
  2. Adopt the surrounding merged semantics the new rows exercise: exclusive-lock interaction with the mini-scheduler, backpressure queuing of async-lowered entries while the lock is held (STARTING), and the trap-message alignment in the no-sibling case.
  3. Retire the cm705-sync-sched xfail class; the stale-xfail detector enforces completeness.

Authority: design/mvp/canonical-abi/definitions.py at the advanced pin (tie-breaker), Concurrency.md §Reentrance/§Blocking as merged in CM#705. Scheduler core is single-owner territory (AGENTS.md): coder-hard at most, close orchestrator review.

Activity

  1. added
    p2Minor bugs; desirable lower-priority features
    on Aug 30, 2026
  2. lannbot commented on Aug 30, 2026

    @lannbot
    CollaboratorAuthor

    Scope re-derivation before implementation, two findings:

    1. CM#716 overlap (open upstream, see #250). #716 restructures the callback event-loop turn (wait_from_callback, the YIELD/WAIT exclusive-lock dance) but does NOT touch this issue's core: the canon_lift sync drive loop's candidate set (the exclusive-thread exclusion removal) and canon_lower's backpressure/initial-status behavior are #705 semantics already at our pin, byte-identical in #716. Safe to implement now: driveSyncLift's exclusion removal, the during-sync-call-no-sibling-resume trap-message alignment ("cannot block a synchronous task before returning"). The callback-loop candidate rows (§3/§4/§6 of during-sync-scheduling-candidates) are #152-translate-blocked in the corpus anyway AND sit in #716's blast radius — implement them last, or after #716 settles.

    2. The sync-streams.wast:208 row collides with the #43 adjudication. The row's new STARTING expectation is the pristine-definitions.py answer that #43 adjudicated as an upstream test defect when the expectation pointed the other way (STARTED, satisfied via the hold-gate + drain-to-quiescence entry policy mirroring wasmtime's deferred-entry model). CM#705 flipping the committed expectation is upstream declaring the pristine answer normative under the post-may_enter model — so adopting this row means revisiting #43's named adjudication, not just tweaking codes: the drain-to-quiescence entry policy itself is what answers STARTED. Check what wasmtime's deferred-entry policy looks like post-#705-adoption before choosing (the parity policy allows either conforming policy only if the corpus row is schedule-independent — and upstream has now made it the committed expectation, which was exactly the #43 exit condition's shape).

    Sequencing consequence: this track is one PR with two reviewed decisions (exclusion removal — mechanical; entry-policy revision — adjudication-grade), not a mechanical sweep. The xfail class holds until then.

  3. added
    spec-divergenceBehavior diverges from the pinned CM reference; fix or adjudicate as a named divergence
    policyDecision owed on deltic-owned semantics
    on Sep 5, 2026
  4. lannbot commented on Sep 5, 2026

    @lannbot
    CollaboratorAuthor

    Triage 2026-09-05: adding spec-divergence (it is a named xfail class against the pinned reference) and policy (finding 2 above is an adjudication revisit of #43's entry policy, a deltic-owned decision). p2 unchanged.

    Two updates to the scope re-derivation above:

    1. CM#716 has merged (2026-09-04; see adopt CM#705/#707 cancellation delivery: subtask.cancel rewrite + pending-cancel ASAP bookkeeping #250). The "implement the callback-loop candidate rows last, or after #716 settles" caveat therefore resolves as soon as adopt CM#705/#707 cancellation delivery: subtask.cancel rewrite + pending-cancel ASAP bookkeeping #250's pin advance to 8892da0 lands — sequence this track after that advance so the callback-turn shape is implemented once, against the merged wait_from_callback.
    2. The live class is one row. Only async/sync-streams.json:208 carries cm705-sync-sched in harness/src/xfail.ts today. The during-sync-scheduling-candidates / during-sync-call-exclusive-resume / during-sync-call-may-block-if-other-ready-threads rows this issue lists are classed under deferred threads (memory64 + shared-everything threads: deferred feature tracking #12) — they die at instantiation on 🧵 thread built-ins before reaching the scheduler — and Pin-blocked conformance residues (#13 exit): name-option + thread-encoding xfails need wasmparser >= 0.255 #152 (the "translate-blocked" note above) is closed since the wasm-tools 0.258 bump. So the corpus evidence for the candidate-set change (scope item 1) is masked by memory64 + shared-everything threads: deferred feature tracking #12 until those rows can instantiate; the exclusion removal in driveSyncLift should carry its own runtime unit pins rather than lean on the corpus.

    Net: the PR shape stands as described — exclusion removal (mechanical, unit-pinned) plus the entry-policy revision (adjudication-grade, owns the single live xfail).

  5. added
    p1Correctness bugs likely to impact consumers; high-priority missing features
    and removed
    p2Minor bugs; desirable lower-priority features
    on Sep 12, 2026
  6. lannbot commented on Sep 12, 2026

    @lannbot
    CollaboratorAuthor

    Triage: p2 → p1 for the remaining executable conformance failure, after the consumer-facing hangs/leaks/valid-operation failures. Scope correction: #307 already removed the exclusive-thread candidate exclusion and added drive_sync_lift_candidates_test.ts; do not redo scope item 1. Current main still carries the single cm705-sync-sched xfail in async/sync-streams.json: the guest assertion traps on initial/completion status codes. Remaining work is the backpressure/entry-policy decision and implementation needed to retire that row. The #43 adjudication must be revisited explicitly; promotion is not a ruling that its replacement policy is already decided.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    p1Correctness bugs likely to impact consumers; high-priority missing featurespolicyDecision owed on deltic-owned semanticsspec-divergenceBehavior diverges from the pinned CM reference; fix or adjudicate as a named divergence

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions