space-data-module-sdk 0.8.19 → 0.8.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +2 -2
- package/docs/assembly.js +190 -0
- package/docs/browser-wasmedge-isomorphic.html +6 -1
- package/docs/byo-wasm-quickstart.html +6 -1
- package/docs/conformance.html +6 -1
- package/docs/events-abi.html +6 -1
- package/docs/families/analytics.html +7 -2
- package/docs/families/attitude.html +7 -2
- package/docs/families/behavior.html +7 -2
- package/docs/families/breakup.html +7 -2
- package/docs/families/conjunction.html +7 -2
- package/docs/families/data-source.html +7 -2
- package/docs/families/effects.html +7 -2
- package/docs/families/environment.html +7 -2
- package/docs/families/estimation.html +7 -2
- package/docs/families/gnc.html +7 -2
- package/docs/families/maneuver.html +7 -2
- package/docs/families/obstruction.html +7 -2
- package/docs/families/propagator.html +7 -2
- package/docs/families/propulsion.html +7 -2
- package/docs/families/reentry.html +7 -2
- package/docs/families/rf.html +7 -2
- package/docs/families/scheduler.html +7 -2
- package/docs/families/sensor.html +7 -2
- package/docs/families/signature.html +7 -2
- package/docs/flatsql-host-contract.html +7 -2
- package/docs/flatsql-host-contract.md +2 -2
- package/docs/flatsql-streaming-standard.html +6 -1
- package/docs/gpu-module-abi.html +6 -1
- package/docs/index.html +21 -14
- package/docs/isomorphic-pthreads.html +19 -2
- package/docs/isomorphic-pthreads.md +59 -1
- package/docs/isomorphic-sdn-runtime-plan.html +6 -1
- package/docs/language-runtime-matrix.html +6 -1
- package/docs/llms.txt +1 -1
- package/docs/module-bundle-runtime-plan.html +6 -1
- package/docs/module-publication-standard.html +6 -1
- package/docs/node-red-default-node-parity.html +6 -1
- package/docs/protect-and-sign.html +6 -1
- package/docs/protocol-installation.html +6 -1
- package/docs/publication-submission.html +6 -1
- package/docs/secrets-capability.html +6 -1
- package/docs/styles.css +32 -0
- package/docs/testing-harness.html +6 -1
- package/docs/tri-runtime-parity-gate.html +6 -1
- package/docs/tri-runtime-parity.html +6 -1
- package/package.json +1 -1
- package/src/host/browserModuleHarness.js +39 -35
- package/src/host/isomorphicLoader.js +13 -6
- package/src/host/wasiShim.js +57 -13
- package/src/host/wasiThreadBrowserWorker.mjs +1 -0
- package/src/host/wasiThreadHost.js +16 -1
- package/src/host/wasiThreadWorker.mjs +2 -1
- package/src/host/wasiThreadWorkerRuntime.js +2 -1
- package/src/testing/browserModuleHarness.js +2 -0
- package/src/testing/buildWasmEdgeRunner.js +147 -4
- package/src/testing/docker/wasmedge-parity.Dockerfile +23 -1
- package/src/testing/isomorphicHarness.js +5 -0
- package/src/testing/native/wasmedge-0.16.4-atomic-wait.patch +111 -0
- package/src/testing/native/wasmedge_wasi_threads_runner.c +345 -0
- package/src/testing/parityBrowserRunner.js +12 -4
- package/src/testing/parityHarness.js +11 -3
- package/src/testing/parityLanes.js +29 -5
|
@@ -5,6 +5,8 @@ import path from "node:path";
|
|
|
5
5
|
import process from "node:process";
|
|
6
6
|
import { promisify } from "node:util";
|
|
7
7
|
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { createHash } from "node:crypto";
|
|
9
|
+
import { mkdir, readFile, writeFile, copyFile, rename, rm } from "node:fs/promises";
|
|
8
10
|
|
|
9
11
|
const execFileAsync = promisify(execFile);
|
|
10
12
|
const __filename = fileURLToPath(import.meta.url);
|
|
@@ -56,11 +58,13 @@ function resolveGeneratedIncludeDir(requestedIncludeDir) {
|
|
|
56
58
|
);
|
|
57
59
|
}
|
|
58
60
|
|
|
59
|
-
export function resolveWasmEdgeRunnerSourcePath() {
|
|
61
|
+
export function resolveWasmEdgeRunnerSourcePath(options = {}) {
|
|
60
62
|
return path.resolve(
|
|
61
63
|
__dirname,
|
|
62
64
|
"native",
|
|
63
|
-
|
|
65
|
+
options.runnerKind === "wasi-threads"
|
|
66
|
+
? "wasmedge_wasi_threads_runner.c"
|
|
67
|
+
: "wasmedge_emscripten_pthread_runner.c",
|
|
64
68
|
);
|
|
65
69
|
}
|
|
66
70
|
|
|
@@ -127,7 +131,7 @@ export function resolveWasmEdgeRunnerBuildPlan(options = {}) {
|
|
|
127
131
|
throw new Error("Missing runner outputPath.");
|
|
128
132
|
}
|
|
129
133
|
|
|
130
|
-
const runnerSourcePath = resolveWasmEdgeRunnerSourcePath();
|
|
134
|
+
const runnerSourcePath = resolveWasmEdgeRunnerSourcePath(options);
|
|
131
135
|
const wasmedgeSharedLibraryPath = path.join(
|
|
132
136
|
wasmedgeLibDir,
|
|
133
137
|
resolveWasmEdgeSharedLibraryFilename(),
|
|
@@ -146,6 +150,7 @@ export function resolveWasmEdgeRunnerBuildPlan(options = {}) {
|
|
|
146
150
|
process.platform === "darwin"
|
|
147
151
|
? [
|
|
148
152
|
"clang",
|
|
153
|
+
"-Wl,-headerpad_max_install_names",
|
|
149
154
|
runnerSourcePath,
|
|
150
155
|
"-std=c11",
|
|
151
156
|
"-O2",
|
|
@@ -191,6 +196,7 @@ export async function buildWasmEdgeEmscriptenPthreadRunner(options = {}) {
|
|
|
191
196
|
process.platform === "darwin"
|
|
192
197
|
? [
|
|
193
198
|
"clang",
|
|
199
|
+
"-Wl,-headerpad_max_install_names",
|
|
194
200
|
basePlan.runnerSourcePath,
|
|
195
201
|
"-std=c11",
|
|
196
202
|
"-O2",
|
|
@@ -242,12 +248,149 @@ export async function buildWasmEdgeEmscriptenPthreadRunner(options = {}) {
|
|
|
242
248
|
cwd: options.cwd ?? process.cwd(),
|
|
243
249
|
});
|
|
244
250
|
if (process.platform === "darwin") {
|
|
251
|
+
let linkedLibrary = plan.wasmedgeSharedLibraryPath;
|
|
252
|
+
if (options.runnerKind === "wasi-threads") {
|
|
253
|
+
// DYLD_LIBRARY_PATH can override even an absolute install name by its
|
|
254
|
+
// basename. Give this exact runtime a unique name so ambient SDK paths
|
|
255
|
+
// cannot silently replace the corrected atomic-wait implementation.
|
|
256
|
+
const sha = createHash("sha256").update(await readFile(linkedLibrary)).digest("hex");
|
|
257
|
+
linkedLibrary = path.join(path.dirname(plan.outputPath), `libsdm-wasmedge-${sha}.dylib`);
|
|
258
|
+
if (!existsSync(linkedLibrary)) {
|
|
259
|
+
const stagingLibrary = `${linkedLibrary}.${process.pid}`;
|
|
260
|
+
try {
|
|
261
|
+
await copyFile(plan.wasmedgeSharedLibraryPath, stagingLibrary);
|
|
262
|
+
await rename(stagingLibrary, linkedLibrary);
|
|
263
|
+
} finally { await rm(stagingLibrary, { force: true }); }
|
|
264
|
+
}
|
|
265
|
+
}
|
|
245
266
|
await execFileAsync("install_name_tool", [
|
|
246
267
|
"-change",
|
|
247
268
|
"@rpath/libwasmedge.0.dylib",
|
|
248
|
-
|
|
269
|
+
linkedLibrary,
|
|
249
270
|
plan.outputPath,
|
|
250
271
|
]);
|
|
251
272
|
}
|
|
252
273
|
return plan.outputPath;
|
|
253
274
|
}
|
|
275
|
+
|
|
276
|
+
const WASMEDGE_THREADS_REVISION = "be85c2fbba68318f103b4a766728f6946e65abf8";
|
|
277
|
+
const runtimeBuilds = new Map();
|
|
278
|
+
|
|
279
|
+
// Upstream 0.16.4 can lose atomic notifications between comparison and sleep.
|
|
280
|
+
// Keep its established SDN fix isolated from the owner's installed SDK/CLI.
|
|
281
|
+
// An explicit include/lib pair remains supported for operator-built runtimes.
|
|
282
|
+
async function prepareWasmEdgeThreadsRuntime(options) {
|
|
283
|
+
if ((options.wasmedgeIncludeDir ?? process.env.WASMEDGE_INCLUDE_DIR) &&
|
|
284
|
+
(options.wasmedgeLibDir ?? process.env.WASMEDGE_LIB_DIR)) return {};
|
|
285
|
+
const patchPath = path.join(__dirname, "native/wasmedge-0.16.4-atomic-wait.patch");
|
|
286
|
+
const digest = createHash("sha256").update(WASMEDGE_THREADS_REVISION)
|
|
287
|
+
.update(await readFile(patchPath)).update(`${process.platform}-${process.arch}`).digest("hex");
|
|
288
|
+
if (!runtimeBuilds.has(digest)) {
|
|
289
|
+
const build = (async () => {
|
|
290
|
+
const root = path.join(os.tmpdir(), "sdm-wasmedge-runtimes", digest);
|
|
291
|
+
const prefix = path.join(root, "sdk");
|
|
292
|
+
const marker = path.join(root, "complete.json");
|
|
293
|
+
const lock = `${root}.lock`;
|
|
294
|
+
await mkdir(path.dirname(root), { recursive: true, mode: 0o700 });
|
|
295
|
+
const started = Date.now();
|
|
296
|
+
let held = false;
|
|
297
|
+
while (!existsSync(marker)) {
|
|
298
|
+
try {
|
|
299
|
+
await mkdir(lock);
|
|
300
|
+
held = true;
|
|
301
|
+
await writeFile(path.join(lock, "pid"), String(process.pid));
|
|
302
|
+
break;
|
|
303
|
+
} catch (error) {
|
|
304
|
+
if (error.code !== "EEXIST") throw error;
|
|
305
|
+
try {
|
|
306
|
+
const owner = Number(await readFile(path.join(lock, "pid"), "utf8"));
|
|
307
|
+
if (owner > 0) {
|
|
308
|
+
try { process.kill(owner, 0); }
|
|
309
|
+
catch (error) { if (error.code === "ESRCH") await rm(lock, { recursive: true, force: true }); }
|
|
310
|
+
}
|
|
311
|
+
} catch { /* another builder is still acquiring its lock */ }
|
|
312
|
+
if (Date.now() - started > 900000) throw new Error("Timed out waiting for the isolated WasmEdge runtime build.");
|
|
313
|
+
await new Promise((resolve) => setTimeout(resolve, 250));
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
try {
|
|
317
|
+
if (!existsSync(marker)) {
|
|
318
|
+
await mkdir(root, { recursive: true });
|
|
319
|
+
const source = path.join(root, "source");
|
|
320
|
+
const buildDir = path.join(root, "build");
|
|
321
|
+
const run = (command, args) => execFileAsync(command, args, { timeout: 900000, maxBuffer: 16 * 1024 * 1024 });
|
|
322
|
+
if (!existsSync(path.join(source, ".git"))) {
|
|
323
|
+
await run("git", ["clone", "--depth", "1", "--branch", "0.16.4", "https://github.com/WasmEdge/WasmEdge.git", source]);
|
|
324
|
+
}
|
|
325
|
+
const revision = (await run("git", ["-C", source, "rev-parse", "HEAD"])).stdout.trim();
|
|
326
|
+
if (revision !== WASMEDGE_THREADS_REVISION) throw new Error(`Unexpected WasmEdge source revision: ${revision}`);
|
|
327
|
+
try { await run("git", ["-C", source, "apply", "--reverse", "--check", patchPath]); }
|
|
328
|
+
catch { await run("git", ["-C", source, "apply", patchPath]); }
|
|
329
|
+
await run("cmake", ["-S", source, "-B", buildDir, "-G", "Ninja",
|
|
330
|
+
"-DCMAKE_BUILD_TYPE=Release", `-DCMAKE_INSTALL_PREFIX=${prefix}`,
|
|
331
|
+
process.platform === "darwin" ? "-DCMAKE_CXX_FLAGS=-Wno-invalid-specialization" : "-DCMAKE_CXX_FLAGS=-Wno-error=maybe-uninitialized -Wno-error=array-bounds",
|
|
332
|
+
"-DWASMEDGE_USE_LLVM=OFF",
|
|
333
|
+
"-DWASMEDGE_BUILD_PLUGINS=OFF", "-DWASMEDGE_BUILD_TOOLS=OFF", "-DWASMEDGE_FORCE_DISABLE_LTO=ON"]);
|
|
334
|
+
await run("cmake", ["--build", buildDir, "-j", "4"]);
|
|
335
|
+
await run("cmake", ["--install", buildDir]);
|
|
336
|
+
await writeFile(marker, JSON.stringify({ revision, patchSha256: createHash("sha256").update(await readFile(patchPath)).digest("hex") }));
|
|
337
|
+
}
|
|
338
|
+
} finally {
|
|
339
|
+
if (held) await rm(lock, { recursive: true, force: true });
|
|
340
|
+
}
|
|
341
|
+
const libDir = existsSync(path.join(prefix, "lib", resolveWasmEdgeSharedLibraryFilename())) ? "lib" : "lib64";
|
|
342
|
+
return { wasmedgeIncludeDir: path.join(prefix, "include"), wasmedgeLibDir: path.join(prefix, libDir) };
|
|
343
|
+
})();
|
|
344
|
+
runtimeBuilds.set(digest, build);
|
|
345
|
+
build.catch(() => runtimeBuilds.delete(digest));
|
|
346
|
+
}
|
|
347
|
+
return runtimeBuilds.get(digest);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
export async function buildWasmEdgeWasiThreadsRunner(options = {}) {
|
|
351
|
+
const runtime = await prepareWasmEdgeThreadsRuntime(options);
|
|
352
|
+
return buildWasmEdgeEmscriptenPthreadRunner({ ...options, ...runtime, runnerKind: "wasi-threads" });
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
const builds = new Map();
|
|
356
|
+
|
|
357
|
+
// The command runner is separate from the legacy resident Emscripten host.
|
|
358
|
+
// Invalidate cached binaries when either the source or linked library changes.
|
|
359
|
+
export async function resolveWasmEdgeWasiThreadsRunner(options = {}) {
|
|
360
|
+
const explicit = options.wasmEdgeRunnerBinary ?? options.wasmedgeRunnerBinary ??
|
|
361
|
+
process.env.SDM_WASMEDGE_RUNNER_BINARY;
|
|
362
|
+
if (explicit) return path.resolve(String(explicit));
|
|
363
|
+
options = { ...options, ...await prepareWasmEdgeThreadsRuntime(options) };
|
|
364
|
+
const plan = resolveWasmEdgeRunnerBuildPlan({
|
|
365
|
+
...options, runnerKind: "wasi-threads", outputPath: path.join(os.tmpdir(), "sdm-runner"),
|
|
366
|
+
});
|
|
367
|
+
const digest = createHash("sha256")
|
|
368
|
+
.update(await readFile(__filename))
|
|
369
|
+
.update(await readFile(plan.runnerSourcePath))
|
|
370
|
+
.update(await readFile(plan.wasmedgeSharedLibraryPath))
|
|
371
|
+
.update(JSON.stringify([process.platform, process.arch, plan.wasmedgeIncludeDir,
|
|
372
|
+
plan.wasmedgeSharedLibraryPath, plan.compilerCommand, plan.compilerArgs]))
|
|
373
|
+
.digest("hex");
|
|
374
|
+
if (!builds.has(digest)) {
|
|
375
|
+
const build = (async () => {
|
|
376
|
+
const dir = path.join(os.tmpdir(), "sdm-wasmedge-runners");
|
|
377
|
+
await mkdir(dir, { recursive: true, mode: 0o700 });
|
|
378
|
+
const outputPath = path.join(dir, `wasi-threads-${digest}`);
|
|
379
|
+
if (!existsSync(outputPath)) {
|
|
380
|
+
const staging = `${outputPath}.${process.pid}`;
|
|
381
|
+
try {
|
|
382
|
+
await buildWasmEdgeWasiThreadsRunner({ ...options, outputPath: staging });
|
|
383
|
+
await rename(staging, outputPath);
|
|
384
|
+
} finally {
|
|
385
|
+
await rm(staging, { force: true });
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
// This executes the linked library's version check, including on cache hits.
|
|
389
|
+
await execFileAsync(outputPath, ["--version"]);
|
|
390
|
+
return outputPath;
|
|
391
|
+
})();
|
|
392
|
+
builds.set(digest, build);
|
|
393
|
+
build.catch(() => builds.delete(digest));
|
|
394
|
+
}
|
|
395
|
+
return builds.get(digest);
|
|
396
|
+
}
|
|
@@ -11,7 +11,7 @@ ARG WASMEDGE_VERSION
|
|
|
11
11
|
RUN test -n "${WASMEDGE_VERSION}" || (echo "WASMEDGE_VERSION build-arg is required (injected from src/testing/wasmedgePin.json)" && exit 1)
|
|
12
12
|
|
|
13
13
|
RUN apt-get update \
|
|
14
|
-
&& apt-get install -y --no-install-recommends curl ca-certificates \
|
|
14
|
+
&& apt-get install -y --no-install-recommends curl ca-certificates build-essential git cmake ninja-build \
|
|
15
15
|
&& rm -rf /var/lib/apt/lists/*
|
|
16
16
|
|
|
17
17
|
RUN set -eux; \
|
|
@@ -34,6 +34,28 @@ RUN set -eux; \
|
|
|
34
34
|
ENV PATH="/opt/wasmedge/bin:${PATH}" \
|
|
35
35
|
LD_LIBRARY_PATH="/opt/wasmedge/lib64:/opt/wasmedge/lib"
|
|
36
36
|
|
|
37
|
+
COPY native/wasmedge_wasi_threads_runner.c /tmp/sdm-wasi-threads-runner.c
|
|
38
|
+
COPY native/wasmedge-0.16.4-atomic-wait.patch /tmp/atomic-wait.patch
|
|
39
|
+
# The ordinary CLI keeps its release library. Only the SDK thread runner uses
|
|
40
|
+
# the isolated 0.16.4 atomic-wait correction, matching the native build.
|
|
41
|
+
RUN git clone --depth 1 --branch 0.16.4 https://github.com/WasmEdge/WasmEdge.git /tmp/wasmedge-source \
|
|
42
|
+
&& test "$(git -C /tmp/wasmedge-source rev-parse HEAD)" = be85c2fbba68318f103b4a766728f6946e65abf8 \
|
|
43
|
+
&& git -C /tmp/wasmedge-source apply /tmp/atomic-wait.patch \
|
|
44
|
+
&& cmake -S /tmp/wasmedge-source -B /tmp/wasmedge-build -G Ninja \
|
|
45
|
+
-DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/sdm-wasmedge \
|
|
46
|
+
"-DCMAKE_CXX_FLAGS=-Wno-error=maybe-uninitialized -Wno-error=array-bounds" \
|
|
47
|
+
-DWASMEDGE_USE_LLVM=OFF -DWASMEDGE_BUILD_PLUGINS=OFF \
|
|
48
|
+
-DWASMEDGE_BUILD_TOOLS=OFF -DWASMEDGE_FORCE_DISABLE_LTO=ON \
|
|
49
|
+
&& cmake --build /tmp/wasmedge-build -j 4 \
|
|
50
|
+
&& cmake --install /tmp/wasmedge-build \
|
|
51
|
+
&& rm -rf /tmp/wasmedge-source /tmp/wasmedge-build /tmp/atomic-wait.patch
|
|
52
|
+
RUN cc /tmp/sdm-wasi-threads-runner.c -std=c11 -O2 -pthread -Wall -Wextra -Werror \
|
|
53
|
+
-I/opt/sdm-wasmedge/include -L/opt/sdm-wasmedge/lib64 -L/opt/sdm-wasmedge/lib -lwasmedge \
|
|
54
|
+
-Wl,--disable-new-dtags,-rpath,/opt/sdm-wasmedge/lib64,-rpath,/opt/sdm-wasmedge/lib \
|
|
55
|
+
-o /opt/wasmedge/bin/sdm-wasi-threads-runner \
|
|
56
|
+
&& /opt/wasmedge/bin/sdm-wasi-threads-runner --version \
|
|
57
|
+
&& rm /tmp/sdm-wasi-threads-runner.c
|
|
58
|
+
|
|
37
59
|
# The parity harness always runs this image with an explicit wasmedge argv
|
|
38
60
|
# (flags + guest module + guest args) so the container is a pure runtime shell.
|
|
39
61
|
ENTRYPOINT ["wasmedge"]
|
|
@@ -58,6 +58,10 @@ export async function createStandaloneHarness(runtimeKind, wasmPath, options = {
|
|
|
58
58
|
allowRawInvoke: options.allowRawInvoke,
|
|
59
59
|
initialMemoryBytes: options.initialMemoryBytes,
|
|
60
60
|
maximumMemoryBytes: options.maximumMemoryBytes,
|
|
61
|
+
maxThreads: options.maxThreads,
|
|
62
|
+
enableBrowserWasiThreads: options.enableBrowserWasiThreads,
|
|
63
|
+
wasiThreadWorkerUrl: options.wasiThreadWorkerUrl,
|
|
64
|
+
wasiThreadWorkerBaseUrl: options.wasiThreadWorkerBaseUrl,
|
|
61
65
|
});
|
|
62
66
|
}
|
|
63
67
|
|
|
@@ -65,6 +69,7 @@ export async function createStandaloneHarness(runtimeKind, wasmPath, options = {
|
|
|
65
69
|
return loadModule({
|
|
66
70
|
wasmSource: resolvedWasmPath,
|
|
67
71
|
runtimeKind: "wasmedge",
|
|
72
|
+
surface: options.surface ?? "command",
|
|
68
73
|
enableThreads: options.enableThreads ?? false,
|
|
69
74
|
wasmEdgeBinary: options.wasmEdgeBinary,
|
|
70
75
|
wasmEdgeRunnerBinary: options.wasmEdgeRunnerBinary,
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
diff --git a/include/executor/engine/atomic.ipp b/include/executor/engine/atomic.ipp
|
|
2
|
+
index 8568e24..8414705 100644
|
|
3
|
+
--- a/include/executor/engine/atomic.ipp
|
|
4
|
+
+++ b/include/executor/engine/atomic.ipp
|
|
5
|
+
@@ -478,40 +478,32 @@ Executor::atomicWait(Runtime::Instance::MemoryInstance &MemInst,
|
|
6
|
+
auto *AtomicObj = MemInst.getPointer<std::atomic<T> *>(Address);
|
|
7
|
+
assuming(AtomicObj);
|
|
8
|
+
|
|
9
|
+
+ // Compare, register, and sleep under the notifier's mutex. Otherwise a
|
|
10
|
+
+ // store+notify between the comparison and wait can be lost forever.
|
|
11
|
+
+ std::unique_lock<decltype(WaiterMapMutex)> Locker(WaiterMapMutex);
|
|
12
|
+
if (AtomicObj->load() != Expected.le()) {
|
|
13
|
+
return UINT32_C(1); // NotEqual
|
|
14
|
+
}
|
|
15
|
+
-
|
|
16
|
+
- decltype(WaiterMap)::iterator WaiterIterator;
|
|
17
|
+
- {
|
|
18
|
+
- std::unique_lock<decltype(WaiterMapMutex)> Locker(WaiterMapMutex);
|
|
19
|
+
- WaiterIterator = WaiterMap.emplace(Address, &MemInst);
|
|
20
|
+
- }
|
|
21
|
+
-
|
|
22
|
+
+ auto WaiterIterator = WaiterMap.emplace(Address, &MemInst);
|
|
23
|
+
cxx20::scope_exit ScopeExitHolder([&]() noexcept {
|
|
24
|
+
- std::unique_lock<decltype(WaiterMapMutex)> Locker(WaiterMapMutex);
|
|
25
|
+
WaiterMap.erase(WaiterIterator);
|
|
26
|
+
});
|
|
27
|
+
-
|
|
28
|
+
- while (true) {
|
|
29
|
+
- std::unique_lock<decltype(WaiterIterator->second.Mutex)> Locker(
|
|
30
|
+
- WaiterIterator->second.Mutex);
|
|
31
|
+
- std::cv_status WaitResult = std::cv_status::no_timeout;
|
|
32
|
+
- if (!Until) {
|
|
33
|
+
- WaiterIterator->second.Cond.wait(Locker);
|
|
34
|
+
- } else {
|
|
35
|
+
- WaitResult = WaiterIterator->second.Cond.wait_until(Locker, *Until);
|
|
36
|
+
- }
|
|
37
|
+
- if (unlikely(StopToken.load(std::memory_order_relaxed) != 0)) {
|
|
38
|
+
- return Unexpect(ErrCode::Value::Interrupted);
|
|
39
|
+
- }
|
|
40
|
+
- if (likely(AtomicObj->load() != Expected.le())) {
|
|
41
|
+
- return UINT32_C(0); // ok
|
|
42
|
+
- }
|
|
43
|
+
- if (WaitResult == std::cv_status::timeout) {
|
|
44
|
+
- return UINT32_C(2); // Timed-out
|
|
45
|
+
- }
|
|
46
|
+
+ auto Ready = [&]() {
|
|
47
|
+
+ return WaiterIterator->second.Notified ||
|
|
48
|
+
+ StopToken.load(std::memory_order_relaxed) != 0;
|
|
49
|
+
+ };
|
|
50
|
+
+ bool Woken = true;
|
|
51
|
+
+ if (!Until) {
|
|
52
|
+
+ WaiterIterator->second.Cond.wait(Locker, Ready);
|
|
53
|
+
+ } else {
|
|
54
|
+
+ Woken = WaiterIterator->second.Cond.wait_until(Locker, *Until, Ready);
|
|
55
|
+
+ }
|
|
56
|
+
+ if (unlikely(StopToken.load(std::memory_order_relaxed) != 0)) {
|
|
57
|
+
+ return Unexpect(ErrCode::Value::Interrupted);
|
|
58
|
+
}
|
|
59
|
+
+ // A notification succeeds even when the memory value has not changed.
|
|
60
|
+
+ return Woken ? UINT32_C(0) : UINT32_C(2);
|
|
61
|
+
+
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
} // namespace Executor
|
|
65
|
+
diff --git a/include/executor/executor.h b/include/executor/executor.h
|
|
66
|
+
index fbcc6ac..6683ee9 100644
|
|
67
|
+
--- a/include/executor/executor.h
|
|
68
|
+
+++ b/include/executor/executor.h
|
|
69
|
+
@@ -28,6 +28,7 @@
|
|
70
|
+
#include "runtime/stackmgr.h"
|
|
71
|
+
#include "runtime/storemgr.h"
|
|
72
|
+
|
|
73
|
+
+#include <map>
|
|
74
|
+
#include <atomic>
|
|
75
|
+
#include <condition_variable>
|
|
76
|
+
#include <csignal>
|
|
77
|
+
@@ -1103,7 +1104,7 @@ private:
|
|
78
|
+
|
|
79
|
+
/// Waiter struct for atomic instructions
|
|
80
|
+
struct Waiter {
|
|
81
|
+
- std::mutex Mutex;
|
|
82
|
+
+ bool Notified = false;
|
|
83
|
+
std::condition_variable Cond;
|
|
84
|
+
Runtime::Instance::MemoryInstance *MemInst;
|
|
85
|
+
Waiter(Runtime::Instance::MemoryInstance *Inst) noexcept : MemInst(Inst) {}
|
|
86
|
+
@@ -1111,7 +1112,7 @@ private:
|
|
87
|
+
/// Waiter map mutex
|
|
88
|
+
std::mutex WaiterMapMutex;
|
|
89
|
+
/// Waiter multimap
|
|
90
|
+
- std::unordered_multimap<uint32_t, Waiter> WaiterMap;
|
|
91
|
+
+ std::multimap<uint32_t, Waiter> WaiterMap;
|
|
92
|
+
|
|
93
|
+
/// WasmEdge configuration
|
|
94
|
+
const Configure Conf;
|
|
95
|
+
diff --git a/lib/executor/engine/threadInstr.cpp b/lib/executor/engine/threadInstr.cpp
|
|
96
|
+
index 0d1ca70..5331e95 100644
|
|
97
|
+
--- a/lib/executor/engine/threadInstr.cpp
|
|
98
|
+
+++ b/lib/executor/engine/threadInstr.cpp
|
|
99
|
+
@@ -67,8 +67,10 @@ Executor::atomicNotify(Runtime::Instance::MemoryInstance &MemInst,
|
|
100
|
+
auto Range = WaiterMap.equal_range(Address);
|
|
101
|
+
for (auto Iterator = Range.first; Total < Count && Iterator != Range.second;
|
|
102
|
+
++Iterator) {
|
|
103
|
+
- if (likely(&MemInst == Iterator->second.MemInst)) {
|
|
104
|
+
- Iterator->second.Cond.notify_all();
|
|
105
|
+
+ if (likely(&MemInst == Iterator->second.MemInst) &&
|
|
106
|
+
+ !Iterator->second.Notified) {
|
|
107
|
+
+ Iterator->second.Notified = true;
|
|
108
|
+
+ Iterator->second.Cond.notify_one();
|
|
109
|
+
++Total;
|
|
110
|
+
}
|
|
111
|
+
}
|