blob: 146901d9d3a2057378fd9716863074b69e21d501 [file] [log] [blame]
// 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);
}
}