Skip to content

Commit 85f97d5

Browse files
rmacnak-googleCommit Queue
authored andcommitted
[test] Make tests more reliably detect races under TSAN.
Bug: #61974 Change-Id: I27ad40af61becc558a8d1650a7f45a1484aecc0b Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/464600 Reviewed-by: Alexander Aprelev <[email protected]> Commit-Queue: Ryan Macnak <[email protected]>
1 parent 7faf496 commit 85f97d5

File tree

4 files changed

+111
-52
lines changed

4 files changed

+111
-52
lines changed

runtime/tests/vm/dart/tsan/array_data_race_test.dart

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
// VMOptions=--experimental-shared-data
5+
// VMOptions=--experimental-shared-data --no-osr --no-background-compilation
66

77
import "dart:ffi";
88
import "dart:io";
@@ -15,29 +15,31 @@ import '../dylib_utils.dart';
1515
@pragma("vm:shared")
1616
List<dynamic>? box;
1717

18-
@pragma("vm:never-inline")
19-
noopt() {}
20-
2118
@pragma("vm:never-inline")
2219
dataRaceFromMain() {
2320
final localBox = box!;
24-
for (var i = 0; i < 1000000; i++) {
25-
localBox[0] += 1;
26-
noopt();
21+
for (var i = 0; i < 50000; i++) {
22+
usleep(100);
23+
var t = localBox[0];
24+
usleep(100);
25+
localBox[0] = t + 1;
2726
}
2827
}
2928

3029
@pragma("vm:never-inline")
3130
dataRaceFromChild() {
3231
final localBox = box!;
33-
for (var i = 0; i < 1000000; i++) {
34-
localBox[0] += 1;
35-
noopt();
32+
for (var i = 0; i < 50000; i++) {
33+
usleep(100);
34+
var t = localBox[0];
35+
usleep(100);
36+
localBox[0] = t + 1;
3637
}
3738
}
3839

39-
child(_) {
40+
child(replyPort) {
4041
dataRaceFromChild();
42+
replyPort.send(null);
4143
}
4244

4345
final nativeLib = dlopenPlatformSpecific('ffi_test_functions');
@@ -53,15 +55,27 @@ final setFfiNativeResolverForTest = nativeLib
5355
@Native<IntPtr Function(Handle, Handle, Handle)>(symbol: 'UnsafeSetSharedTo')
5456
external int unsafeSetSharedTo(Object library_name, String name, Object value);
5557

58+
// Leaf: we don't want the two threads to synchronize via safepoint.
59+
final usleep = DynamicLibrary.process()
60+
.lookupFunction<Void Function(Long), void Function(int)>(
61+
'usleep',
62+
isLeaf: true,
63+
);
64+
5665
main(List<String> arguments) {
5766
if (arguments.contains("--testee")) {
5867
setFfiNativeResolverForTest(getRootLibraryUrl());
5968
// At this point List is not allowed to be stored in shaded fields.
6069
// Still we want to use it here to test data race detection.
6170
unsafeSetSharedTo(getRootLibraryUrl(), "box", List<dynamic>.filled(1, 0));
6271

63-
print(box); // side effect initialization
64-
Isolate.spawn(child, null);
72+
// Avoid synchronizing via lazy compilation and initialization.
73+
usleep(0);
74+
box![0] += 0;
75+
76+
var port = new RawReceivePort();
77+
port.handler = (_) => port.close();
78+
Isolate.spawn(child, port.sendPort);
6579
dataRaceFromMain();
6680
return;
6781
}

runtime/tests/vm/dart/tsan/field_data_race_no_sanitize_test.dart

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
// VMOptions=--experimental-shared-data
5+
// VMOptions=--experimental-shared-data --no-osr --no-background-compilation
66

77
import "dart:ffi";
88
import "dart:io";
@@ -20,29 +20,31 @@ class Box {
2020
@pragma("vm:shared")
2121
Box? box;
2222

23-
@pragma("vm:never-inline")
24-
noopt() {}
25-
2623
@pragma("vm:never-inline")
2724
dataRaceFromMain() {
2825
final localBox = box!;
29-
for (var i = 0; i < 1000000; i++) {
30-
localBox.foo += 1;
31-
noopt();
26+
for (var i = 0; i < 50000; i++) {
27+
usleep(100);
28+
var t = localBox.foo;
29+
usleep(100);
30+
localBox.foo = t + 1;
3231
}
3332
}
3433

3534
@pragma("vm:never-inline")
3635
dataRaceFromChild() {
3736
final localBox = box!;
38-
for (var i = 0; i < 1000000; i++) {
39-
localBox.foo += 1;
40-
noopt();
37+
for (var i = 0; i < 50000; i++) {
38+
usleep(100);
39+
var t = localBox.foo;
40+
usleep(100);
41+
localBox.foo = t + 1;
4142
}
4243
}
4344

44-
child(_) {
45+
child(replyPort) {
4546
dataRaceFromChild();
47+
replyPort.send(null);
4648
}
4749

4850
final nativeLib = dlopenPlatformSpecific('ffi_test_functions');
@@ -58,12 +60,25 @@ final setFfiNativeResolverForTest = nativeLib
5860
@Native<IntPtr Function(Handle, Handle, Handle)>(symbol: 'UnsafeSetSharedTo')
5961
external int unsafeSetSharedTo(Object library_name, String name, Object value);
6062

63+
// Leaf: we don't want the two threads to synchronize via safepoint.
64+
final usleep = DynamicLibrary.process()
65+
.lookupFunction<Void Function(Long), void Function(int)>(
66+
'usleep',
67+
isLeaf: true,
68+
);
69+
6170
main(List<String> arguments) {
6271
if (arguments.contains("--testee")) {
6372
setFfiNativeResolverForTest(getRootLibraryUrl());
6473
unsafeSetSharedTo(getRootLibraryUrl(), "box", Box());
65-
print(box); // side effect initialization
66-
Isolate.spawn(child, null);
74+
75+
// Avoid synchronizing via lazy compilation.
76+
usleep(0);
77+
box!.foo += 0;
78+
79+
var port = new RawReceivePort();
80+
port.handler = (_) => port.close();
81+
Isolate.spawn(child, port.sendPort);
6782
dataRaceFromMain();
6883
return;
6984
}

runtime/tests/vm/dart/tsan/field_data_race_test.dart

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
// VMOptions=--experimental-shared-data
5+
// VMOptions=--experimental-shared-data --no-osr --no-background-compilation
66

77
import "dart:ffi";
88
import "dart:io";
@@ -19,24 +19,25 @@ class Box {
1919
@pragma("vm:shared")
2020
Box? box;
2121

22-
@pragma("vm:never-inline")
23-
noopt() {}
24-
2522
@pragma("vm:never-inline")
2623
dataRaceFromMain() {
2724
final localBox = box!;
28-
for (var i = 0; i < 1000000; i++) {
29-
localBox.foo += 1;
30-
noopt();
25+
for (var i = 0; i < 50000; i++) {
26+
usleep(100);
27+
var t = localBox.foo;
28+
usleep(100);
29+
localBox.foo = t + 1;
3130
}
3231
}
3332

3433
@pragma("vm:never-inline")
3534
dataRaceFromChild() {
3635
final localBox = box!;
37-
for (var i = 0; i < 1000000; i++) {
38-
localBox.foo += 1;
39-
noopt();
36+
for (var i = 0; i < 50000; i++) {
37+
usleep(100);
38+
var t = localBox.foo;
39+
usleep(100);
40+
localBox.foo = t + 1;
4041
}
4142
}
4243

@@ -52,8 +53,9 @@ dataRaceFromChildCaller() => dataRaceFromChild();
5253
@pragma("vm:never-inline")
5354
dataRaceFromChildCallerCaller() => dataRaceFromChildCaller();
5455

55-
child(_) {
56+
child(replyPort) {
5657
dataRaceFromChildCallerCaller();
58+
replyPort.send(null);
5759
}
5860

5961
final nativeLib = dlopenPlatformSpecific('ffi_test_functions');
@@ -69,14 +71,27 @@ final setFfiNativeResolverForTest = nativeLib
6971
@Native<IntPtr Function(Handle, Handle, Handle)>(symbol: 'UnsafeSetSharedTo')
7072
external int unsafeSetSharedTo(Object library_name, String name, Object value);
7173

74+
// Leaf: we don't want the two threads to synchronize via safepoint.
75+
final usleep = DynamicLibrary.process()
76+
.lookupFunction<Void Function(Long), void Function(int)>(
77+
'usleep',
78+
isLeaf: true,
79+
);
80+
7281
main(List<String> arguments) {
7382
if (arguments.contains("--testee")) {
7483
setFfiNativeResolverForTest(getRootLibraryUrl());
7584
// At this point List is not allowed to be stored in shaded fields.
7685
// Still we want to use it here to test data race detection.
7786
unsafeSetSharedTo(getRootLibraryUrl(), "box", Box());
78-
print(box); // side effect initialization
79-
Isolate.spawn(child, null);
87+
88+
// Avoid synchronizing via lazy compilation.
89+
usleep(0);
90+
box!.foo += 0;
91+
92+
var port = new RawReceivePort();
93+
port.handler = (_) => port.close();
94+
Isolate.spawn(child, port.sendPort);
8095
dataRaceFromMainCallerCaller();
8196
return;
8297
}

runtime/tests/vm/dart/tsan/typed_data_race_test.dart

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5-
// VMOptions=--experimental-shared-data
5+
// VMOptions=--experimental-shared-data --no-osr --no-background-compilation
66

7+
import "dart:ffi";
78
import "dart:io";
89
import "dart:isolate";
910
import "dart:typed_data";
@@ -12,35 +13,49 @@ import "package:expect/expect.dart";
1213
@pragma("vm:shared")
1314
Uint8List box = Uint8List(1);
1415

15-
@pragma("vm:never-inline")
16-
noopt() {}
17-
1816
@pragma("vm:never-inline")
1917
dataRaceFromMain() {
2018
final localBox = box;
21-
for (var i = 0; i < 10000000; i++) {
22-
localBox[0] += 1;
23-
noopt();
19+
for (var i = 0; i < 50000; i++) {
20+
usleep(100);
21+
var t = localBox[0];
22+
usleep(100);
23+
localBox[0] = t + 1;
2424
}
2525
}
2626

2727
@pragma("vm:never-inline")
2828
dataRaceFromChild() {
2929
final localBox = box;
30-
for (var i = 0; i < 10000000; i++) {
31-
localBox[0] += 1;
32-
noopt();
30+
for (var i = 0; i < 50000; i++) {
31+
usleep(100);
32+
var t = localBox[0];
33+
usleep(100);
34+
localBox[0] = t + 1;
3335
}
3436
}
3537

36-
child(_) {
38+
child(replyPort) {
3739
dataRaceFromChild();
40+
replyPort.send(null);
3841
}
3942

43+
// Leaf: we don't want the two threads to synchronize via safepoint.
44+
final usleep = DynamicLibrary.process()
45+
.lookupFunction<Void Function(Long), void Function(int)>(
46+
'usleep',
47+
isLeaf: true,
48+
);
49+
4050
main(List<String> arguments) {
4151
if (arguments.contains("--testee")) {
42-
print(box); // side effect initialization
43-
Isolate.spawn(child, null);
52+
// Avoid synchronizing via lazy compilation and initialization.
53+
usleep(0);
54+
box![0] += 0;
55+
56+
var port = new RawReceivePort();
57+
port.handler = (_) => port.close();
58+
Isolate.spawn(child, port.sendPort);
4459
dataRaceFromMain();
4560
return;
4661
}

0 commit comments

Comments
 (0)