1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
//! `wasm32-wasip1-threads` only: whether a wasm thread of this instance has died. Not a public
//! API; the generated worker raises it, and napi-async-runtime's shutdown waits read it.
//!
//! A pool thread that traps unwinds nothing: the locks it held stay held, and the counts it
//! would have lowered stay up. The JavaScript thread runs the environment cleanup, and a wait
//! there on such a lock or count parks it in `memory.atomic.wait32` for good, before the loader
//! can see the crash. So when a worker's wasm thread dies, the generated worker (`wasi-worker.mjs`)
//! raises this flag right after the loader's own crash flag, and the cleanup waits on the
//! JavaScript thread check it between short slices and trap once it is up. The loader then
//! reports the crash instead of hanging.
//!
//! The flag is one 4-byte word in linear memory, which is shared with every worker. napi's
//! `napi_wasm_thread_crash_flag_address` export hands its address to the loader, which gives
//! each worker an `Int32Array` over it; the worker raises the flag with `Atomics.store`. That
//! needs no instance, so a worker whose load failed after its thread spawn had already been
//! reported as started raises it too. napi's `napi_wasm_thread_crashed` export stores into the
//! same word, for a worker that has an instance but no view.
//!
//! It lives in napi-sys for the same reason as [`crate::wasi_heap_sync`]: napi-async-runtime
//! reads it and cannot depend on napi. It defines no `#[no_mangle]` item and imports nothing.
use ;
/// 0 while every thread is alive, 1 once one died. An `AtomicI32` so the word is 4-aligned and
/// JavaScript's `Atomics` can store into it through an `Int32Array`.
static THREAD_CRASHED: AtomicI32 = new;
/// The flag word itself, whose address napi exports to the loader. Anything written there
/// other than 0 counts as a crash.
/// Record that a wasm thread of this instance has died. It stays set: nothing in the instance
/// can be trusted afterwards.
///
/// `SeqCst`, like the flag the worker raises for the loader just before: a thread that sees
/// this one set and traps then finds the loader's flag set too, so the loader reports the trap
/// as the crash. JavaScript's `Atomics.store` is sequentially consistent as well.
/// Whether a crash was recorded, by [`mark_thread_crashed`] or by a store to
/// [`thread_crash_flag`].