Source code

Revision control

Copy as Markdown

Other Tools

// |jit-test| --enable-atomics-pause; skip-if: !Atomics.pause || helperThreadCount() === 0 || getBuildConfiguration("arm64-simulator") === true
function startWorker(worker) {
evalInWorker(`
(${worker})(getSharedObject());
`);
}
// Index 0: Worker Lock
// Index 1: Counter
// Index 2: Sync
// Index 3: Worker State
let sab = new SharedArrayBuffer(4 * Int32Array.BYTES_PER_ELEMENT)
let i32 = new Int32Array(sab);
setSharedObject(sab);
// Number of workers.
const N = 4;
// Number of iterations.
const K = N * 1000;
for (let i = 0; i < N; ++i) {
startWorker(function(sab) {
// Number of workers.
const N = 4;
// Number of iterations.
const K = N * 1000;
let i32 = new Int32Array(sab);
// Mark worker as started.
Atomics.add(i32, 3, 1);
// Wait until main thread is ready.
Atomics.wait(i32, 2, 0);
for (let i = 0; i < K / N; ++i) {
// Spin-wait loop using a "test, test-and-set" technique.
while (true) {
while (Atomics.load(i32, 0) !== 0) {
Atomics.pause();
}
if (Atomics.exchange(i32, 0, 1) === 0) {
break;
}
}
// "Critical section" - non-atomic load-and-store.
i32[1] += 1;
// Leave "Critical section".
Atomics.store(i32, 0, 0);
}
// Mark worker as finished.
Atomics.sub(i32, 3, 1);
});
}
// Wait until all worker threads have started.
while (Atomics.load(i32, 3) !== N) {
Atomics.pause();
}
// Start work in all worker threads.
let woken = 0;
while ((woken += Atomics.notify(i32, 2, N)) !== N) {
}
// Wait until all worker threads have finished.
while (Atomics.load(i32, 3) !== 0) {
Atomics.pause();
}
assertEq(i32[1], K);