| Index: runtime/vm/thread_interrupter.cc
|
| diff --git a/runtime/vm/thread_interrupter.cc b/runtime/vm/thread_interrupter.cc
|
| index 2d44208739fd38bdf776c603fa8100bd170e51dc..d2858f71c74c1f2f1061d6fb6396c7da7baf298c 100644
|
| --- a/runtime/vm/thread_interrupter.cc
|
| +++ b/runtime/vm/thread_interrupter.cc
|
| @@ -52,19 +52,21 @@ Monitor* ThreadInterrupter::monitor_ = NULL;
|
| intptr_t ThreadInterrupter::interrupt_period_ = 1000;
|
| ThreadLocalKey ThreadInterrupter::thread_state_key_ =
|
| Thread::kUnsetThreadLocalKey;
|
| -ThreadInterrupter::ThreadState** ThreadInterrupter::threads_ = NULL;
|
| -intptr_t ThreadInterrupter::threads_capacity_ = 0;
|
| -intptr_t ThreadInterrupter::threads_size_ = 0;
|
|
|
|
|
| void ThreadInterrupter::InitOnce() {
|
| ASSERT(!initialized_);
|
| - initialized_ = true;
|
| ASSERT(thread_state_key_ == Thread::kUnsetThreadLocalKey);
|
| thread_state_key_ = Thread::CreateThreadLocal();
|
| ASSERT(thread_state_key_ != Thread::kUnsetThreadLocalKey);
|
| monitor_ = new Monitor();
|
| - ResizeThreads(16);
|
| + ASSERT(monitor_ != NULL);
|
| + initialized_ = true;
|
| +}
|
| +
|
| +
|
| +void ThreadInterrupter::Startup() {
|
| + ASSERT(initialized_);
|
| if (FLAG_trace_thread_interrupter) {
|
| OS::Print("ThreadInterrupter starting up.\n");
|
| }
|
| @@ -92,15 +94,9 @@ void ThreadInterrupter::Shutdown() {
|
| if (FLAG_trace_thread_interrupter) {
|
| OS::Print("ThreadInterrupter shutting down.\n");
|
| }
|
| - intptr_t size_at_shutdown = 0;
|
| {
|
| MonitorLocker ml(monitor_);
|
| shutdown_ = true;
|
| - size_at_shutdown = threads_size_;
|
| - threads_size_ = 0;
|
| - threads_capacity_ = 0;
|
| - free(threads_);
|
| - threads_ = NULL;
|
| }
|
| {
|
| MonitorLocker shutdown_ml(monitor_);
|
| @@ -110,7 +106,7 @@ void ThreadInterrupter::Shutdown() {
|
| }
|
| interrupter_thread_id_ = Thread::kInvalidThreadId;
|
| if (FLAG_trace_thread_interrupter) {
|
| - OS::Print("ThreadInterrupter shut down (%" Pd ").\n", size_at_shutdown);
|
| + OS::Print("ThreadInterrupter shut down.\n");
|
| }
|
| }
|
|
|
| @@ -121,27 +117,22 @@ void ThreadInterrupter::SetInterruptPeriod(intptr_t period) {
|
| }
|
| ASSERT(initialized_);
|
| ASSERT(period > 0);
|
| - {
|
| - MonitorLocker ml(monitor_);
|
| - interrupt_period_ = period;
|
| - }
|
| + interrupt_period_ = period;
|
| }
|
|
|
|
|
| // Register the currently running thread for interrupts. If the current thread
|
| // is already registered, callback and data will be updated.
|
| -void ThreadInterrupter::Register(ThreadInterruptCallback callback, void* data) {
|
| +InterruptableThreadState* ThreadInterrupter::Register(
|
| + ThreadInterruptCallback callback, void* data) {
|
| if (shutdown_) {
|
| - return;
|
| + return NULL;
|
| }
|
| ASSERT(initialized_);
|
| - {
|
| - MonitorLocker ml(monitor_);
|
| - _EnsureThreadStateCreated();
|
| - // Set callback and data.
|
| - UpdateStateObject(callback, data);
|
| - _Enable();
|
| - }
|
| + InterruptableThreadState* state = _EnsureThreadStateCreated();
|
| + // Set callback and data.
|
| + UpdateStateObject(callback, data);
|
| + return state;
|
| }
|
|
|
|
|
| @@ -151,44 +142,14 @@ void ThreadInterrupter::Unregister() {
|
| return;
|
| }
|
| ASSERT(initialized_);
|
| - {
|
| - MonitorLocker ml(monitor_);
|
| - _EnsureThreadStateCreated();
|
| - // Clear callback and data.
|
| - UpdateStateObject(NULL, NULL);
|
| - _Disable();
|
| - }
|
| + _EnsureThreadStateCreated();
|
| + // Clear callback and data.
|
| + UpdateStateObject(NULL, NULL);
|
| }
|
|
|
|
|
| -void ThreadInterrupter::Enable() {
|
| - if (shutdown_) {
|
| - return;
|
| - }
|
| - ASSERT(initialized_);
|
| - {
|
| - MonitorLocker ml(monitor_);
|
| - _EnsureThreadStateCreated();
|
| - _Enable();
|
| - }
|
| -}
|
| -
|
| -
|
| -void ThreadInterrupter::Disable() {
|
| - if (shutdown_) {
|
| - return;
|
| - }
|
| - ASSERT(initialized_);
|
| - {
|
| - MonitorLocker ml(monitor_);
|
| - _EnsureThreadStateCreated();
|
| - _Disable();
|
| - }
|
| -}
|
| -
|
| -
|
| -void ThreadInterrupter::_EnsureThreadStateCreated() {
|
| - ThreadState* state = CurrentThreadState();
|
| +InterruptableThreadState* ThreadInterrupter::_EnsureThreadStateCreated() {
|
| + InterruptableThreadState* state = CurrentThreadState();
|
| if (state == NULL) {
|
| // Create thread state object lazily.
|
| ThreadId current_thread = Thread::GetCurrentThreadId();
|
| @@ -197,56 +158,21 @@ void ThreadInterrupter::_EnsureThreadStateCreated() {
|
| OS::Print("ThreadInterrupter Tracking %p\n",
|
| reinterpret_cast<void*>(tid));
|
| }
|
| - state = new ThreadState();
|
| + // Note: We currently do not free a thread's InterruptableThreadState.
|
| + state = new InterruptableThreadState();
|
| + ASSERT(state != NULL);
|
| state->callback = NULL;
|
| state->data = NULL;
|
| state->id = current_thread;
|
| SetCurrentThreadState(state);
|
| }
|
| + return state;
|
| }
|
|
|
|
|
| -void ThreadInterrupter::_Enable() {
|
| - // Must be called with monitor_ locked.
|
| - ThreadId current_thread = Thread::GetCurrentThreadId();
|
| - if (Thread::Compare(current_thread, interrupter_thread_id_)) {
|
| - return;
|
| - }
|
| - intptr_t i = FindThreadIndex(current_thread);
|
| - if (i >= 0) {
|
| - return;
|
| - }
|
| - AddThread(current_thread);
|
| - if (FLAG_trace_thread_interrupter) {
|
| - intptr_t tid = Thread::ThreadIdToIntPtr(current_thread);
|
| - OS::Print("ThreadInterrupter Added %p\n", reinterpret_cast<void*>(tid));
|
| - }
|
| -}
|
| -
|
| -void ThreadInterrupter::_Disable() {
|
| - // Must be called with monitor_ locked.
|
| - ThreadId current_thread = Thread::GetCurrentThreadId();
|
| - if (Thread::Compare(current_thread, interrupter_thread_id_)) {
|
| - return;
|
| - }
|
| - intptr_t index = FindThreadIndex(current_thread);
|
| - if (index < 0) {
|
| - // Not registered.
|
| - return;
|
| - }
|
| - ThreadState* state = RemoveThread(index);
|
| - ASSERT(state != NULL);
|
| - ASSERT(state == ThreadInterrupter::CurrentThreadState());
|
| - if (FLAG_trace_thread_interrupter) {
|
| - intptr_t tid = Thread::ThreadIdToIntPtr(current_thread);
|
| - OS::Print("ThreadInterrupter Removed %p\n", reinterpret_cast<void*>(tid));
|
| - }
|
| -}
|
| -
|
| void ThreadInterrupter::UpdateStateObject(ThreadInterruptCallback callback,
|
| void* data) {
|
| - // Must be called with monitor_ locked.
|
| - ThreadState* state = CurrentThreadState();
|
| + InterruptableThreadState* state = CurrentThreadState();
|
| ThreadId current_thread = Thread::GetCurrentThreadId();
|
| ASSERT(state != NULL);
|
| ASSERT(Thread::Compare(state->id, Thread::GetCurrentThreadId()));
|
| @@ -267,90 +193,41 @@ void ThreadInterrupter::UpdateStateObject(ThreadInterruptCallback callback,
|
| }
|
|
|
|
|
| -ThreadInterrupter::ThreadState* ThreadInterrupter::CurrentThreadState() {
|
| - ThreadState* state = reinterpret_cast<ThreadState*>(
|
| - Thread::GetThreadLocal(thread_state_key_));
|
| - return state;
|
| +InterruptableThreadState* ThreadInterrupter::GetCurrentThreadState() {
|
| + return _EnsureThreadStateCreated();
|
| }
|
|
|
|
|
| -void ThreadInterrupter::SetCurrentThreadState(ThreadState* state) {
|
| - Thread::SetThreadLocal(thread_state_key_, reinterpret_cast<uword>(state));
|
| +InterruptableThreadState* ThreadInterrupter::CurrentThreadState() {
|
| + InterruptableThreadState* state = reinterpret_cast<InterruptableThreadState*>(
|
| + Thread::GetThreadLocal(thread_state_key_));
|
| + return state;
|
| }
|
|
|
|
|
| -void ThreadInterrupter::ResizeThreads(intptr_t new_capacity) {
|
| - // Must be called with monitor_ locked.
|
| - ASSERT(new_capacity < kMaxThreads);
|
| - ASSERT(new_capacity > threads_capacity_);
|
| - ThreadState* state = NULL;
|
| - threads_ = reinterpret_cast<ThreadState**>(
|
| - realloc(threads_, sizeof(state) * new_capacity));
|
| - for (intptr_t i = threads_capacity_; i < new_capacity; i++) {
|
| - threads_[i] = NULL;
|
| - }
|
| - threads_capacity_ = new_capacity;
|
| +void ThreadInterrupter::SetCurrentThreadState(InterruptableThreadState* state) {
|
| + Thread::SetThreadLocal(thread_state_key_, reinterpret_cast<uword>(state));
|
| }
|
|
|
|
|
| -void ThreadInterrupter::AddThread(ThreadId id) {
|
| - // Must be called with monitor_ locked.
|
| - if (threads_ == NULL) {
|
| - // We are shutting down.
|
| - return;
|
| - }
|
| - ThreadState* state = CurrentThreadState();
|
| - if (state->callback == NULL) {
|
| - // No callback.
|
| - return;
|
| - }
|
| - if (threads_size_ == threads_capacity_) {
|
| - ResizeThreads(threads_capacity_ == 0 ? 16 : threads_capacity_ * 2);
|
| - }
|
| - threads_[threads_size_] = state;
|
| - threads_size_++;
|
| +void ThreadInterruptNoOp(const InterruptedThreadState& state, void* data) {
|
| + // NoOp.
|
| }
|
|
|
|
|
| -intptr_t ThreadInterrupter::FindThreadIndex(ThreadId id) {
|
| - // Must be called with monitor_ locked.
|
| - if (threads_ == NULL) {
|
| - // We are shutting down.
|
| - return -1;
|
| - }
|
| - for (intptr_t i = 0; i < threads_size_; i++) {
|
| - if (threads_[i]->id == id) {
|
| - return i;
|
| +class ThreadInterrupterVisitIsolates : public IsolateVisitor {
|
| + public:
|
| + ThreadInterrupterVisitIsolates() { }
|
| + void VisitIsolate(Isolate* isolate) {
|
| + ASSERT(isolate != NULL);
|
| + InterruptableThreadState* state = isolate->thread_state();
|
| + if (state == NULL) {
|
| + return;
|
| }
|
| + ASSERT(state->id != Thread::kInvalidThreadId);
|
| + ThreadInterrupter::InterruptThread(state);
|
| }
|
| - return -1;
|
| -}
|
| -
|
| -
|
| -ThreadInterrupter::ThreadState* ThreadInterrupter::RemoveThread(intptr_t i) {
|
| - // Must be called with monitor_ locked.
|
| - if (threads_ == NULL) {
|
| - // We are shutting down.
|
| - return NULL;
|
| - }
|
| - ASSERT(i < threads_size_);
|
| - ThreadState* state = threads_[i];
|
| - ASSERT(state != NULL);
|
| - intptr_t last = threads_size_ - 1;
|
| - if (i != last) {
|
| - threads_[i] = threads_[last];
|
| - }
|
| - // Mark last as NULL.
|
| - threads_[last] = NULL;
|
| - // Pop.
|
| - threads_size_--;
|
| - return state;
|
| -}
|
| -
|
| -
|
| -void ThreadInterruptNoOp(const InterruptedThreadState& state, void* data) {
|
| - // NoOp.
|
| -}
|
| +};
|
|
|
|
|
| void ThreadInterrupter::ThreadMain(uword parameters) {
|
| @@ -367,11 +244,11 @@ void ThreadInterrupter::ThreadMain(uword parameters) {
|
| startup_ml.Notify();
|
| }
|
| {
|
| - MonitorLocker ml(monitor_);
|
| + MonitorLocker wait_ml(monitor_);
|
| + ThreadInterrupterVisitIsolates visitor;
|
| while (!shutdown_) {
|
| - int64_t current_time = OS::GetCurrentTimeMicros();
|
| - InterruptThreads(current_time);
|
| - ml.WaitMicros(interrupt_period_);
|
| + Isolate::VisitIsolates(&visitor);
|
| + wait_ml.WaitMicros(interrupt_period_);
|
| }
|
| }
|
| if (FLAG_trace_thread_interrupter) {
|
|
|