| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/safepoint.h" | 5 #include "vm/safepoint.h" |
| 6 | 6 |
| 7 #include "vm/thread.h" | 7 #include "vm/thread.h" |
| 8 #include "vm/thread_registry.h" | 8 #include "vm/thread_registry.h" |
| 9 | 9 |
| 10 namespace dart { | 10 namespace dart { |
| 11 | 11 |
| 12 SafepointOperationScope::SafepointOperationScope(Thread* T) : StackResource(T) { | 12 SafepointOperationScope::SafepointOperationScope(Thread* T) : StackResource(T) { |
| 13 ASSERT(T != NULL); | 13 ASSERT(T != NULL); |
| 14 Isolate* I = T->isolate(); | 14 Isolate* I = T->isolate(); |
| 15 ASSERT(I != NULL); | 15 ASSERT(I != NULL); |
| 16 ASSERT(T->no_safepoint_scope_depth() == 0); | 16 ASSERT(T->no_safepoint_scope_depth() == 0); |
| 17 | 17 |
| 18 SafepointHandler* handler = I->safepoint_handler(); | 18 SafepointHandler* handler = I->safepoint_handler(); |
| 19 ASSERT(handler != NULL); | 19 ASSERT(handler != NULL); |
| 20 | 20 |
| 21 // Signal all threads to get to a safepoint and wait for them to | 21 // Signal all threads to get to a safepoint and wait for them to |
| 22 // get to a safepoint. | 22 // get to a safepoint. |
| 23 handler->SafepointThreads(T); | 23 handler->SafepointThreads(T); |
| 24 } | 24 } |
| 25 | 25 |
| 26 | |
| 27 SafepointOperationScope::~SafepointOperationScope() { | 26 SafepointOperationScope::~SafepointOperationScope() { |
| 28 Thread* T = thread(); | 27 Thread* T = thread(); |
| 29 ASSERT(T != NULL); | 28 ASSERT(T != NULL); |
| 30 Isolate* I = T->isolate(); | 29 Isolate* I = T->isolate(); |
| 31 ASSERT(I != NULL); | 30 ASSERT(I != NULL); |
| 32 | 31 |
| 33 // Resume all threads which are blocked for the safepoint operation. | 32 // Resume all threads which are blocked for the safepoint operation. |
| 34 SafepointHandler* handler = I->safepoint_handler(); | 33 SafepointHandler* handler = I->safepoint_handler(); |
| 35 ASSERT(handler != NULL); | 34 ASSERT(handler != NULL); |
| 36 handler->ResumeThreads(T); | 35 handler->ResumeThreads(T); |
| 37 } | 36 } |
| 38 | 37 |
| 39 | |
| 40 SafepointHandler::SafepointHandler(Isolate* isolate) | 38 SafepointHandler::SafepointHandler(Isolate* isolate) |
| 41 : isolate_(isolate), | 39 : isolate_(isolate), |
| 42 safepoint_lock_(new Monitor()), | 40 safepoint_lock_(new Monitor()), |
| 43 number_threads_not_at_safepoint_(0), | 41 number_threads_not_at_safepoint_(0), |
| 44 safepoint_operation_count_(0), | 42 safepoint_operation_count_(0), |
| 45 owner_(NULL) {} | 43 owner_(NULL) {} |
| 46 | 44 |
| 47 | |
| 48 SafepointHandler::~SafepointHandler() { | 45 SafepointHandler::~SafepointHandler() { |
| 49 ASSERT(owner_ == NULL); | 46 ASSERT(owner_ == NULL); |
| 50 ASSERT(safepoint_operation_count_ == 0); | 47 ASSERT(safepoint_operation_count_ == 0); |
| 51 delete safepoint_lock_; | 48 delete safepoint_lock_; |
| 52 safepoint_lock_ = NULL; | 49 safepoint_lock_ = NULL; |
| 53 isolate_ = NULL; | 50 isolate_ = NULL; |
| 54 } | 51 } |
| 55 | 52 |
| 56 | |
| 57 void SafepointHandler::SafepointThreads(Thread* T) { | 53 void SafepointHandler::SafepointThreads(Thread* T) { |
| 58 { | 54 { |
| 59 // First grab the threads list lock for this isolate | 55 // First grab the threads list lock for this isolate |
| 60 // and check if a safepoint is already in progress. This | 56 // and check if a safepoint is already in progress. This |
| 61 // ensures that two threads do not start a safepoint operation | 57 // ensures that two threads do not start a safepoint operation |
| 62 // at the same time. | 58 // at the same time. |
| 63 MonitorLocker sl(threads_lock()); | 59 MonitorLocker sl(threads_lock()); |
| 64 | 60 |
| 65 // Now check to see if a safepoint operation is already in progress | 61 // Now check to see if a safepoint operation is already in progress |
| 66 // for this isolate, block if an operation is in progress. | 62 // for this isolate, block if an operation is in progress. |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 113 // We have been waiting too long, start logging this as we might | 109 // We have been waiting too long, start logging this as we might |
| 114 // have an issue where a thread is not checking in for a safepoint. | 110 // have an issue where a thread is not checking in for a safepoint. |
| 115 OS::Print("Attempt:%" Pd " waiting for %d threads to check in\n", | 111 OS::Print("Attempt:%" Pd " waiting for %d threads to check in\n", |
| 116 num_attempts, number_threads_not_at_safepoint_); | 112 num_attempts, number_threads_not_at_safepoint_); |
| 117 } | 113 } |
| 118 } | 114 } |
| 119 } | 115 } |
| 120 } | 116 } |
| 121 } | 117 } |
| 122 | 118 |
| 123 | |
| 124 void SafepointHandler::ResumeThreads(Thread* T) { | 119 void SafepointHandler::ResumeThreads(Thread* T) { |
| 125 // First resume all the threads which are blocked for the safepoint | 120 // First resume all the threads which are blocked for the safepoint |
| 126 // operation. | 121 // operation. |
| 127 MonitorLocker sl(threads_lock()); | 122 MonitorLocker sl(threads_lock()); |
| 128 | 123 |
| 129 // First check if we are in a recursive safepoint operation, in that case | 124 // First check if we are in a recursive safepoint operation, in that case |
| 130 // we just decrement safepoint_operation_count and return. | 125 // we just decrement safepoint_operation_count and return. |
| 131 ASSERT(SafepointInProgress()); | 126 ASSERT(SafepointInProgress()); |
| 132 if (safepoint_operation_count() > 1) { | 127 if (safepoint_operation_count() > 1) { |
| 133 decrement_safepoint_operation_count(); | 128 decrement_safepoint_operation_count(); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 146 } | 141 } |
| 147 current = current->next(); | 142 current = current->next(); |
| 148 } | 143 } |
| 149 // Now reset the safepoint_in_progress_ state and notify all threads | 144 // Now reset the safepoint_in_progress_ state and notify all threads |
| 150 // that are waiting to enter the isolate or waiting to start another | 145 // that are waiting to enter the isolate or waiting to start another |
| 151 // safepoint operation. | 146 // safepoint operation. |
| 152 ResetSafepointInProgress(T); | 147 ResetSafepointInProgress(T); |
| 153 sl.NotifyAll(); | 148 sl.NotifyAll(); |
| 154 } | 149 } |
| 155 | 150 |
| 156 | |
| 157 void SafepointHandler::EnterSafepointUsingLock(Thread* T) { | 151 void SafepointHandler::EnterSafepointUsingLock(Thread* T) { |
| 158 MonitorLocker tl(T->thread_lock()); | 152 MonitorLocker tl(T->thread_lock()); |
| 159 T->SetAtSafepoint(true); | 153 T->SetAtSafepoint(true); |
| 160 if (T->IsSafepointRequested()) { | 154 if (T->IsSafepointRequested()) { |
| 161 MonitorLocker sl(safepoint_lock_); | 155 MonitorLocker sl(safepoint_lock_); |
| 162 ASSERT(number_threads_not_at_safepoint_ > 0); | 156 ASSERT(number_threads_not_at_safepoint_ > 0); |
| 163 number_threads_not_at_safepoint_ -= 1; | 157 number_threads_not_at_safepoint_ -= 1; |
| 164 sl.Notify(); | 158 sl.Notify(); |
| 165 } | 159 } |
| 166 } | 160 } |
| 167 | 161 |
| 168 | |
| 169 void SafepointHandler::ExitSafepointUsingLock(Thread* T) { | 162 void SafepointHandler::ExitSafepointUsingLock(Thread* T) { |
| 170 MonitorLocker tl(T->thread_lock()); | 163 MonitorLocker tl(T->thread_lock()); |
| 171 ASSERT(T->IsAtSafepoint()); | 164 ASSERT(T->IsAtSafepoint()); |
| 172 while (T->IsSafepointRequested()) { | 165 while (T->IsSafepointRequested()) { |
| 173 T->SetBlockedForSafepoint(true); | 166 T->SetBlockedForSafepoint(true); |
| 174 tl.Wait(); | 167 tl.Wait(); |
| 175 T->SetBlockedForSafepoint(false); | 168 T->SetBlockedForSafepoint(false); |
| 176 } | 169 } |
| 177 T->SetAtSafepoint(false); | 170 T->SetAtSafepoint(false); |
| 178 } | 171 } |
| 179 | 172 |
| 180 | |
| 181 void SafepointHandler::BlockForSafepoint(Thread* T) { | 173 void SafepointHandler::BlockForSafepoint(Thread* T) { |
| 182 MonitorLocker tl(T->thread_lock()); | 174 MonitorLocker tl(T->thread_lock()); |
| 183 if (T->IsSafepointRequested()) { | 175 if (T->IsSafepointRequested()) { |
| 184 T->SetAtSafepoint(true); | 176 T->SetAtSafepoint(true); |
| 185 { | 177 { |
| 186 MonitorLocker sl(safepoint_lock_); | 178 MonitorLocker sl(safepoint_lock_); |
| 187 ASSERT(number_threads_not_at_safepoint_ > 0); | 179 ASSERT(number_threads_not_at_safepoint_ > 0); |
| 188 number_threads_not_at_safepoint_ -= 1; | 180 number_threads_not_at_safepoint_ -= 1; |
| 189 sl.Notify(); | 181 sl.Notify(); |
| 190 } | 182 } |
| 191 while (T->IsSafepointRequested()) { | 183 while (T->IsSafepointRequested()) { |
| 192 T->SetBlockedForSafepoint(true); | 184 T->SetBlockedForSafepoint(true); |
| 193 tl.Wait(); | 185 tl.Wait(); |
| 194 T->SetBlockedForSafepoint(false); | 186 T->SetBlockedForSafepoint(false); |
| 195 } | 187 } |
| 196 T->SetAtSafepoint(false); | 188 T->SetAtSafepoint(false); |
| 197 } | 189 } |
| 198 } | 190 } |
| 199 | 191 |
| 200 } // namespace dart | 192 } // namespace dart |
| OLD | NEW |