diff options
| author | Pavel Labath <labath@google.com> | 2015-05-05 15:05:50 +0000 |
|---|---|---|
| committer | Pavel Labath <labath@google.com> | 2015-05-05 15:05:50 +0000 |
| commit | 45f5cb31dcab4a956ababd123628e10fcc810d5b (patch) | |
| tree | 7afb0e321acd7a1b391d09fb056d2a838d740ed1 /lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp | |
| parent | 941b743fc9a65d73345560d1695e844a0db1d366 (diff) | |
| download | bcm5719-llvm-45f5cb31dcab4a956ababd123628e10fcc810d5b.tar.gz bcm5719-llvm-45f5cb31dcab4a956ababd123628e10fcc810d5b.zip | |
[NativeProcessLinux] Get rid of the thread state coordinator thread
Summary:
This change removes the thread state coordinator thread by making all the operations it was
performing synchronous. In order to prevent deadlock, NativeProcessLinux must now always call
m_monitor->DoOperation with the m_threads_mutex released. This is needed because HandleWait
callbacks lock the mutex (which means the monitor thread will block waiting on whoever holds the
lock). If the other thread now requests a monitor operation, it will wait for the monitor thread
do process it, creating a deadlock.
To preserve this invariant I have introduced two new Monitor commands: "begin operation block"
and "end operation block". They begin command blocks the monitor from processing waitpid
events until the corresponding end command, thereby assuring the monitor does not attempt to
acquire the mutex.
Test Plan: Run the test suite locally, verify no tests fail.
Reviewers: vharron, chaoren
Subscribers: lldb-commits
Differential Revision: http://reviews.llvm.org/D9227
llvm-svn: 236501
Diffstat (limited to 'lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp')
| -rw-r--r-- | lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp | 134 |
1 files changed, 24 insertions, 110 deletions
diff --git a/lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp b/lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp index da1c33f64fd..438c1423bf6 100644 --- a/lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp +++ b/lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp @@ -46,29 +46,6 @@ public: //===----------------------------------------------------------------------===// -class ThreadStateCoordinator::EventStopCoordinator : public ThreadStateCoordinator::EventBase -{ -public: - EventStopCoordinator (): - EventBase () - { - } - - EventLoopResult - ProcessEvent(ThreadStateCoordinator &coordinator) override - { - return eventLoopResultStop; - } - - std::string - GetDescription () override - { - return "EventStopCoordinator"; - } -}; - -//===----------------------------------------------------------------------===// - class ThreadStateCoordinator::EventCallAfterThreadsStop : public ThreadStateCoordinator::EventBase { public: @@ -588,42 +565,12 @@ private: ThreadStateCoordinator::ThreadStateCoordinator (const LogFunction &log_function) : m_log_function (log_function), - m_event_queue (), - m_queue_condition (), - m_queue_mutex (), m_tid_map (), m_log_event_processing (false) { } void -ThreadStateCoordinator::EnqueueEvent (EventBaseSP event_sp) -{ - std::lock_guard<std::mutex> lock (m_queue_mutex); - - m_event_queue.push (event_sp); - if (m_log_event_processing) - Log ("ThreadStateCoordinator::%s enqueued event: %s", __FUNCTION__, event_sp->GetDescription ().c_str ()); - - m_queue_condition.notify_one (); -} - -ThreadStateCoordinator::EventBaseSP -ThreadStateCoordinator::DequeueEventWithWait () -{ - // Wait for an event to be present. - std::unique_lock<std::mutex> lock (m_queue_mutex); - m_queue_condition.wait (lock, - [this] { return !m_event_queue.empty (); }); - - // Grab the event and pop it off the queue. - EventBaseSP event_sp = m_event_queue.front (); - m_event_queue.pop (); - - return event_sp; -} - -void ThreadStateCoordinator::SetPendingNotification (const EventBaseSP &event_sp) { assert (event_sp && "null event_sp"); @@ -653,11 +600,11 @@ ThreadStateCoordinator::CallAfterThreadsStop (const lldb::tid_t triggering_tid, const ThreadIDFunction &call_after_function, const ErrorFunction &error_function) { - EnqueueEvent (EventBaseSP (new EventCallAfterThreadsStop (triggering_tid, - wait_for_stop_tids, - request_thread_stop_function, - call_after_function, - error_function))); + ProcessEvent(EventBaseSP(new EventCallAfterThreadsStop (triggering_tid, + wait_for_stop_tids, + request_thread_stop_function, + call_after_function, + error_function))); } void @@ -666,10 +613,10 @@ ThreadStateCoordinator::CallAfterRunningThreadsStop (const lldb::tid_t triggerin const ThreadIDFunction &call_after_function, const ErrorFunction &error_function) { - EnqueueEvent (EventBaseSP (new EventCallAfterThreadsStop (triggering_tid, - request_thread_stop_function, - call_after_function, - error_function))); + ProcessEvent(EventBaseSP(new EventCallAfterThreadsStop (triggering_tid, + request_thread_stop_function, + call_after_function, + error_function))); } void @@ -679,11 +626,11 @@ ThreadStateCoordinator::CallAfterRunningThreadsStopWithSkipTIDs (lldb::tid_t tri const ThreadIDFunction &call_after_function, const ErrorFunction &error_function) { - EnqueueEvent (EventBaseSP (new EventCallAfterThreadsStop (triggering_tid, - request_thread_stop_function, - call_after_function, - skip_stop_request_tids, - error_function))); + ProcessEvent(EventBaseSP(new EventCallAfterThreadsStop (triggering_tid, + request_thread_stop_function, + call_after_function, + skip_stop_request_tids, + error_function))); } @@ -826,7 +773,7 @@ ThreadStateCoordinator::NotifyThreadStop (lldb::tid_t tid, bool initiated_by_llgs, const ErrorFunction &error_function) { - EnqueueEvent (EventBaseSP (new EventThreadStopped (tid, initiated_by_llgs, error_function))); + ProcessEvent(EventBaseSP(new EventThreadStopped (tid, initiated_by_llgs, error_function))); } void @@ -834,7 +781,7 @@ ThreadStateCoordinator::RequestThreadResume (lldb::tid_t tid, const ResumeThreadFunction &request_thread_resume_function, const ErrorFunction &error_function) { - EnqueueEvent (EventBaseSP (new EventRequestResume (tid, request_thread_resume_function, error_function, true))); + ProcessEvent(EventBaseSP(new EventRequestResume (tid, request_thread_resume_function, error_function, true))); } void @@ -842,7 +789,7 @@ ThreadStateCoordinator::RequestThreadResumeAsNeeded (lldb::tid_t tid, const ResumeThreadFunction &request_thread_resume_function, const ErrorFunction &error_function) { - EnqueueEvent (EventBaseSP (new EventRequestResume (tid, request_thread_resume_function, error_function, false))); + ProcessEvent(EventBaseSP(new EventRequestResume (tid, request_thread_resume_function, error_function, false))); } void @@ -850,56 +797,26 @@ ThreadStateCoordinator::NotifyThreadCreate (lldb::tid_t tid, bool is_stopped, const ErrorFunction &error_function) { - EnqueueEvent (EventBaseSP (new EventThreadCreate (tid, is_stopped, error_function))); + ProcessEvent(EventBaseSP(new EventThreadCreate (tid, is_stopped, error_function))); } void ThreadStateCoordinator::NotifyThreadDeath (lldb::tid_t tid, const ErrorFunction &error_function) { - EnqueueEvent (EventBaseSP (new EventThreadDeath (tid, error_function))); + ProcessEvent(EventBaseSP(new EventThreadDeath (tid, error_function))); } void ThreadStateCoordinator::ResetForExec () { - std::lock_guard<std::mutex> lock (m_queue_mutex); - - // Remove everything from the queue. This is the only - // state mutation that takes place outside the processing - // loop. - QueueType empty_queue; - m_event_queue.swap (empty_queue); - - // Do the real clear behavior on the the queue to eliminate - // the chance that processing of a dequeued earlier event is - // overlapping with the clearing of state here. Push it - // directly because we need to have this happen with the lock, - // and so far I only have this one place that needs a no-lock - // variant. - m_event_queue.push (EventBaseSP (new EventReset ())); + ProcessEvent(EventBaseSP(new EventReset())); } void -ThreadStateCoordinator::StopCoordinator () +ThreadStateCoordinator::ProcessEvent (const EventBaseSP &event_sp) { - EnqueueEvent (EventBaseSP (new EventStopCoordinator ())); -} - -ThreadStateCoordinator::EventLoopResult -ThreadStateCoordinator::ProcessNextEvent () -{ - // Dequeue the next event, synchronous. - if (m_log_event_processing) - Log ("ThreadStateCoordinator::%s about to dequeue next event in blocking mode", __FUNCTION__); - - EventBaseSP event_sp = DequeueEventWithWait(); - assert (event_sp && "event should never be null"); - if (!event_sp) - { - Log ("ThreadStateCoordinator::%s error: event_sp was null, signaling exit of event loop.", __FUNCTION__); - return eventLoopResultStop; - } + std::lock_guard<std::mutex> lock(m_event_mutex); if (m_log_event_processing) { @@ -907,15 +824,12 @@ ThreadStateCoordinator::ProcessNextEvent () } // Process the event. - const EventLoopResult result = event_sp->ProcessEvent (*this); + event_sp->ProcessEvent (*this); if (m_log_event_processing) { - Log ("ThreadStateCoordinator::%s event processing returned value %s", __FUNCTION__, - result == eventLoopResultContinue ? "eventLoopResultContinue" : "eventLoopResultStop"); + Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__); } - - return result; } void |

