summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/atomics/mutual-exclusion.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/atomics/mutual-exclusion.js')
-rw-r--r--js/src/jit-test/tests/atomics/mutual-exclusion.js91
1 files changed, 91 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/atomics/mutual-exclusion.js b/js/src/jit-test/tests/atomics/mutual-exclusion.js
new file mode 100644
index 000000000..146901d9d
--- /dev/null
+++ b/js/src/jit-test/tests/atomics/mutual-exclusion.js
@@ -0,0 +1,91 @@
+// Let a few threads hammer on memory with atomics to provoke errors
+// in exclusion work. This test is not 100% fail-safe: the test may
+// pass despite a bug, but this is unlikely.
+
+if (!(this.SharedArrayBuffer && this.getSharedArrayBuffer && this.setSharedArrayBuffer && this.evalInWorker))
+ quit(0);
+
+try {
+ // This will fail with --no-threads.
+ evalInWorker("37");
+}
+catch (e) {
+ quit(0);
+}
+
+// Map an Int32Array on shared memory. The first location is used as
+// a counter, each worker counts up on exit and the main thread will
+// wait until the counter reaches the number of workers. The other
+// elements are contended accumulators where we count up and down very
+// rapidly and for a long time, any failure in mutual exclusion should
+// lead to errors in the result. (For example, the test fails almost
+// immediately when I disable simulation of mutual exclusion in the
+// ARM simulator.)
+
+const numWorkers = 4; // You're not meant to change this
+const iterCount = 255; // Nor this
+const sabLength = 1024; // Nor this
+
+const oddResult = (function () {
+ var v = 0;
+ for ( var j=0 ; j < numWorkers ; j++ )
+ v |= (iterCount << (8 * j));
+ return v;
+})();
+
+const evenResult = 0;
+
+const sab = new SharedArrayBuffer(sabLength);
+
+setSharedArrayBuffer(sab);
+
+const iab = new Int32Array(sab);
+
+function testRun(limit) {
+ console.log("Limit = " + limit);
+
+ // Fork off workers to hammer on memory.
+ for ( var i=0 ; i < numWorkers ; i++ ) {
+ evalInWorker(`
+ const iab = new Int32Array(getSharedArrayBuffer());
+ const v = 1 << (8 * ${i});
+ for ( var i=0 ; i < ${limit} ; i++ ) {
+ for ( var k=0 ; k < ${iterCount} ; k++ ) {
+ if (i & 1) {
+ for ( var j=1 ; j < iab.length ; j++ )
+ Atomics.sub(iab, j, v);
+ }
+ else {
+ for ( var j=1 ; j < iab.length ; j++ )
+ Atomics.add(iab, j, v);
+ }
+ }
+ }
+ Atomics.add(iab, 0, 1);
+ `);
+ }
+
+ // Wait...
+ while (Atomics.load(iab, 0) != numWorkers)
+ ;
+ Atomics.store(iab, 0, 0);
+
+ // Check the results and clear the array again.
+ const v = (limit & 1) ? oddResult : evenResult;
+ for ( var i=1 ; i < iab.length ; i++ ) {
+ assertEq(iab[i], v);
+ iab[i] = 0;
+ }
+}
+
+// Under some configurations the test can take a while to run (and may
+// saturate the CPU since it runs four workers); try not to time out.
+
+var then = new Date();
+testRun(1);
+if (new Date() - then < 20000) {
+ testRun(2);
+ if (new Date() - then < 30000) {
+ testRun(3);
+ }
+}