mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-29 07:04:09 +08:00
Atomics operations on 8-, 16- and 32-bit integer arrays are sequentially consistent atomic instructions on the element, and no longer take the process-wide shared-memory lock. Other reads and writes of shared storage are relaxed atomic accesses: element reads and writes access the element, and copies, fills, conversions, searches and sorts read shared bytes into a private copy and write back only the range they change, so concurrent accesses to the same bytes are free of data races. Non-shared storage keeps its plain memory accesses. Atomics.wait and Atomics.notify queue waiters in buckets chosen by location, each with its own lock and condition variable, so waiting threads no longer serialize other Atomics. Atomics.store answers +0 for a value that truncates to -0, as Node does. The shared storage runtime test also runs under ThreadSanitizer.
51 lines
1.8 KiB
TypeScript
51 lines
1.8 KiB
TypeScript
import { execFile } from "node:child_process";
|
|
import { mkdtemp, rm } from "node:fs/promises";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { promisify } from "node:util";
|
|
import { expect, test } from "vitest";
|
|
import { EXECUTABLE_RUNTIME_SOURCES } from "../../compiler/src/backend/native-toolchain.js";
|
|
|
|
const exec = promisify(execFile);
|
|
|
|
// Atomics operations take no lock, and every other access to shared bytes
|
|
// is a relaxed atomic one; the ThreadSanitizer build checks that concurrent
|
|
// element, bulk and Atomics accesses to the same bytes are race-free.
|
|
test
|
|
.skipIf(process.platform === "win32")
|
|
.each([["-fsanitize=address,undefined"], ["-fsanitize=thread"]])(
|
|
"shared views keep concurrent accesses atomic and cancel parked waiters (%s)",
|
|
async (sanitize) => {
|
|
const dir = await mkdtemp(join(tmpdir(), "scriptc-shared-"));
|
|
try {
|
|
const bin = join(dir, "shared");
|
|
await exec("clang", [
|
|
"-std=c11",
|
|
"-O1",
|
|
"-pthread",
|
|
"-DSCR_WORKERS",
|
|
"-DSCR_RC_AUDIT",
|
|
sanitize,
|
|
"-Wno-deprecated-declarations",
|
|
...(process.platform === "linux" ? ["-D_GNU_SOURCE"] : []),
|
|
...["scr_shared.test.c", ...EXECUTABLE_RUNTIME_SOURCES].map((name) =>
|
|
join(import.meta.dirname, name),
|
|
),
|
|
...(process.platform === "linux" ? ["-lm"] : []),
|
|
"-o",
|
|
bin,
|
|
]);
|
|
const result = await exec(bin, [], {
|
|
timeout: 30000,
|
|
env: { ...process.env, UBSAN_OPTIONS: "halt_on_error=1", TSAN_OPTIONS: "halt_on_error=1" },
|
|
});
|
|
expect(result.stdout).toBe(
|
|
"shared views preserve atomic updates, wait queues and cancellation ownership\n",
|
|
);
|
|
expect(result.stderr).toBe("");
|
|
} finally {
|
|
await rm(dir, { recursive: true, force: true });
|
|
}
|
|
},
|
|
);
|