Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(569)

Side by Side Diff: test/mjsunit/harmony/futex.js

Issue 1208933006: Atomics Futex API (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: TODO about busy-waiting Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « test/cctest/test-api.cc ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Flags: --allow-natives-syntax --harmony-atomics --harmony-sharedarraybuffer
6
7 (function TestFailsWithNonSharedArray() {
8 var ab = new ArrayBuffer(16);
9
10 var i8a = new Int8Array(ab);
11 var i16a = new Int16Array(ab);
12 var i32a = new Int32Array(ab);
13 var ui8a = new Uint8Array(ab);
14 var ui8ca = new Uint8ClampedArray(ab);
15 var ui16a = new Uint16Array(ab);
16 var ui32a = new Uint32Array(ab);
17 var f32a = new Float32Array(ab);
18 var f64a = new Float64Array(ab);
19
20 [i8a, i16a, i32a, ui8a, ui8ca, ui16a, ui32a, f32a, f64a].forEach(function(
21 ta) {
22 assertThrows(function() { Atomics.futexWait(ta, 0, 0); });
23 assertThrows(function() { Atomics.futexWake(ta, 0, 1); });
24 assertThrows(function() { Atomics.futexWakeOrRequeue(ta, 0, 1, 0, 0); });
25 });
26 })();
27
28 (function TestFailsWithNonSharedInt32Array() {
29 var sab = new SharedArrayBuffer(16);
30
31 var i8a = new Int8Array(sab);
32 var i16a = new Int16Array(sab);
33 var ui8a = new Uint8Array(sab);
34 var ui8ca = new Uint8ClampedArray(sab);
35 var ui16a = new Uint16Array(sab);
36 var ui32a = new Uint32Array(sab);
37 var f32a = new Float32Array(sab);
38 var f64a = new Float64Array(sab);
39
40 [i8a, i16a, ui8a, ui8ca, ui16a, ui32a, f32a, f64a].forEach(function(
41 ta) {
42 assertThrows(function() { Atomics.futexWait(ta, 0, 0); });
43 assertThrows(function() { Atomics.futexWake(ta, 0, 1); });
44 assertThrows(function() { Atomics.futexWakeOrRequeue(ta, 0, 1, 0, 0); });
45 });
46 })();
47
48 (function TestInvalidIndex() {
49 var i32a = new Int32Array(new SharedArrayBuffer(16));
50
51 // Valid indexes are 0-3.
52 [-1, 4, 100].forEach(function(invalidIndex) {
53 assertEquals(undefined, Atomics.futexWait(i32a, invalidIndex, 0));
54 assertEquals(undefined, Atomics.futexWake(i32a, invalidIndex, 0));
55 var validIndex = 0;
56 assertEquals(undefined, Atomics.futexWakeOrRequeue(i32a, invalidIndex, 0, 0,
57 validIndex));
58 assertEquals(undefined, Atomics.futexWakeOrRequeue(i32a, validIndex, 0, 0,
59 invalidIndex));
60 });
61
62 })();
63
64 (function TestWaitTimeout() {
65 var i32a = new Int32Array(new SharedArrayBuffer(16));
66 var waitMs = 100;
67 var startTime = new Date();
68 assertEquals(Atomics.TIMEDOUT, Atomics.futexWait(i32a, 0, 0, waitMs));
69 var endTime = new Date();
70 assertTrue(endTime - startTime >= waitMs);
71 })();
72
73 (function TestWaitNotEqual() {
74 var i32a = new Int32Array(new SharedArrayBuffer(16));
75 assertEquals(Atomics.NOTEQUAL, Atomics.futexWait(i32a, 0, 42));
76 })();
77
78 (function TestWaitNegativeTimeout() {
79 var i32a = new Int32Array(new SharedArrayBuffer(16));
80 assertEquals(Atomics.TIMEDOUT, Atomics.futexWait(i32a, 0, 0, -1));
81 assertEquals(Atomics.TIMEDOUT, Atomics.futexWait(i32a, 0, 0, -Infinity));
82 })();
83
84 //// WORKER ONLY TESTS
85
86 if (this.Worker) {
87
88 var TestWaitWithTimeout = function(timeout) {
89 var sab = new SharedArrayBuffer(16);
90 var i32a = new Int32Array(sab);
91
92 var workerScript =
93 `onmessage = function(sab) {
94 var i32a = new Int32Array(sab);
95 var result = Atomics.futexWait(i32a, 0, 0, ${timeout});
96 postMessage(result);
97 };`;
98
99 var worker = new Worker(workerScript);
100 worker.postMessage(sab, [sab]);
101
102 // Spin until the worker is waiting on the futex.
103 while (%AtomicsFutexNumWaitersForTesting(i32a, 0) != 1) {}
104
105 Atomics.futexWake(i32a, 0, 1);
106 assertEquals(Atomics.OK, worker.getMessage());
107 worker.terminate();
108 };
109
110 // Test various infinite timeouts
111 TestWaitWithTimeout(undefined);
112 TestWaitWithTimeout(NaN);
113 TestWaitWithTimeout(Infinity);
114
115
116 (function TestWakeMulti() {
117 var sab = new SharedArrayBuffer(20);
118 var i32a = new Int32Array(sab);
119
120 // SAB values:
121 // i32a[id], where id in range [0, 3]:
122 // 0 => Worker |id| is still waiting on the futex
123 // 1 => Worker |id| is not waiting on futex, but has not be reaped by the
124 // main thread.
125 // 2 => Worker |id| has been reaped.
126 //
127 // i32a[4]:
128 // always 0. Each worker is waiting on this index.
129
130 var workerScript =
131 `onmessage = function(msg) {
132 var id = msg.id;
133 var i32a = new Int32Array(msg.sab);
134
135 // Wait on i32a[4] (should be zero).
136 var result = Atomics.futexWait(i32a, 4, 0);
137 // Set i32a[id] to 1 to notify the main thread which workers were
138 // woken up.
139 Atomics.store(i32a, id, 1);
140 postMessage(result);
141 };`;
142
143 var id;
144 var workers = [];
145 for (id = 0; id < 4; id++) {
146 workers[id] = new Worker(workerScript);
147 workers[id].postMessage({sab: sab, id: id}, [sab]);
148 }
149
150 // Spin until all workers are waiting on the futex.
151 while (%AtomicsFutexNumWaitersForTesting(i32a, 4) != 4) {}
152
153 // Wake up three waiters.
154 assertEquals(3, Atomics.futexWake(i32a, 4, 3));
155
156 var wokenCount = 0;
157 var waitingId = 0 + 1 + 2 + 3;
158 while (wokenCount < 3) {
159 for (id = 0; id < 4; id++) {
160 // Look for workers that have not yet been reaped. Set i32a[id] to 2
161 // when they've been processed so we don't look at them again.
162 if (Atomics.compareExchange(i32a, id, 1, 2) == 1) {
163 assertEquals(Atomics.OK, workers[id].getMessage());
164 workers[id].terminate();
165 waitingId -= id;
166 wokenCount++;
167 }
168 }
169 }
170
171 assertEquals(3, wokenCount);
172 assertEquals(0, Atomics.load(i32a, waitingId));
173 assertEquals(1, %AtomicsFutexNumWaitersForTesting(i32a, 4));
174
175 // Finally wake the last waiter.
176 assertEquals(1, Atomics.futexWake(i32a, 4, 1));
177 assertEquals(Atomics.OK, workers[waitingId].getMessage());
178 workers[waitingId].terminate();
179
180 assertEquals(0, %AtomicsFutexNumWaitersForTesting(i32a, 4));
181
182 })();
183
184 (function TestWakeOrRequeue() {
185 var sab = new SharedArrayBuffer(24);
186 var i32a = new Int32Array(sab);
187
188 // SAB values:
189 // i32a[id], where id in range [0, 3]:
190 // 0 => Worker |id| is still waiting on the futex
191 // 1 => Worker |id| is not waiting on futex, but has not be reaped by the
192 // main thread.
193 // 2 => Worker |id| has been reaped.
194 //
195 // i32a[4]:
196 // always 0. Each worker will initially wait on this index.
197 //
198 // i32a[5]:
199 // always 0. Requeued workers will wait on this index.
200
201 var workerScript =
202 `onmessage = function(msg) {
203 var id = msg.id;
204 var i32a = new Int32Array(msg.sab);
205
206 var result = Atomics.futexWait(i32a, 4, 0, Infinity);
207 Atomics.store(i32a, id, 1);
208 postMessage(result);
209 };`;
210
211 var workers = [];
212 for (id = 0; id < 4; id++) {
213 workers[id] = new Worker(workerScript);
214 workers[id].postMessage({sab: sab, id: id}, [sab]);
215 }
216
217 // Spin until all workers are waiting on the futex.
218 while (%AtomicsFutexNumWaitersForTesting(i32a, 4) != 4) {}
219
220 var index1 = 4;
221 var index2 = 5;
222
223 // If futexWakeOrRequeue is called with the incorrect value, it shouldn't
224 // wake any waiters.
225 assertEquals(Atomics.NOTEQUAL,
226 Atomics.futexWakeOrRequeue(i32a, index1, 1, 42, index2));
227
228 assertEquals(4, %AtomicsFutexNumWaitersForTesting(i32a, index1));
229 assertEquals(0, %AtomicsFutexNumWaitersForTesting(i32a, index2));
230
231 // Now wake with the correct value.
232 assertEquals(1, Atomics.futexWakeOrRequeue(i32a, index1, 1, 0, index2));
233
234 // The workers that are still waiting should atomically be transferred to
235 // the new index.
236 assertEquals(3, %AtomicsFutexNumWaitersForTesting(i32a, index2));
237
238 // The woken worker may not have been scheduled yet. Look for which thread
239 // has set its i32a value to 1.
240 var wokenCount = 0;
241 while (wokenCount < 1) {
242 for (id = 0; id < 4; id++) {
243 if (Atomics.compareExchange(i32a, id, 1, 2) == 1) {
244 wokenCount++;
245 }
246 }
247 }
248
249 assertEquals(0, %AtomicsFutexNumWaitersForTesting(i32a, index1));
250
251 // Wake the remaining waiters.
252 assertEquals(3, Atomics.futexWake(i32a, index2, 3));
253
254 // As above, wait until the workers have been scheduled.
255 wokenCount = 0;
256 while (wokenCount < 3) {
257 for (id = 0; id < 4; id++) {
258 if (Atomics.compareExchange(i32a, id, 1, 2) == 1) {
259 wokenCount++;
260 }
261 }
262 }
263
264 assertEquals(0, %AtomicsFutexNumWaitersForTesting(i32a, index1));
265 assertEquals(0, %AtomicsFutexNumWaitersForTesting(i32a, index2));
266
267 for (id = 0; id < 4; ++id) {
268 assertEquals(Atomics.OK, workers[id].getMessage());
269 workers[id].terminate();
270 }
271
272 })();
273
274 }
OLDNEW
« no previous file with comments | « test/cctest/test-api.cc ('k') | tools/gyp/v8.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698