blob: bd3f1b0c4fd74ee35c4c18755c356c98640b5809 [file] [log] [blame]
// |reftest| skip-if(!xulRuntime.shell)
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
if (!(this.SharedArrayBuffer && this.getSharedArrayBuffer && this.setSharedArrayBuffer)) {
reportCompare(true,true);
quit(0);
}
var DEBUG = false;
function dprint(s) {
if (DEBUG) print(s);
}
// Tests the SharedArrayBuffer mailbox in the shell.
// Tests the futex functionality in the shell.
var sab = new SharedArrayBuffer(12);
var mem = new Int32Array(sab);
// SharedArrayBuffer mailbox tests
assertEq(getSharedArrayBuffer(), null); // Mbx starts empty
assertEq(setSharedArrayBuffer(mem.buffer), undefined); // Setter returns undefined
assertEq(getSharedArrayBuffer() == null, false); // And then the mbx is not empty
var v = getSharedArrayBuffer();
assertEq(v.byteLength, mem.buffer.byteLength); // Looks like what we put in?
var w = new Int32Array(v);
mem[0] = 314159;
assertEq(w[0], 314159); // Shares memory (locally) with what we put in?
mem[0] = 0;
setSharedArrayBuffer(null); // Setting to null clears to null
assertEq(getSharedArrayBuffer(), null);
setSharedArrayBuffer(mem.buffer);
setSharedArrayBuffer(undefined); // Setting to undefined clears to null
assertEq(getSharedArrayBuffer(), null);
setSharedArrayBuffer(mem.buffer);
setSharedArrayBuffer(); // Setting without arguments clears to null
assertEq(getSharedArrayBuffer(), null);
// Only SharedArrayBuffer can be stored in the mbx
assertThrowsInstanceOf(() => setSharedArrayBuffer({x:10, y:20}), Error);
assertThrowsInstanceOf(() => setSharedArrayBuffer([1,2]), Error);
assertThrowsInstanceOf(() => setSharedArrayBuffer(new ArrayBuffer(10)), Error);
assertThrowsInstanceOf(() => setSharedArrayBuffer(new Int32Array(10)), Error);
assertThrowsInstanceOf(() => setSharedArrayBuffer(false), Error);
assertThrowsInstanceOf(() => setSharedArrayBuffer(3.14), Error);
assertThrowsInstanceOf(() => setSharedArrayBuffer(mem), Error);
assertThrowsInstanceOf(() => setSharedArrayBuffer("abracadabra"), Error);
assertThrowsInstanceOf(() => setSharedArrayBuffer(() => 37), Error);
// Futex test
// Main is sharing the buffer with the worker; the worker is clearing
// the buffer.
mem[0] = 42;
mem[1] = 37;
mem[2] = DEBUG;
setSharedArrayBuffer(mem.buffer);
if (helperThreadCount() === 0) {
// Abort if there is no helper thread.
reportCompare(true,true);
quit();
}
evalInWorker(`
var mem = new Int32Array(getSharedArrayBuffer());
function dprint(s) {
if (mem[2]) print(s);
}
assertEq(mem[0], 42); // what was written in the main thread
assertEq(mem[1], 37); // is read in the worker
mem[1] = 1337;
dprint("Sleeping for 3 seconds");
sleep(3);
dprint("Waking the main thread now");
setSharedArrayBuffer(null);
Atomics.futexWake(mem, 0, 1);
`);
var then = Date.now();
assertEq(Atomics.futexWait(mem, 0, 42), Atomics.OK);
dprint("Woke up as I should have in " + (Date.now() - then)/1000 + "s");
assertEq(mem[1], 1337); // what was written in the worker is read in the main thread
assertEq(getSharedArrayBuffer(), null); // The worker's clearing of the mbx is visible
// A tricky case: while in the wait there will be an interrupt, and in
// the interrupt handler we will execute a futexWait. This is
// explicitly prohibited (for now), so there should be a catchable exception.
timeout(2, function () {
dprint("In the interrupt, starting inner wait");
Atomics.futexWait(mem, 0, 42); // Should throw and propagate all the way out
});
var exn = false;
try {
dprint("Starting outer wait");
assertEq(Atomics.futexWait(mem, 0, 42, 5000), Atomics.OK);
}
catch (e) {
dprint("Got the exception!");
exn = true;
}
finally {
timeout(-1);
}
assertEq(exn, true);
dprint("Done");
reportCompare(true,true);