summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp
diff options
context:
space:
mode:
authorPavel Labath <labath@google.com>2015-05-05 15:05:50 +0000
committerPavel Labath <labath@google.com>2015-05-05 15:05:50 +0000
commit45f5cb31dcab4a956ababd123628e10fcc810d5b (patch)
tree7afb0e321acd7a1b391d09fb056d2a838d740ed1 /lldb/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp
parent941b743fc9a65d73345560d1695e844a0db1d366 (diff)
downloadbcm5719-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.cpp134
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
OpenPOWER on IntegriCloud