[vm] Make vm/cc/SafepointOperation_SafepointPointTest more robust
Closes https://github.com/dart-lang/sdk/issues/48716
TEST=vm/cc/SafepointOperation_SafepointPointTest
Change-Id: I03e392710fdc37da4a7c3b2c0934f4c4c71958fc
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/295780
Commit-Queue: Martin Kustermann <kustermann@google.com>
Reviewed-by: Ryan Macnak <rmacnak@google.com>
diff --git a/runtime/vm/heap/safepoint_test.cc b/runtime/vm/heap/safepoint_test.cc
index daedca2..c04aa74 100644
--- a/runtime/vm/heap/safepoint_test.cc
+++ b/runtime/vm/heap/safepoint_test.cc
@@ -295,15 +295,18 @@
Data(IsolateGroup* isolate_group,
SafepointLevel level,
std::atomic<intptr_t>* gc_only_checkins,
- std::atomic<intptr_t>* deopt_checkin)
+ std::atomic<intptr_t>* deopt_checkin,
+ std::atomic<intptr_t>* timeout_checkin)
: StateMachineTask::Data(isolate_group),
level(level),
gc_only_checkins(gc_only_checkins),
- deopt_checkin(deopt_checkin) {}
+ deopt_checkin(deopt_checkin),
+ timeout_checkin(timeout_checkin) {}
SafepointLevel level;
std::atomic<intptr_t>* gc_only_checkins;
std::atomic<intptr_t>* deopt_checkin;
+ std::atomic<intptr_t>* timeout_checkin;
};
explicit CheckinTask(std::shared_ptr<Data> data) : StateMachineTask(data) {}
@@ -348,9 +351,9 @@
// thread continue.
const auto now = OS::GetCurrentTimeMillis();
if ((now - last_sync) > 1000) {
- thread_->EnterSafepoint();
- thread_->ExitSafepoint();
- last_sync = now;
+ if (SafepointIfRequested(thread_, data()->timeout_checkin)) {
+ last_sync = now;
+ }
}
}
}
@@ -372,20 +375,55 @@
ISOLATE_UNIT_TEST_CASE(SafepointOperation_SafepointPointTest) {
auto isolate_group = thread->isolate_group();
- const intptr_t kTaskCount = 5;
+ const intptr_t kTaskCount = 6;
std::atomic<intptr_t> gc_only_checkins[kTaskCount];
std::atomic<intptr_t> deopt_checkin[kTaskCount];
+ std::atomic<intptr_t> timeout_checkins[kTaskCount];
for (intptr_t i = 0; i < kTaskCount; ++i) {
gc_only_checkins[i] = 0;
deopt_checkin[i] = 0;
+ timeout_checkins[i] = 0;
}
+ auto task_to_level = [](intptr_t task_id) -> SafepointLevel {
+ switch (task_id) {
+ case 0:
+ case 1:
+ case 2:
+ return SafepointLevel::kGC;
+ case 3:
+ case 4:
+ case 5:
+ return SafepointLevel::kGCAndDeopt;
+ default:
+ UNREACHABLE();
+ return SafepointLevel::kGC;
+ }
+ };
+ auto wait_for_sync = [&](intptr_t syncs) {
+ while (true) {
+ bool ready = true;
+ for (intptr_t i = 0; i < kTaskCount; ++i) {
+ const intptr_t all =
+ gc_only_checkins[i] + deopt_checkin[i] + timeout_checkins[i];
+ if (all != syncs) {
+ ready = false;
+ break;
+ }
+ }
+ if (ready) {
+ return;
+ }
+ OS::SleepMicros(1000);
+ }
+ };
+
std::vector<std::shared_ptr<CheckinTask::Data>> threads;
for (intptr_t i = 0; i < kTaskCount; ++i) {
- const auto level =
- (i % 2) == 0 ? SafepointLevel::kGC : SafepointLevel::kGCAndDeopt;
- std::unique_ptr<CheckinTask::Data> data(new CheckinTask::Data(
- isolate_group, level, &gc_only_checkins[i], &deopt_checkin[i]));
+ const auto level = task_to_level(i);
+ std::unique_ptr<CheckinTask::Data> data(
+ new CheckinTask::Data(isolate_group, level, &gc_only_checkins[i],
+ &deopt_checkin[i], &timeout_checkins[i]));
threads.push_back(std::move(data));
}
@@ -404,11 +442,11 @@
}
{
{ GcSafepointOperationScope safepoint_operation(thread); }
- OS::SleepMicros(1000); // Wait for threads to exit safepoint
+ wait_for_sync(1); // Wait for threads to exit safepoint
{ DeoptSafepointOperationScope safepoint_operation(thread); }
- OS::SleepMicros(1000); // Wait for threads to exit safepoint
+ wait_for_sync(2); // Wait for threads to exit safepoint
{ GcSafepointOperationScope safepoint_operation(thread); }
- OS::SleepMicros(1000); // Wait for threads to exit safepoint
+ wait_for_sync(3); // Wait for threads to exit safepoint
{ DeoptSafepointOperationScope safepoint_operation(thread); }
}
for (intptr_t i = 0; i < kTaskCount; i++) {
@@ -418,16 +456,16 @@
threads[i]->WaitUntil(CheckinTask::kExited);
}
for (intptr_t i = 0; i < kTaskCount; ++i) {
- const auto level =
- (i % 2) == 0 ? SafepointLevel::kGC : SafepointLevel::kGCAndDeopt;
- switch (level) {
+ switch (task_to_level(i)) {
case SafepointLevel::kGC:
EXPECT_EQ(0, deopt_checkin[i]);
EXPECT_EQ(2, gc_only_checkins[i]);
+ EXPECT_EQ(2, timeout_checkins[i]);
break;
case SafepointLevel::kGCAndDeopt:
EXPECT_EQ(4, deopt_checkin[i]);
EXPECT_EQ(0, gc_only_checkins[i]);
+ EXPECT_EQ(0, timeout_checkins[i]);
break;
case SafepointLevel::kNumLevels:
UNREACHABLE();