13DEFINE_FLAG(
bool, trace_safepoint,
false,
"Trace Safepoint logic.");
18 ASSERT(
T !=
nullptr &&
T->isolate_group() !=
nullptr);
20 auto handler =
T->isolate_group()->safepoint_handler();
21 handler->SafepointThreads(
T, level_);
26 ASSERT(
T !=
nullptr &&
T->isolate_group() !=
nullptr);
28 auto handler =
T->isolate_group()->safepoint_handler();
29 handler->ResumeThreads(
T, level_);
40 T->IncrementForceGrowthScopeDepth();
42 auto handler =
IG->safepoint_handler();
43 handler->SafepointThreads(
T, level_);
52 auto handler =
IG->safepoint_handler();
53 handler->ResumeThreads(
T, level_);
55 T->DecrementForceGrowthScopeDepth();
56 if (!
T->force_growth()) {
58 T->heap()->CheckCatchUp(
T);
63 : isolate_group_(isolate_group) {
75 delete handlers_[
level];
80 ASSERT(
T->no_safepoint_scope_depth() == 0);
89 if (handlers_[
level]->owner_ ==
T) {
92 AssertWeOwnLowerLevelSafepoints(
T,
level);
94 for (intptr_t
i = 0;
i <=
level; ++
i) {
95 handlers_[
i]->operation_count_++;
102 AssertWeDoNotOwnLowerLevelSafepoints(
T,
level);
106 MonitorLocker tl(
T->thread_lock());
111 EnterSafepointLocked(
T, &tl,
level);
116 while (handlers_[
level]->SafepointInProgress()) {
119 handlers_[
level]->SetSafepointInProgress(
T);
122 handlers_[
level]->NotifyThreadsToGetToSafepointLevel(
T, &oob_isolates);
125 for (
auto main_port : oob_isolates) {
131 handlers_[
level]->WaitUntilThreadsReachedSafepointLevel();
137 AcquireLowerLevelSafepoints(
T,
level);
142 MonitorLocker tl(
T->thread_lock());
143 ExitSafepointLocked(
T, &tl,
level);
147void SafepointHandler::AssertWeOwnLowerLevelSafepoints(Thread*
T,
149 for (intptr_t lower_level =
level - 1; lower_level >= 0; --lower_level) {
154void SafepointHandler::AssertWeDoNotOwnLowerLevelSafepoints(
157 for (intptr_t lower_level =
level - 1; lower_level >= 0; --lower_level) {
162void SafepointHandler::LevelHandler::NotifyThreadsToGetToSafepointLevel(
164 MallocGrowableArray<Dart_Port>* oob_isolates) {
165 ASSERT(num_threads_not_parked_ == 0);
166 for (
auto current = isolate_group()->thread_registry()->active_list();
167 current !=
nullptr; current = current->next()) {
168 MonitorLocker tl(current->thread_lock());
169 if (!current->BypassSafepoints() && current !=
T) {
170 const uint32_t
state = current->SetSafepointRequested(level_,
true);
181 auto isolate = current->scheduled_dart_mutator_isolate();
182 if (isolate !=
nullptr) {
183 oob_isolates->Add(isolate->main_port());
188 if (current->IsDartMutatorThread()) {
192 MonitorLocker sl(&parked_lock_);
193 num_threads_not_parked_++;
201 MonitorLocker sl(threads_lock());
205 AssertWeOwnLowerLevelSafepoints(
T,
level);
208 if (handlers_[
level]->operation_count_ > 1) {
209 for (intptr_t
i = 0;
i <=
level; ++
i) {
210 handlers_[
i]->operation_count_--;
215 ReleaseLowerLevelSafepoints(
T,
level);
216 handlers_[
level]->ResetSafepointInProgress(
T);
217 handlers_[
level]->NotifyThreadsToContinue(
T);
222void SafepointHandler::LevelHandler::WaitUntilThreadsReachedSafepointLevel() {
223 MonitorLocker sl(&parked_lock_);
224 intptr_t num_attempts = 0;
225 while (num_threads_not_parked_ > 0) {
229 if (FLAG_trace_safepoint && num_attempts > 10) {
230 for (
auto current = isolate_group()->thread_registry()->active_list();
231 current !=
nullptr; current = current->next()) {
232 if (!current->IsAtSafepoint(level_)) {
233 OS::PrintErr(
"Attempt:%" Pd " waiting for thread %s to check in\n",
234 num_attempts, current->os_thread()->name());
242void SafepointHandler::AcquireLowerLevelSafepoints(Thread*
T,
244 MonitorLocker tl(threads_lock());
246 for (intptr_t lower_level =
level - 1; lower_level >= 0; --lower_level) {
247 ASSERT(!handlers_[lower_level]->SafepointInProgress());
248 handlers_[lower_level]->SetSafepointInProgress(
T);
249 ASSERT(handlers_[lower_level]->owner_ ==
T);
253void SafepointHandler::ReleaseLowerLevelSafepoints(Thread*
T,
255 for (intptr_t lower_level = 0; lower_level <
level; ++lower_level) {
256 handlers_[lower_level]->ResetSafepointInProgress(
T);
260void SafepointHandler::LevelHandler::NotifyThreadsToContinue(Thread*
T) {
261 for (
auto current = isolate_group()->thread_registry()->active_list();
262 current !=
nullptr; current = current->next()) {
263 MonitorLocker tl(current->thread_lock());
264 if (!current->BypassSafepoints() && current !=
T) {
266 for (intptr_t lower_level = level_; lower_level >= 0; --lower_level) {
281 EnterSafepointLocked(
T, &tl,
T->current_safepoint_level());
287 ExitSafepointLocked(
T, &tl,
T->current_safepoint_level());
288 ASSERT(!
T->IsSafepointRequestedLocked(
T->current_safepoint_level()));
292 const Thread* current_thread)
const {
294 intptr_t last_count = -1;
312 if (handlers_[
level]->owner_ == current_thread) {
313 const intptr_t
count = handlers_[
level]->operation_count_;
314 if (
count < last_count)
return last_level;
325 ASSERT(!
T->BypassSafepoints());
329 if (
T->IsSafepointRequestedLocked(
level)) {
330 EnterSafepointLocked(
T, &tl,
level);
331 ExitSafepointLocked(
T, &tl,
level);
336void SafepointHandler::EnterSafepointLocked(
Thread*
T,
339 T->SetAtSafepoint(
true,
level);
342 for (intptr_t
i = 0;
i <=
level; ++
i) {
344 handlers_[
i]->NotifyWeAreParked(
T);
349void SafepointHandler::LevelHandler::NotifyWeAreParked(Thread*
T) {
350 ASSERT(owner_ !=
nullptr);
351 MonitorLocker sl(&parked_lock_);
352 ASSERT(num_threads_not_parked_ > 0);
353 num_threads_not_parked_ -= 1;
354 if (num_threads_not_parked_ == 0) {
359void SafepointHandler::ExitSafepointLocked(Thread*
T,
362 while (
T->IsSafepointRequestedLocked(
level)) {
363 T->SetBlockedForSafepoint(
true);
365 T->SetBlockedForSafepoint(
false);
367 T->SetAtSafepoint(
false,
level);
#define RELEASE_ASSERT(cond)
ForceGrowthSafepointOperationScope(Thread *T, SafepointLevel level)
~ForceGrowthSafepointOperationScope()
void SendInternalLibMessage(LibMsgId msg_id, uint64_t capability)
static void static void PrintErr(const char *format,...) PRINTF_ATTRIBUTE(1
SafepointLevel InnermostSafepointOperation(const Thread *current_thread) const
SafepointHandler(IsolateGroup *I)
void EnterSafepointUsingLock(Thread *T)
void BlockForSafepoint(Thread *T)
void ExitSafepointUsingLock(Thread *T)
~SafepointOperationScope()
SafepointOperationScope(Thread *T, SafepointLevel level)
bool IsBlockedForSafepoint() const
bool IsAtSafepoint() const
DEFINE_FLAG(bool, print_cluster_information, false, "Print information about clusters written to snapshot")