1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
// |reftest| skip-if(!xulRuntime.shell)
if (helperThreadCount() === 0) {
if (typeof reportCompare === "function")
reportCompare(true, true);
quit();
}
// TypedArray constructors which can use radix sort.
const TAConstructors = [
Int16Array,
Uint16Array,
Int32Array,
Uint32Array,
Float32Array,
];
// Use a large enough size to ensure concurrent accesses can be detected.
const size = 0x4000;
function ToAtomicTA(TA) {
switch (TA) {
case Int16Array:
case Int32Array:
case Uint16Array:
case Uint32Array:
return TA;
case Float32Array:
return Uint32Array;
}
throw new Error("Invalid typed array kind");
}
function ascending(a, b) {
return a < b ? -1 : a > b ? 1 : 0;
}
function descending(a, b) {
return -ascending(a, b);
}
for (let TA of TAConstructors) {
let sorted = new TA(size);
// Fill with |1..size| and then sort to account for wrap-arounds.
for (let i = 0; i < size; ++i) {
sorted[i] = i + 1;
}
sorted.sort();
let extra = Math.max(TA.BYTES_PER_ELEMENT, Int32Array.BYTES_PER_ELEMENT);
let buffer = new SharedArrayBuffer(size * TA.BYTES_PER_ELEMENT + extra);
let controller = new Int32Array(buffer, 0, 1);
// Create a copy in descending order.
let ta = new TA(buffer, extra, size);
ta.set(sorted)
ta.sort(descending);
// Worker code expects that the last element changes when sorted.
assertEq(ta[size - 1] === sorted[size - 1], false);
setSharedObject(buffer);
evalInWorker(`
const ToAtomicTA = ${ToAtomicTA};
const TA = ${TA.name};
const AtomicTA = ToAtomicTA(TA);
let size = ${size};
let extra = ${extra};
let buffer = getSharedObject();
let controller = new Int32Array(buffer, 0, 1);
let ta = new AtomicTA(buffer, extra, size);
let value = Atomics.load(ta, size - 1);
// Coordinate with main thread.
while (Atomics.notify(controller, 0, 1) < 1) ;
// Wait until modification of the last element.
//
// Sorting writes in ascending indexed ordered, so when the last element
// was modified, we know that the sort operation has finished.
while (Atomics.load(ta, size - 1) === value) ;
// Set all elements to zero.
ta.fill(0);
// Sleep for 50 ms.
const amount = 0.05;
// Coordinate with main thread.
while (Atomics.notify(controller, 0, 1) < 1) {
sleep(amount);
}
`);
// Wait until worker is set-up.
assertEq(Atomics.wait(controller, 0, 0), "ok");
// Sort the array in ascending order.
ta.sort();
// Wait until worker has finished.
assertEq(Atomics.wait(controller, 0, 0), "ok");
// All elements have been set to zero.
for (let i = 0; i < size; ++i) {
assertEq(ta[i], 0, `${TA.name} at index ${i} for size ${size}`);
}
}
if (typeof reportCompare === "function")
reportCompare(true, true);
|