[test] Make tests more reliably detect races under TSAN.
Bug: https://github.com/dart-lang/sdk/issues/61974 Change-Id: I27ad40af61becc558a8d1650a7f45a1484aecc0b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/464600 Reviewed-by: Alexander Aprelev <aam@google.com> Commit-Queue: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
committed by
Commit Queue
parent
7faf4969e8
commit
85f97d54ee
@@ -2,7 +2,7 @@
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// VMOptions=--experimental-shared-data
|
||||
// VMOptions=--experimental-shared-data --no-osr --no-background-compilation
|
||||
|
||||
import "dart:ffi";
|
||||
import "dart:io";
|
||||
@@ -15,29 +15,31 @@ import '../dylib_utils.dart';
|
||||
@pragma("vm:shared")
|
||||
List<dynamic>? box;
|
||||
|
||||
@pragma("vm:never-inline")
|
||||
noopt() {}
|
||||
|
||||
@pragma("vm:never-inline")
|
||||
dataRaceFromMain() {
|
||||
final localBox = box!;
|
||||
for (var i = 0; i < 1000000; i++) {
|
||||
localBox[0] += 1;
|
||||
noopt();
|
||||
for (var i = 0; i < 50000; i++) {
|
||||
usleep(100);
|
||||
var t = localBox[0];
|
||||
usleep(100);
|
||||
localBox[0] = t + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@pragma("vm:never-inline")
|
||||
dataRaceFromChild() {
|
||||
final localBox = box!;
|
||||
for (var i = 0; i < 1000000; i++) {
|
||||
localBox[0] += 1;
|
||||
noopt();
|
||||
for (var i = 0; i < 50000; i++) {
|
||||
usleep(100);
|
||||
var t = localBox[0];
|
||||
usleep(100);
|
||||
localBox[0] = t + 1;
|
||||
}
|
||||
}
|
||||
|
||||
child(_) {
|
||||
child(replyPort) {
|
||||
dataRaceFromChild();
|
||||
replyPort.send(null);
|
||||
}
|
||||
|
||||
final nativeLib = dlopenPlatformSpecific('ffi_test_functions');
|
||||
@@ -53,6 +55,13 @@ final setFfiNativeResolverForTest = nativeLib
|
||||
@Native<IntPtr Function(Handle, Handle, Handle)>(symbol: 'UnsafeSetSharedTo')
|
||||
external int unsafeSetSharedTo(Object library_name, String name, Object value);
|
||||
|
||||
// Leaf: we don't want the two threads to synchronize via safepoint.
|
||||
final usleep = DynamicLibrary.process()
|
||||
.lookupFunction<Void Function(Long), void Function(int)>(
|
||||
'usleep',
|
||||
isLeaf: true,
|
||||
);
|
||||
|
||||
main(List<String> arguments) {
|
||||
if (arguments.contains("--testee")) {
|
||||
setFfiNativeResolverForTest(getRootLibraryUrl());
|
||||
@@ -60,8 +69,13 @@ main(List<String> arguments) {
|
||||
// Still we want to use it here to test data race detection.
|
||||
unsafeSetSharedTo(getRootLibraryUrl(), "box", List<dynamic>.filled(1, 0));
|
||||
|
||||
print(box); // side effect initialization
|
||||
Isolate.spawn(child, null);
|
||||
// Avoid synchronizing via lazy compilation and initialization.
|
||||
usleep(0);
|
||||
box![0] += 0;
|
||||
|
||||
var port = new RawReceivePort();
|
||||
port.handler = (_) => port.close();
|
||||
Isolate.spawn(child, port.sendPort);
|
||||
dataRaceFromMain();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// VMOptions=--experimental-shared-data
|
||||
// VMOptions=--experimental-shared-data --no-osr --no-background-compilation
|
||||
|
||||
import "dart:ffi";
|
||||
import "dart:io";
|
||||
@@ -20,29 +20,31 @@ class Box {
|
||||
@pragma("vm:shared")
|
||||
Box? box;
|
||||
|
||||
@pragma("vm:never-inline")
|
||||
noopt() {}
|
||||
|
||||
@pragma("vm:never-inline")
|
||||
dataRaceFromMain() {
|
||||
final localBox = box!;
|
||||
for (var i = 0; i < 1000000; i++) {
|
||||
localBox.foo += 1;
|
||||
noopt();
|
||||
for (var i = 0; i < 50000; i++) {
|
||||
usleep(100);
|
||||
var t = localBox.foo;
|
||||
usleep(100);
|
||||
localBox.foo = t + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@pragma("vm:never-inline")
|
||||
dataRaceFromChild() {
|
||||
final localBox = box!;
|
||||
for (var i = 0; i < 1000000; i++) {
|
||||
localBox.foo += 1;
|
||||
noopt();
|
||||
for (var i = 0; i < 50000; i++) {
|
||||
usleep(100);
|
||||
var t = localBox.foo;
|
||||
usleep(100);
|
||||
localBox.foo = t + 1;
|
||||
}
|
||||
}
|
||||
|
||||
child(_) {
|
||||
child(replyPort) {
|
||||
dataRaceFromChild();
|
||||
replyPort.send(null);
|
||||
}
|
||||
|
||||
final nativeLib = dlopenPlatformSpecific('ffi_test_functions');
|
||||
@@ -58,12 +60,25 @@ final setFfiNativeResolverForTest = nativeLib
|
||||
@Native<IntPtr Function(Handle, Handle, Handle)>(symbol: 'UnsafeSetSharedTo')
|
||||
external int unsafeSetSharedTo(Object library_name, String name, Object value);
|
||||
|
||||
// Leaf: we don't want the two threads to synchronize via safepoint.
|
||||
final usleep = DynamicLibrary.process()
|
||||
.lookupFunction<Void Function(Long), void Function(int)>(
|
||||
'usleep',
|
||||
isLeaf: true,
|
||||
);
|
||||
|
||||
main(List<String> arguments) {
|
||||
if (arguments.contains("--testee")) {
|
||||
setFfiNativeResolverForTest(getRootLibraryUrl());
|
||||
unsafeSetSharedTo(getRootLibraryUrl(), "box", Box());
|
||||
print(box); // side effect initialization
|
||||
Isolate.spawn(child, null);
|
||||
|
||||
// Avoid synchronizing via lazy compilation.
|
||||
usleep(0);
|
||||
box!.foo += 0;
|
||||
|
||||
var port = new RawReceivePort();
|
||||
port.handler = (_) => port.close();
|
||||
Isolate.spawn(child, port.sendPort);
|
||||
dataRaceFromMain();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// VMOptions=--experimental-shared-data
|
||||
// VMOptions=--experimental-shared-data --no-osr --no-background-compilation
|
||||
|
||||
import "dart:ffi";
|
||||
import "dart:io";
|
||||
@@ -19,24 +19,25 @@ class Box {
|
||||
@pragma("vm:shared")
|
||||
Box? box;
|
||||
|
||||
@pragma("vm:never-inline")
|
||||
noopt() {}
|
||||
|
||||
@pragma("vm:never-inline")
|
||||
dataRaceFromMain() {
|
||||
final localBox = box!;
|
||||
for (var i = 0; i < 1000000; i++) {
|
||||
localBox.foo += 1;
|
||||
noopt();
|
||||
for (var i = 0; i < 50000; i++) {
|
||||
usleep(100);
|
||||
var t = localBox.foo;
|
||||
usleep(100);
|
||||
localBox.foo = t + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@pragma("vm:never-inline")
|
||||
dataRaceFromChild() {
|
||||
final localBox = box!;
|
||||
for (var i = 0; i < 1000000; i++) {
|
||||
localBox.foo += 1;
|
||||
noopt();
|
||||
for (var i = 0; i < 50000; i++) {
|
||||
usleep(100);
|
||||
var t = localBox.foo;
|
||||
usleep(100);
|
||||
localBox.foo = t + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,8 +53,9 @@ dataRaceFromChildCaller() => dataRaceFromChild();
|
||||
@pragma("vm:never-inline")
|
||||
dataRaceFromChildCallerCaller() => dataRaceFromChildCaller();
|
||||
|
||||
child(_) {
|
||||
child(replyPort) {
|
||||
dataRaceFromChildCallerCaller();
|
||||
replyPort.send(null);
|
||||
}
|
||||
|
||||
final nativeLib = dlopenPlatformSpecific('ffi_test_functions');
|
||||
@@ -69,14 +71,27 @@ final setFfiNativeResolverForTest = nativeLib
|
||||
@Native<IntPtr Function(Handle, Handle, Handle)>(symbol: 'UnsafeSetSharedTo')
|
||||
external int unsafeSetSharedTo(Object library_name, String name, Object value);
|
||||
|
||||
// Leaf: we don't want the two threads to synchronize via safepoint.
|
||||
final usleep = DynamicLibrary.process()
|
||||
.lookupFunction<Void Function(Long), void Function(int)>(
|
||||
'usleep',
|
||||
isLeaf: true,
|
||||
);
|
||||
|
||||
main(List<String> arguments) {
|
||||
if (arguments.contains("--testee")) {
|
||||
setFfiNativeResolverForTest(getRootLibraryUrl());
|
||||
// At this point List is not allowed to be stored in shaded fields.
|
||||
// Still we want to use it here to test data race detection.
|
||||
unsafeSetSharedTo(getRootLibraryUrl(), "box", Box());
|
||||
print(box); // side effect initialization
|
||||
Isolate.spawn(child, null);
|
||||
|
||||
// Avoid synchronizing via lazy compilation.
|
||||
usleep(0);
|
||||
box!.foo += 0;
|
||||
|
||||
var port = new RawReceivePort();
|
||||
port.handler = (_) => port.close();
|
||||
Isolate.spawn(child, port.sendPort);
|
||||
dataRaceFromMainCallerCaller();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
// VMOptions=--experimental-shared-data
|
||||
// VMOptions=--experimental-shared-data --no-osr --no-background-compilation
|
||||
|
||||
import "dart:ffi";
|
||||
import "dart:io";
|
||||
import "dart:isolate";
|
||||
import "dart:typed_data";
|
||||
@@ -12,35 +13,49 @@ import "package:expect/expect.dart";
|
||||
@pragma("vm:shared")
|
||||
Uint8List box = Uint8List(1);
|
||||
|
||||
@pragma("vm:never-inline")
|
||||
noopt() {}
|
||||
|
||||
@pragma("vm:never-inline")
|
||||
dataRaceFromMain() {
|
||||
final localBox = box;
|
||||
for (var i = 0; i < 10000000; i++) {
|
||||
localBox[0] += 1;
|
||||
noopt();
|
||||
for (var i = 0; i < 50000; i++) {
|
||||
usleep(100);
|
||||
var t = localBox[0];
|
||||
usleep(100);
|
||||
localBox[0] = t + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@pragma("vm:never-inline")
|
||||
dataRaceFromChild() {
|
||||
final localBox = box;
|
||||
for (var i = 0; i < 10000000; i++) {
|
||||
localBox[0] += 1;
|
||||
noopt();
|
||||
for (var i = 0; i < 50000; i++) {
|
||||
usleep(100);
|
||||
var t = localBox[0];
|
||||
usleep(100);
|
||||
localBox[0] = t + 1;
|
||||
}
|
||||
}
|
||||
|
||||
child(_) {
|
||||
child(replyPort) {
|
||||
dataRaceFromChild();
|
||||
replyPort.send(null);
|
||||
}
|
||||
|
||||
// Leaf: we don't want the two threads to synchronize via safepoint.
|
||||
final usleep = DynamicLibrary.process()
|
||||
.lookupFunction<Void Function(Long), void Function(int)>(
|
||||
'usleep',
|
||||
isLeaf: true,
|
||||
);
|
||||
|
||||
main(List<String> arguments) {
|
||||
if (arguments.contains("--testee")) {
|
||||
print(box); // side effect initialization
|
||||
Isolate.spawn(child, null);
|
||||
// Avoid synchronizing via lazy compilation and initialization.
|
||||
usleep(0);
|
||||
box![0] += 0;
|
||||
|
||||
var port = new RawReceivePort();
|
||||
port.handler = (_) => port.close();
|
||||
Isolate.spawn(child, port.sendPort);
|
||||
dataRaceFromMain();
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user