Chez concurrency pt.1: real OS-thread futures + blocking promises (shared heap)
future/future-call run the body on a native thread (fork-thread) over the SAME heap — JVM semantics, not Janet's isolated-heap snapshot. deref blocks on a mutex+condition latch; timed (deref f ms val) uses an absolute deadline. promise is a real blocking promise (deref parks until deliver), replacing the Janet non-blocking atom shim. future?/future-done?/future-cancelled?/future-cancel /realized? are native (the overlay versions read Janet map keys); re-asserted in post-prelude over the overlay. pmap/pcalls/pvalues (overlay, over future) light up for free. Thread-safety this forces: - atoms get a per-atom mutex; swap!/swap-vals! are a JVM-style CAS loop (f runs outside the lock, so a watch/validator can deref the same atom); reset!/ compare-and-set! are atomic. - the dynamic binding stack becomes a Chez thread-parameter, so each future/thread has its own; Chez inherits it at fork, giving binding conveyance (the shim also installs an explicit snapshot). - Thread/sleep really sleeps now (a worker sleeping doesn't block the parent). Re-minted the seed: future-call now resolves at compile time, so pmap compiles to a var-deref instead of the host-static-call fallback that crashed. image.ss unchanged. Corpus: the 2 snapshot cases now match the JVM (shared) not Janet (isolated) — allowlisted on both Chez gates; the two racy future-cancel cases allowlisted; "promise undelivered" (blocks on JVM/Chez, profile :bucket :timeout) skipped like :throws. Zero-Janet corpus 2544 -> 2569, 0 new divergences, floor raised. Full Janet gate + JVM cert green. jolt-byjr
This commit is contained in:
parent
a23095b502
commit
ec30c9e405
10 changed files with 330 additions and 42 deletions
|
|
@ -78,7 +78,24 @@
|
|||
"inf inside coll" true
|
||||
# #?@ reader-conditional splicing into the enclosing seq isn't supported yet
|
||||
# (plain #? works); a single niche corpus case.
|
||||
"reader cond splice" true})
|
||||
"reader cond splice" true
|
||||
# concurrency (jolt-byjr): Chez futures are real OS threads sharing the heap =
|
||||
# JVM semantics, NOT Janet's isolated-heap snapshot. So a captured atom IS
|
||||
# shared (the corpus :expected is the Janet snapshot value). Deliberate per the
|
||||
# jvm-parity-north-star — Chez matches the JVM, Janet keeps the old snapshot.
|
||||
"captured atom is snapshotted, not shared" true # Chez 1 (shared) vs Janet 0
|
||||
"snapshot semantics" true # pmap: Chez 2 (shared) vs Janet 0
|
||||
# future-cancel on a trivial body is timing-dependent under real threads: the
|
||||
# future usually completes before the cancel (cancel -> false), like the JVM.
|
||||
# The Janet :expected "true" relies on cooperative scheduling. Flaky/divergent.
|
||||
"cancel an in-flight future returns true" true
|
||||
"future-cancelled? after cancel" true})
|
||||
|
||||
# Cases that BLOCK forever on a shared-heap / JVM host (profile.edn :bucket
|
||||
# :timeout) — skip them, like :throws: a single hung case would stall the whole
|
||||
# batched process. (deref of an undelivered promise blocks on the JVM and now on
|
||||
# Chez; Janet's non-blocking atom-shim returned nil.)
|
||||
(def skip-blocking @{"promise undelivered" true})
|
||||
|
||||
(var pass 0)
|
||||
(def crashes @[]) # nonzero chez exit (analyzer/emitter raised, or runtime gap)
|
||||
|
|
@ -116,8 +133,8 @@
|
|||
(def rows-by-idx @{})
|
||||
(def pairs @[])
|
||||
(eachp [i row] cases
|
||||
(def {:expected e :actual a} row)
|
||||
(if (= e :throws)
|
||||
(def {:expected e :actual a :label l} row)
|
||||
(if (or (= e :throws) (get skip-blocking l))
|
||||
(++ throws)
|
||||
(let [key (string i)]
|
||||
(put rows-by-idx key row)
|
||||
|
|
@ -166,7 +183,7 @@
|
|||
|
||||
# Regression floor: raise as the Chez-hosted compiler closes gaps. The gate fails
|
||||
# on any NEW divergence or if pass drops below the floor. Strided runs scale to 0.
|
||||
(def base-floor (scan-number (or (os/getenv "JOLT_CHEZ_ZJ_FLOOR") "2544")))
|
||||
(def base-floor (scan-number (or (os/getenv "JOLT_CHEZ_ZJ_FLOOR") "2569")))
|
||||
(def floor (if (os/getenv "JOLT_CORPUS_LIMIT") 0 base-floor))
|
||||
(when (or (> (length diverged) 0) (< pass floor))
|
||||
(printf "REGRESSION: pass %d < floor %d or %d new divergence(s)" pass floor (length diverged)))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue