summaryrefslogtreecommitdiffstats
path: root/js/src/tests/shell/futex.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/shell/futex.js')
-rw-r--r--js/src/tests/shell/futex.js160
1 files changed, 160 insertions, 0 deletions
diff --git a/js/src/tests/shell/futex.js b/js/src/tests/shell/futex.js
new file mode 100644
index 000000000..b0951f12e
--- /dev/null
+++ b/js/src/tests/shell/futex.js
@@ -0,0 +1,160 @@
+// |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 wait/wake 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
+
+if (helperThreadCount() === 0) {
+ // Abort if there is no helper thread.
+ reportCompare(true,true);
+ quit();
+}
+
+////////////////////////////////////////////////////////////
+
+// wait() returns "not-equal" if the value is not the expected one.
+
+mem[0] = 42;
+
+assertEq(Atomics.wait(mem, 0, 33), "not-equal");
+
+// wait() returns "timed-out" if it times out
+
+assertEq(Atomics.wait(mem, 0, 42, 100), "timed-out");
+
+////////////////////////////////////////////////////////////
+
+// 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);
+
+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 2 seconds");
+sleep(2);
+dprint("Waking the main thread now");
+setSharedArrayBuffer(null);
+assertEq(Atomics.wake(mem, 0, 1), 1); // Can fail spuriously but very unlikely
+`);
+
+var then = Date.now();
+assertEq(Atomics.wait(mem, 0, 42), "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
+
+////////////////////////////////////////////////////////////
+
+// Test the default argument to atomics.wake()
+
+setSharedArrayBuffer(mem.buffer);
+
+evalInWorker(`
+var mem = new Int32Array(getSharedArrayBuffer());
+sleep(2); // Probably long enough to avoid a spurious error next
+assertEq(Atomics.wake(mem, 0), 1); // Last argument to wake should default to +Infinity
+`);
+
+var then = Date.now();
+dprint("Main thread waiting on wakeup (2s)");
+assertEq(Atomics.wait(mem, 0, 42), "ok");
+dprint("Woke up as I should have in " + (Date.now() - then)/1000 + "s");
+
+////////////////////////////////////////////////////////////
+
+// A tricky case: while in the wait there will be an interrupt, and in
+// the interrupt handler we will execute a wait. This is
+// explicitly prohibited (for now), so there should be a catchable exception.
+
+var exn = false;
+timeout(2, function () {
+ dprint("In the interrupt, starting inner wait with timeout 2s");
+ try {
+ Atomics.wait(mem, 0, 42); // Should throw
+ } catch (e) {
+ dprint("Got the interrupt exception!");
+ exn = true;
+ }
+ return true;
+});
+try {
+ dprint("Starting outer wait");
+ assertEq(Atomics.wait(mem, 0, 42, 5000), "timed-out");
+}
+finally {
+ timeout(-1);
+}
+assertEq(exn, true);
+
+////////////////////////////////////////////////////////////
+
+dprint("Done");
+reportCompare(true,true);