[Lldb-commits] [lldb] r236576 - [ThreadStateCoordinator] Remove Event classes
Pavel Labath
labath at google.com
Wed May 6 01:23:47 PDT 2015
Author: labath
Date: Wed May 6 03:23:47 2015
New Revision: 236576
URL: http://llvm.org/viewvc/llvm-project?rev=236576&view=rev
Log:
[ThreadStateCoordinator] Remove Event classes
Summary:
This is a cleanup patch for thread state coordinator. After making processing of all events
synchronous, there is no need to have a a separate class for each event. I have moved back
processing of all events back into the TSC class. No functional change.
Test Plan: All tests continue to pass.
Reviewers: chaoren, vharron
Subscribers: lldb-commits
Differential Revision: http://reviews.llvm.org/D9254
Modified:
lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp
lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h
Modified: lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp?rev=236576&r1=236575&r2=236576&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.cpp Wed May 6 03:23:47 2015
@@ -24,618 +24,281 @@ using namespace lldb_private::process_li
//===----------------------------------------------------------------------===//
-class ThreadStateCoordinator::EventBase : public std::enable_shared_from_this<ThreadStateCoordinator::EventBase>
-{
-public:
- EventBase ()
- {
- }
-
- virtual
- ~EventBase ()
- {
- }
-
- virtual std::string
- GetDescription () = 0;
-
- // Return false if the coordinator should terminate running.
- virtual EventLoopResult
- ProcessEvent (ThreadStateCoordinator &coordinator) = 0;
-};
-
-//===----------------------------------------------------------------------===//
-
-class ThreadStateCoordinator::EventCallAfterThreadsStop : public ThreadStateCoordinator::EventBase
+void
+ThreadStateCoordinator::DoResume(
+ lldb::tid_t tid,
+ ResumeThreadFunction request_thread_resume_function,
+ ErrorFunction error_function,
+ bool error_when_already_running)
{
-public:
- EventCallAfterThreadsStop (lldb::tid_t triggering_tid,
- const ThreadIDSet &wait_for_stop_tids,
- const StopThreadFunction &request_thread_stop_function,
- const ThreadIDFunction &call_after_function,
- const ErrorFunction &error_function):
- EventBase (),
- m_triggering_tid (triggering_tid),
- m_wait_for_stop_tids (wait_for_stop_tids),
- m_original_wait_for_stop_tids (wait_for_stop_tids),
- m_request_thread_stop_function (request_thread_stop_function),
- m_call_after_function (call_after_function),
- m_error_function (error_function),
- m_request_stop_on_all_unstopped_threads (false),
- m_skip_stop_request_tids ()
- {
- }
-
- EventCallAfterThreadsStop (lldb::tid_t triggering_tid,
- const StopThreadFunction &request_thread_stop_function,
- const ThreadIDFunction &call_after_function,
- const ErrorFunction &error_function) :
- EventBase (),
- m_triggering_tid (triggering_tid),
- m_wait_for_stop_tids (),
- m_original_wait_for_stop_tids (),
- m_request_thread_stop_function (request_thread_stop_function),
- m_call_after_function (call_after_function),
- m_error_function (error_function),
- m_request_stop_on_all_unstopped_threads (true),
- m_skip_stop_request_tids ()
- {
- }
-
- EventCallAfterThreadsStop (lldb::tid_t triggering_tid,
- const StopThreadFunction &request_thread_stop_function,
- const ThreadIDFunction &call_after_function,
- const ThreadIDSet &skip_stop_request_tids,
- const ErrorFunction &error_function) :
- EventBase (),
- m_triggering_tid (triggering_tid),
- m_wait_for_stop_tids (),
- m_original_wait_for_stop_tids (),
- m_request_thread_stop_function (request_thread_stop_function),
- m_call_after_function (call_after_function),
- m_error_function (error_function),
- m_request_stop_on_all_unstopped_threads (true),
- m_skip_stop_request_tids (skip_stop_request_tids)
- {
- }
-
- lldb::tid_t GetTriggeringTID () const
- {
- return m_triggering_tid;
- }
-
- ThreadIDSet &
- GetRemainingWaitTIDs ()
- {
- return m_wait_for_stop_tids;
- }
-
- const ThreadIDSet &
- GetRemainingWaitTIDs () const
- {
- return m_wait_for_stop_tids;
- }
-
-
- const ThreadIDSet &
- GetInitialWaitTIDs () const
+ // Ensure we know about the thread.
+ auto find_it = m_tid_map.find (tid);
+ if (find_it == m_tid_map.end ())
{
- return m_original_wait_for_stop_tids;
+ // We don't know about this thread. This is an error condition.
+ std::ostringstream error_message;
+ error_message << "error: tid " << tid << " asked to resume but tid is unknown";
+ error_function (error_message.str ());
+ return;
}
-
- EventLoopResult
- ProcessEvent(ThreadStateCoordinator &coordinator) override
- {
- // Validate we know about the deferred trigger thread.
- if (!coordinator.IsKnownThread (m_triggering_tid))
- {
- // We don't know about this thread. This is an error condition.
- std::ostringstream error_message;
- error_message << "error: deferred notification tid " << m_triggering_tid << " is unknown";
- m_error_function (error_message.str ());
-
- // We bail out here.
- return eventLoopResultContinue;
- }
-
- if (m_request_stop_on_all_unstopped_threads)
- {
- RequestStopOnAllRunningThreads (coordinator);
- }
- else
- {
- if (!RequestStopOnAllSpecifiedThreads (coordinator))
- return eventLoopResultContinue;
- }
-
- if (m_wait_for_stop_tids.empty ())
- {
- // We're not waiting for any threads. Fire off the deferred signal delivery event.
- NotifyNow ();
+ auto& context = find_it->second;
+ // Tell the thread to resume if we don't already think it is running.
+ const bool is_stopped = context.m_state == ThreadState::Stopped;
+ if (!is_stopped)
+ {
+ // It's not an error, just a log, if the error_when_already_running flag is not set.
+ // This covers cases where, for instance, we're just trying to resume all threads
+ // from the user side.
+ if (!error_when_already_running)
+ {
+ Log ("ThreadStateCoordinator::%s tid %" PRIu64 " optional resume skipped since it is already running",
+ __FUNCTION__,
+ tid);
}
else
{
- // The real meat of this class: wait until all
- // the thread stops (or thread deaths) come in
- // before firing off that the triggering signal
- // arrived.
- coordinator.SetPendingNotification (shared_from_this ());
+ // Skip the resume call - we have tracked it to be running. And we unconditionally
+ // expected to resume this thread. Flag this as an error.
+ std::ostringstream error_message;
+ error_message << "error: tid " << tid << " asked to resume but we think it is already running";
+ error_function (error_message.str ());
}
- return eventLoopResultContinue;
+ // Error or not, we're done.
+ return;
}
- // Return true if still pending thread stops waiting; false if no more stops.
- // If no more pending stops, signal.
- bool
- RemoveThreadStopRequirementAndMaybeSignal (lldb::tid_t tid)
+ // Before we do the resume below, first check if we have a pending
+ // stop notification this is currently or was previously waiting for
+ // this thread to stop. This is potentially a buggy situation since
+ // we're ostensibly waiting for threads to stop before we send out the
+ // pending notification, and here we are resuming one before we send
+ // out the pending stop notification.
+ if (m_pending_notification_up)
{
- // Remove this tid if it was in it.
- m_wait_for_stop_tids.erase (tid);
-
- // Fire pending notification if no pending thread stops remain.
- if (m_wait_for_stop_tids.empty ())
+ if (m_pending_notification_up->wait_for_stop_tids.count (tid) > 0)
{
- // Fire the pending notification now.
- NotifyNow ();
- return false;
+ Log ("ThreadStateCoordinator::%s about to resume tid %" PRIu64 " per explicit request but we have a pending stop notification (tid %" PRIu64 ") that is actively waiting for this thread to stop. Valid sequence of events?", __FUNCTION__, tid, m_pending_notification_up->triggering_tid);
}
-
- // Still have pending thread stops.
- return true;
- }
-
- void
- AddThreadStopRequirement (lldb::tid_t tid)
- {
- // Add this tid.
- auto insert_result = m_wait_for_stop_tids.insert (tid);
-
- // If it was really added, send the stop request to it.
- if (insert_result.second)
- m_request_thread_stop_function (tid);
- }
-
- std::string
- GetDescription () override
- {
- std::ostringstream description;
- description << "EventCallAfterThreadsStop (triggering_tid=" << m_triggering_tid << ", request_stop_on_all_unstopped_threads=" << m_request_stop_on_all_unstopped_threads << ", skip_stop_request_tids.size()=" << m_skip_stop_request_tids.size () << ")";
- return description.str ();
- }
-
-private:
-
- void
- NotifyNow ()
- {
- m_call_after_function (m_triggering_tid);
- }
-
- bool
- RequestStopOnAllSpecifiedThreads (ThreadStateCoordinator &coordinator)
- {
- // Request a stop for all the thread stops that need to be stopped
- // and are not already known to be stopped. Keep a list of all the
- // threads from which we still need to hear a stop reply.
-
- ThreadIDSet sent_tids;
- for (auto tid : m_wait_for_stop_tids)
+ else if (m_pending_notification_up->original_wait_for_stop_tids.count (tid) > 0)
{
- // Validate we know about all tids for which we must first receive a stop before
- // triggering the deferred stop notification.
- auto find_it = coordinator.m_tid_map.find (tid);
- if (find_it == coordinator.m_tid_map.end ())
+ Log ("ThreadStateCoordinator::%s about to resume tid %" PRIu64 " per explicit request but we have a pending stop notification (tid %" PRIu64 ") that hasn't fired yet and this is one of the threads we had been waiting on (and already marked satisfied for this tid). Valid sequence of events?", __FUNCTION__, tid, m_pending_notification_up->triggering_tid);
+ for (auto tid : m_pending_notification_up->wait_for_stop_tids)
{
- // This is an error. We shouldn't be asking for waiting pids that aren't known.
- // NOTE: we may be stripping out the specification of wait tids and handle this
- // automatically, in which case this state can never occur.
- std::ostringstream error_message;
- error_message << "error: deferred notification for tid " << m_triggering_tid << " specified an unknown/untracked pending stop tid " << m_triggering_tid;
- m_error_function (error_message.str ());
-
- // Bail out here.
- return false;
- }
-
- // If the pending stop thread is currently running, we need to send it a stop request.
- auto& context = find_it->second;
- if (context.m_state == ThreadState::Running)
- {
- RequestThreadStop (tid, coordinator, context);
- sent_tids.insert (tid);
+ Log ("ThreadStateCoordinator::%s tid %" PRIu64 " deferred stop notification still waiting on tid %" PRIu64,
+ __FUNCTION__,
+ m_pending_notification_up->triggering_tid,
+ tid);
}
}
-
- // We only need to wait for the sent_tids - so swap our wait set
- // to the sent tids. The rest are already stopped and we won't
- // be receiving stop notifications for them.
- m_wait_for_stop_tids.swap (sent_tids);
-
- // Succeeded, keep running.
- return true;
}
- void
- RequestStopOnAllRunningThreads (ThreadStateCoordinator &coordinator)
+ // Request a resume. We expect this to be synchronous and the system
+ // to reflect it is running after this completes.
+ const auto error = request_thread_resume_function (tid, false);
+ if (error.Success ())
{
- // Request a stop for all the thread stops that need to be stopped
- // and are not already known to be stopped. Keep a list of all the
- // threads from which we still need to hear a stop reply.
-
- ThreadIDSet sent_tids;
- for (auto it = coordinator.m_tid_map.begin(); it != coordinator.m_tid_map.end(); ++it)
- {
- // We only care about threads not stopped.
- const bool running = it->second.m_state == ThreadState::Running;
- if (running)
- {
- const lldb::tid_t tid = it->first;
-
- // Request this thread stop if the tid stop request is not explicitly ignored.
- const bool skip_stop_request = m_skip_stop_request_tids.count (tid) > 0;
- if (!skip_stop_request)
- RequestThreadStop (tid, coordinator, it->second);
-
- // Even if we skipped sending the stop request for other reasons (like stepping),
- // we still need to wait for that stepping thread to notify completion/stop.
- sent_tids.insert (tid);
- }
- }
-
- // Set the wait list to the set of tids for which we requested stops.
- m_wait_for_stop_tids.swap (sent_tids);
+ // Now mark it is running.
+ context.m_state = ThreadState::Running;
+ context.m_request_resume_function = request_thread_resume_function;
}
-
- void
- RequestThreadStop (lldb::tid_t tid, ThreadStateCoordinator &coordinator, ThreadContext& context)
+ else
{
- const auto error = m_request_thread_stop_function (tid);
- if (error.Success ())
- {
- context.m_stop_requested = true;
- }
- else
- {
- coordinator.Log ("EventCallAfterThreadsStop::%s failed to request thread stop tid %" PRIu64 ": %s",
- __FUNCTION__, tid, error.AsCString ());
- }
+ Log ("ThreadStateCoordinator::%s failed to resume thread tid %" PRIu64 ": %s",
+ __FUNCTION__, tid, error.AsCString ());
}
- const lldb::tid_t m_triggering_tid;
- ThreadIDSet m_wait_for_stop_tids;
- const ThreadIDSet m_original_wait_for_stop_tids;
- StopThreadFunction m_request_thread_stop_function;
- ThreadIDFunction m_call_after_function;
- ErrorFunction m_error_function;
- const bool m_request_stop_on_all_unstopped_threads;
- ThreadIDSet m_skip_stop_request_tids;
-};
+ return;
+}
//===----------------------------------------------------------------------===//
-class ThreadStateCoordinator::EventReset : public ThreadStateCoordinator::EventBase
+ThreadStateCoordinator::ThreadStateCoordinator (const LogFunction &log_function) :
+ m_log_function (log_function),
+ m_tid_map (),
+ m_log_event_processing (false)
{
-public:
- EventReset ():
- EventBase ()
- {
- }
-
- EventLoopResult
- ProcessEvent(ThreadStateCoordinator &coordinator) override
- {
- coordinator.ResetNow ();
- return eventLoopResultContinue;
- }
-
- std::string
- GetDescription () override
- {
- return "EventReset";
- }
-};
-
-//===----------------------------------------------------------------------===//
+}
-class ThreadStateCoordinator::EventThreadStopped : public ThreadStateCoordinator::EventBase
+void
+ThreadStateCoordinator::CallAfterThreadsStop (const lldb::tid_t triggering_tid,
+ const ThreadIDSet &wait_for_stop_tids,
+ const StopThreadFunction &request_thread_stop_function,
+ const ThreadIDFunction &call_after_function,
+ const ErrorFunction &error_function)
{
-public:
- EventThreadStopped (lldb::tid_t tid,
- bool initiated_by_llgs,
- const ErrorFunction &error_function):
- EventBase (),
- m_tid (tid),
- m_initiated_by_llgs (initiated_by_llgs),
- m_error_function (error_function)
- {
- }
+ std::lock_guard<std::mutex> lock(m_event_mutex);
- EventLoopResult
- ProcessEvent(ThreadStateCoordinator &coordinator) override
+ if (m_log_event_processing)
{
- coordinator.ThreadDidStop (m_tid, m_initiated_by_llgs, m_error_function);
- return eventLoopResultContinue;
+ Log ("ThreadStateCoordinator::%s about to process event: (triggering_tid: %" PRIu64 ", wait_for_stop_tids.size(): %zd)",
+ __FUNCTION__, triggering_tid, wait_for_stop_tids.size());
}
- std::string
- GetDescription () override
+ DoCallAfterThreadsStop(PendingNotificationUP(new PendingNotification(
+ triggering_tid, wait_for_stop_tids, request_thread_stop_function,
+ call_after_function, error_function)));
+
+ if (m_log_event_processing)
{
- std::ostringstream description;
- description << "EventThreadStopped (tid=" << m_tid << ")";
- return description.str ();
+ Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
}
+}
-private:
-
- const lldb::tid_t m_tid;
- const bool m_initiated_by_llgs;
- ErrorFunction m_error_function;
-};
-
-//===----------------------------------------------------------------------===//
-
-class ThreadStateCoordinator::EventThreadCreate : public ThreadStateCoordinator::EventBase
+void
+ThreadStateCoordinator::CallAfterRunningThreadsStop (const lldb::tid_t triggering_tid,
+ const StopThreadFunction &request_thread_stop_function,
+ const ThreadIDFunction &call_after_function,
+ const ErrorFunction &error_function)
{
-public:
- EventThreadCreate (lldb::tid_t tid,
- bool is_stopped,
- const ErrorFunction &error_function):
- EventBase (),
- m_tid (tid),
- m_is_stopped (is_stopped),
- m_error_function (error_function)
- {
- }
+ std::lock_guard<std::mutex> lock(m_event_mutex);
- EventLoopResult
- ProcessEvent(ThreadStateCoordinator &coordinator) override
+ if (m_log_event_processing)
{
- coordinator.ThreadWasCreated (m_tid, m_is_stopped, m_error_function);
- return eventLoopResultContinue;
+ Log ("ThreadStateCoordinator::%s about to process event: (triggering_tid: %" PRIu64 ")",
+ __FUNCTION__, triggering_tid);
}
- std::string
- GetDescription () override
+ DoCallAfterThreadsStop(PendingNotificationUP(new PendingNotification(
+ triggering_tid,
+ request_thread_stop_function,
+ call_after_function,
+ error_function)));
+
+ if (m_log_event_processing)
{
- std::ostringstream description;
- description << "EventThreadCreate (tid=" << m_tid << ", " << (m_is_stopped ? "stopped" : "running") << ")";
- return description.str ();
+ Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
}
+}
-private:
-
- const lldb::tid_t m_tid;
- const bool m_is_stopped;
- ErrorFunction m_error_function;
-};
-
-//===----------------------------------------------------------------------===//
-
-class ThreadStateCoordinator::EventThreadDeath : public ThreadStateCoordinator::EventBase
+void
+ThreadStateCoordinator::CallAfterRunningThreadsStopWithSkipTIDs (lldb::tid_t triggering_tid,
+ const ThreadIDSet &skip_stop_request_tids,
+ const StopThreadFunction &request_thread_stop_function,
+ const ThreadIDFunction &call_after_function,
+ const ErrorFunction &error_function)
{
-public:
- EventThreadDeath (lldb::tid_t tid,
- const ErrorFunction &error_function):
- EventBase (),
- m_tid (tid),
- m_error_function (error_function)
- {
- }
+ std::lock_guard<std::mutex> lock(m_event_mutex);
- EventLoopResult
- ProcessEvent(ThreadStateCoordinator &coordinator) override
+ if (m_log_event_processing)
{
- coordinator.ThreadDidDie (m_tid, m_error_function);
- return eventLoopResultContinue;
+ Log ("ThreadStateCoordinator::%s about to process event: (triggering_tid: %" PRIu64 ", skip_stop_request_tids.size(): %zd)",
+ __FUNCTION__, triggering_tid, skip_stop_request_tids.size());
}
- std::string
- GetDescription () override
+ DoCallAfterThreadsStop(PendingNotificationUP(new PendingNotification(
+ triggering_tid,
+ request_thread_stop_function,
+ call_after_function,
+ skip_stop_request_tids,
+ error_function)));
+
+ if (m_log_event_processing)
{
- std::ostringstream description;
- description << "EventThreadDeath (tid=" << m_tid << ")";
- return description.str ();
+ Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
}
+}
-private:
-
- const lldb::tid_t m_tid;
- ErrorFunction m_error_function;
-};
-
-//===----------------------------------------------------------------------===//
-
-class ThreadStateCoordinator::EventRequestResume : public ThreadStateCoordinator::EventBase
+void
+ThreadStateCoordinator::SignalIfRequirementsSatisfied()
{
-public:
- EventRequestResume (lldb::tid_t tid,
- const ResumeThreadFunction &request_thread_resume_function,
- const ErrorFunction &error_function,
- bool error_when_already_running):
- EventBase (),
- m_tid (tid),
- m_request_thread_resume_function (request_thread_resume_function),
- m_error_function (error_function),
- m_error_when_already_running (error_when_already_running)
+ if (m_pending_notification_up && m_pending_notification_up->wait_for_stop_tids.empty ())
{
+ m_pending_notification_up->call_after_function(m_pending_notification_up->triggering_tid);
+ m_pending_notification_up.reset();
}
+}
- EventLoopResult
- ProcessEvent(ThreadStateCoordinator &coordinator) override
- {
- // Ensure we know about the thread.
- auto find_it = coordinator.m_tid_map.find (m_tid);
- if (find_it == coordinator.m_tid_map.end ())
- {
- // We don't know about this thread. This is an error condition.
+bool
+ThreadStateCoordinator::RequestStopOnAllSpecifiedThreads()
+{
+ // Request a stop for all the thread stops that need to be stopped
+ // and are not already known to be stopped. Keep a list of all the
+ // threads from which we still need to hear a stop reply.
+
+ ThreadIDSet sent_tids;
+ for (auto tid : m_pending_notification_up->wait_for_stop_tids)
+ {
+ // Validate we know about all tids for which we must first receive a stop before
+ // triggering the deferred stop notification.
+ auto find_it = m_tid_map.find (tid);
+ if (find_it == m_tid_map.end ())
+ {
+ // This is an error. We shouldn't be asking for waiting pids that aren't known.
+ // NOTE: we may be stripping out the specification of wait tids and handle this
+ // automatically, in which case this state can never occur.
std::ostringstream error_message;
- error_message << "error: tid " << m_tid << " asked to resume but tid is unknown";
- m_error_function (error_message.str ());
- return eventLoopResultContinue;
- }
- auto& context = find_it->second;
- // Tell the thread to resume if we don't already think it is running.
- const bool is_stopped = context.m_state == ThreadState::Stopped;
- if (!is_stopped)
- {
- // It's not an error, just a log, if the m_already_running_no_error flag is set.
- // This covers cases where, for instance, we're just trying to resume all threads
- // from the user side.
- if (!m_error_when_already_running)
- {
- coordinator.Log ("EventRequestResume::%s tid %" PRIu64 " optional resume skipped since it is already running",
- __FUNCTION__,
- m_tid);
- }
- else
- {
- // Skip the resume call - we have tracked it to be running. And we unconditionally
- // expected to resume this thread. Flag this as an error.
- std::ostringstream error_message;
- error_message << "error: tid " << m_tid << " asked to resume but we think it is already running";
- m_error_function (error_message.str ());
- }
+ error_message << "error: deferred notification for tid " << m_pending_notification_up->triggering_tid << " specified an unknown/untracked pending stop tid " << m_pending_notification_up->triggering_tid;
+ m_pending_notification_up->error_function (error_message.str ());
- // Error or not, we're done.
- return eventLoopResultContinue;
- }
-
- // Before we do the resume below, first check if we have a pending
- // stop notification this is currently or was previously waiting for
- // this thread to stop. This is potentially a buggy situation since
- // we're ostensibly waiting for threads to stop before we send out the
- // pending notification, and here we are resuming one before we send
- // out the pending stop notification.
- const EventCallAfterThreadsStop *const pending_stop_notification = coordinator.GetPendingThreadStopNotification ();
- if (pending_stop_notification)
- {
- if (pending_stop_notification->GetRemainingWaitTIDs ().count (m_tid) > 0)
- {
- coordinator.Log ("EventRequestResume::%s about to resume tid %" PRIu64 " per explicit request but we have a pending stop notification (tid %" PRIu64 ") that is actively waiting for this thread to stop. Valid sequence of events?", __FUNCTION__, m_tid, pending_stop_notification->GetTriggeringTID ());
- }
- else if (pending_stop_notification->GetInitialWaitTIDs ().count (m_tid) > 0)
- {
- coordinator.Log ("EventRequestResume::%s about to resume tid %" PRIu64 " per explicit request but we have a pending stop notification (tid %" PRIu64 ") that hasn't fired yet and this is one of the threads we had been waiting on (and already marked satisfied for this tid). Valid sequence of events?", __FUNCTION__, m_tid, pending_stop_notification->GetTriggeringTID ());
- for (auto tid : pending_stop_notification->GetRemainingWaitTIDs ())
- {
- coordinator.Log ("EventRequestResume::%s tid %" PRIu64 " deferred stop notification still waiting on tid %" PRIu64,
- __FUNCTION__,
- pending_stop_notification->GetTriggeringTID (),
- tid);
- }
- }
+ // Bail out here.
+ return false;
}
- // Request a resume. We expect this to be synchronous and the system
- // to reflect it is running after this completes.
- const auto error = m_request_thread_resume_function (m_tid, false);
- if (error.Success ())
- {
- // Now mark it is running.
- context.m_state = ThreadState::Running;
- context.m_request_resume_function = m_request_thread_resume_function;
- }
- else
+ // If the pending stop thread is currently running, we need to send it a stop request.
+ auto& context = find_it->second;
+ if (context.m_state == ThreadState::Running)
{
- coordinator.Log ("EventRequestResume::%s failed to resume thread tid %" PRIu64 ": %s",
- __FUNCTION__, m_tid, error.AsCString ());
+ RequestThreadStop (tid, context);
+ sent_tids.insert (tid);
}
-
- return eventLoopResultContinue;
}
+ // We only need to wait for the sent_tids - so swap our wait set
+ // to the sent tids. The rest are already stopped and we won't
+ // be receiving stop notifications for them.
+ m_pending_notification_up->wait_for_stop_tids.swap (sent_tids);
- std::string
- GetDescription () override
- {
- std::ostringstream description;
- description << "EventRequestResume (tid=" << m_tid << ")";
- return description.str ();
- }
-
-private:
-
- const lldb::tid_t m_tid;
- ResumeThreadFunction m_request_thread_resume_function;
- ErrorFunction m_error_function;
- const bool m_error_when_already_running;
-};
-
-//===----------------------------------------------------------------------===//
-
-ThreadStateCoordinator::ThreadStateCoordinator (const LogFunction &log_function) :
- m_log_function (log_function),
- m_tid_map (),
- m_log_event_processing (false)
-{
+ // Succeeded, keep running.
+ return true;
}
void
-ThreadStateCoordinator::SetPendingNotification (const EventBaseSP &event_sp)
+ThreadStateCoordinator::RequestStopOnAllRunningThreads()
{
- assert (event_sp && "null event_sp");
- if (!event_sp)
- return;
-
- const EventCallAfterThreadsStop *new_call_after_event = static_cast<EventCallAfterThreadsStop*> (event_sp.get ());
+ // Request a stop for all the thread stops that need to be stopped
+ // and are not already known to be stopped. Keep a list of all the
+ // threads from which we still need to hear a stop reply.
- EventCallAfterThreadsStop *const prev_call_after_event = GetPendingThreadStopNotification ();
- if (prev_call_after_event)
+ ThreadIDSet sent_tids;
+ for (auto it = m_tid_map.begin(); it != m_tid_map.end(); ++it)
{
- // Yikes - we've already got a pending signal notification in progress.
- // Log this info. We lose the pending notification here.
- Log ("ThreadStateCoordinator::%s dropping existing pending signal notification for tid %" PRIu64 ", to be replaced with signal for tid %" PRIu64,
- __FUNCTION__,
- prev_call_after_event->GetTriggeringTID (),
- new_call_after_event->GetTriggeringTID ());
- }
+ // We only care about threads not stopped.
+ const bool running = it->second.m_state == ThreadState::Running;
+ if (running)
+ {
+ const lldb::tid_t tid = it->first;
- m_pending_notification_sp = event_sp;
-}
+ // Request this thread stop if the tid stop request is not explicitly ignored.
+ const bool skip_stop_request = m_pending_notification_up->skip_stop_request_tids.count (tid) > 0;
+ if (!skip_stop_request)
+ RequestThreadStop (tid, it->second);
-void
-ThreadStateCoordinator::CallAfterThreadsStop (const lldb::tid_t triggering_tid,
- const ThreadIDSet &wait_for_stop_tids,
- const StopThreadFunction &request_thread_stop_function,
- const ThreadIDFunction &call_after_function,
- const ErrorFunction &error_function)
-{
- ProcessEvent(EventBaseSP(new EventCallAfterThreadsStop (triggering_tid,
- wait_for_stop_tids,
- request_thread_stop_function,
- call_after_function,
- error_function)));
-}
+ // Even if we skipped sending the stop request for other reasons (like stepping),
+ // we still need to wait for that stepping thread to notify completion/stop.
+ sent_tids.insert (tid);
+ }
+ }
-void
-ThreadStateCoordinator::CallAfterRunningThreadsStop (const lldb::tid_t triggering_tid,
- const StopThreadFunction &request_thread_stop_function,
- const ThreadIDFunction &call_after_function,
- const ErrorFunction &error_function)
-{
- ProcessEvent(EventBaseSP(new EventCallAfterThreadsStop (triggering_tid,
- request_thread_stop_function,
- call_after_function,
- error_function)));
+ // Set the wait list to the set of tids for which we requested stops.
+ m_pending_notification_up->wait_for_stop_tids.swap (sent_tids);
}
void
-ThreadStateCoordinator::CallAfterRunningThreadsStopWithSkipTIDs (lldb::tid_t triggering_tid,
- const ThreadIDSet &skip_stop_request_tids,
- const StopThreadFunction &request_thread_stop_function,
- const ThreadIDFunction &call_after_function,
- const ErrorFunction &error_function)
+ThreadStateCoordinator::RequestThreadStop (lldb::tid_t tid, ThreadContext& context)
{
- ProcessEvent(EventBaseSP(new EventCallAfterThreadsStop (triggering_tid,
- request_thread_stop_function,
- call_after_function,
- skip_stop_request_tids,
- error_function)));
+ const auto error = m_pending_notification_up->request_thread_stop_function (tid);
+ if (error.Success ())
+ context.m_stop_requested = true;
+ else
+ {
+ Log ("ThreadStateCoordinator::%s failed to request thread stop tid %" PRIu64 ": %s",
+ __FUNCTION__, tid, error.AsCString ());
+ }
}
void
-ThreadStateCoordinator::ThreadDidStop (lldb::tid_t tid, bool initiated_by_llgs, ErrorFunction &error_function)
+ThreadStateCoordinator::ThreadDidStop (lldb::tid_t tid, bool initiated_by_llgs, const ErrorFunction &error_function)
{
// Ensure we know about the thread.
auto find_it = m_tid_map.find (tid);
@@ -655,15 +318,10 @@ ThreadStateCoordinator::ThreadDidStop (l
context.m_stop_requested = false;
// If we have a pending notification, remove this from the set.
- EventCallAfterThreadsStop *const call_after_event = GetPendingThreadStopNotification ();
- if (call_after_event)
+ if (m_pending_notification_up)
{
- const bool pending_stops_remain = call_after_event->RemoveThreadStopRequirementAndMaybeSignal (tid);
- if (!pending_stops_remain)
- {
- // Clear the pending notification now.
- m_pending_notification_sp.reset ();
- }
+ m_pending_notification_up->wait_for_stop_tids.erase(tid);
+ SignalIfRequirementsSatisfied();
}
if (initiated_by_llgs && context.m_request_resume_function && !stop_was_requested)
@@ -685,7 +343,49 @@ ThreadStateCoordinator::ThreadDidStop (l
}
void
-ThreadStateCoordinator::ThreadWasCreated (lldb::tid_t tid, bool is_stopped, ErrorFunction &error_function)
+ThreadStateCoordinator::DoCallAfterThreadsStop(PendingNotificationUP &¬ification_up)
+{
+ // Validate we know about the deferred trigger thread.
+ if (!IsKnownThread (notification_up->triggering_tid))
+ {
+ // We don't know about this thread. This is an error condition.
+ std::ostringstream error_message;
+ error_message << "error: deferred notification tid " << notification_up->triggering_tid << " is unknown";
+ notification_up->error_function (error_message.str ());
+
+ // We bail out here.
+ return;
+ }
+
+ if (m_pending_notification_up)
+ {
+ // Yikes - we've already got a pending signal notification in progress.
+ // Log this info. We lose the pending notification here.
+ Log ("ThreadStateCoordinator::%s dropping existing pending signal notification for tid %" PRIu64 ", to be replaced with signal for tid %" PRIu64,
+ __FUNCTION__,
+ m_pending_notification_up->triggering_tid,
+ notification_up->triggering_tid);
+ }
+ m_pending_notification_up = std::move(notification_up);
+
+ if (m_pending_notification_up->request_stop_on_all_unstopped_threads)
+ RequestStopOnAllRunningThreads();
+ else
+ {
+ if (!RequestStopOnAllSpecifiedThreads())
+ return;
+ }
+
+ if (m_pending_notification_up->wait_for_stop_tids.empty ())
+ {
+ // We're not waiting for any threads. Fire off the deferred signal delivery event.
+ m_pending_notification_up->call_after_function(m_pending_notification_up->triggering_tid);
+ m_pending_notification_up.reset();
+ }
+}
+
+void
+ThreadStateCoordinator::ThreadWasCreated (lldb::tid_t tid, bool is_stopped, const ErrorFunction &error_function)
{
// Ensure we don't already know about the thread.
auto find_it = m_tid_map.find (tid);
@@ -703,17 +403,17 @@ ThreadStateCoordinator::ThreadWasCreated
ctx.m_state = (is_stopped) ? ThreadState::Stopped : ThreadState::Running;
m_tid_map[tid] = std::move(ctx);
- EventCallAfterThreadsStop *const call_after_event = GetPendingThreadStopNotification ();
- if (call_after_event && !is_stopped)
+ if (m_pending_notification_up && !is_stopped)
{
- // Tell the pending notification that we need to wait
- // for this new thread to stop.
- call_after_event->AddThreadStopRequirement (tid);
+ // We will need to wait for this new thread to stop as well before firing the
+ // notification.
+ m_pending_notification_up->wait_for_stop_tids.insert(tid);
+ m_pending_notification_up->request_thread_stop_function(tid);
}
}
void
-ThreadStateCoordinator::ThreadDidDie (lldb::tid_t tid, ErrorFunction &error_function)
+ThreadStateCoordinator::ThreadDidDie (lldb::tid_t tid, const ErrorFunction &error_function)
{
// Ensure we know about the thread.
auto find_it = m_tid_map.find (tid);
@@ -732,32 +432,14 @@ ThreadStateCoordinator::ThreadDidDie (ll
m_tid_map.erase (find_it);
// If we have a pending notification, remove this from the set.
- EventCallAfterThreadsStop *const call_after_event = GetPendingThreadStopNotification ();
- if (call_after_event)
+ if (m_pending_notification_up)
{
- const bool pending_stops_remain = call_after_event->RemoveThreadStopRequirementAndMaybeSignal (tid);
- if (!pending_stops_remain)
- {
- // Clear the pending notification now.
- m_pending_notification_sp.reset ();
- }
+ m_pending_notification_up->wait_for_stop_tids.erase(tid);
+ SignalIfRequirementsSatisfied();
}
}
void
-ThreadStateCoordinator::ResetNow ()
-{
- // Clear the pending notification if there was one.
- m_pending_notification_sp.reset ();
-
- // Clear the stop map - we no longer know anything about any thread state.
- // The caller is expected to reset thread states for all threads, and we
- // will assume anything we haven't heard about is running and requires a
- // stop.
- m_tid_map.clear ();
-}
-
-void
ThreadStateCoordinator::Log (const char *format, ...)
{
va_list args;
@@ -773,7 +455,20 @@ ThreadStateCoordinator::NotifyThreadStop
bool initiated_by_llgs,
const ErrorFunction &error_function)
{
- ProcessEvent(EventBaseSP(new EventThreadStopped (tid, initiated_by_llgs, error_function)));
+ std::lock_guard<std::mutex> lock(m_event_mutex);
+
+ if (m_log_event_processing)
+ {
+ Log ("ThreadStateCoordinator::%s about to process event: (tid: %" PRIu64 ", %sinitiated by llgs)",
+ __FUNCTION__, tid, initiated_by_llgs?"":"not ");
+ }
+
+ ThreadDidStop (tid, initiated_by_llgs, error_function);
+
+ if (m_log_event_processing)
+ {
+ Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
+ }
}
void
@@ -781,7 +476,20 @@ ThreadStateCoordinator::RequestThreadRes
const ResumeThreadFunction &request_thread_resume_function,
const ErrorFunction &error_function)
{
- ProcessEvent(EventBaseSP(new EventRequestResume (tid, request_thread_resume_function, error_function, true)));
+ std::lock_guard<std::mutex> lock(m_event_mutex);
+
+ if (m_log_event_processing)
+ {
+ Log ("ThreadStateCoordinator::%s about to process event: (tid: %" PRIu64 ")",
+ __FUNCTION__, tid);
+ }
+
+ DoResume(tid, request_thread_resume_function, error_function, true);
+
+ if (m_log_event_processing)
+ {
+ Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
+ }
}
void
@@ -789,7 +497,20 @@ ThreadStateCoordinator::RequestThreadRes
const ResumeThreadFunction &request_thread_resume_function,
const ErrorFunction &error_function)
{
- ProcessEvent(EventBaseSP(new EventRequestResume (tid, request_thread_resume_function, error_function, false)));
+ std::lock_guard<std::mutex> lock(m_event_mutex);
+
+ if (m_log_event_processing)
+ {
+ Log ("ThreadStateCoordinator::%s about to process event: (tid: %" PRIu64 ")",
+ __FUNCTION__, tid);
+ }
+
+ DoResume (tid, request_thread_resume_function, error_function, false);
+
+ if (m_log_event_processing)
+ {
+ Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
+ }
}
void
@@ -797,53 +518,71 @@ ThreadStateCoordinator::NotifyThreadCrea
bool is_stopped,
const ErrorFunction &error_function)
{
- ProcessEvent(EventBaseSP(new EventThreadCreate (tid, is_stopped, error_function)));
+ std::lock_guard<std::mutex> lock(m_event_mutex);
+
+ if (m_log_event_processing)
+ {
+ Log ("ThreadStateCoordinator::%s about to process event: (tid: %" PRIu64 ", is %sstopped)",
+ __FUNCTION__, tid, is_stopped?"":"not ");
+ }
+
+ ThreadWasCreated (tid, is_stopped, error_function);
+
+ if (m_log_event_processing)
+ {
+ Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
+ }
}
void
ThreadStateCoordinator::NotifyThreadDeath (lldb::tid_t tid,
const ErrorFunction &error_function)
{
- ProcessEvent(EventBaseSP(new EventThreadDeath (tid, error_function)));
-}
+ std::lock_guard<std::mutex> lock(m_event_mutex);
-void
-ThreadStateCoordinator::ResetForExec ()
-{
- ProcessEvent(EventBaseSP(new EventReset()));
+ if (m_log_event_processing)
+ {
+ Log ("ThreadStateCoordinator::%s about to process event: (tid: %" PRIu64 ")", __FUNCTION__, tid);
+ }
+
+ ThreadDidDie(tid, error_function);
+
+ if (m_log_event_processing)
+ {
+ Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
+ }
}
void
-ThreadStateCoordinator::ProcessEvent (const EventBaseSP &event_sp)
+ThreadStateCoordinator::ResetForExec ()
{
std::lock_guard<std::mutex> lock(m_event_mutex);
if (m_log_event_processing)
{
- Log ("ThreadStateCoordinator::%s about to process event: %s", __FUNCTION__, event_sp->GetDescription ().c_str ());
+ Log ("ThreadStateCoordinator::%s about to process event", __FUNCTION__);
}
- // Process the event.
- event_sp->ProcessEvent (*this);
+ // Clear the pending notification if there was one.
+ m_pending_notification_up.reset ();
+
+ // Clear the stop map - we no longer know anything about any thread state.
+ // The caller is expected to reset thread states for all threads, and we
+ // will assume anything we haven't heard about is running and requires a
+ // stop.
+ m_tid_map.clear ();
if (m_log_event_processing)
{
Log ("ThreadStateCoordinator::%s event processing done", __FUNCTION__);
}
}
-
void
ThreadStateCoordinator::LogEnableEventProcessing (bool enabled)
{
m_log_event_processing = enabled;
}
-ThreadStateCoordinator::EventCallAfterThreadsStop *
-ThreadStateCoordinator::GetPendingThreadStopNotification ()
-{
- return static_cast<EventCallAfterThreadsStop*> (m_pending_notification_sp.get ());
-}
-
bool
ThreadStateCoordinator::IsKnownThread (lldb::tid_t tid) const
{
Modified: lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h?rev=236576&r1=236575&r2=236576&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ThreadStateCoordinator.h Wed May 6 03:23:47 2015
@@ -29,12 +29,6 @@ namespace process_linux {
// Typedefs.
typedef std::unordered_set<lldb::tid_t> ThreadIDSet;
- enum EventLoopResult
- {
- eventLoopResultContinue,
- eventLoopResultStop
- };
-
// Callback/block definitions.
typedef std::function<void (lldb::tid_t tid)> ThreadIDFunction;
typedef std::function<void (const char *format, va_list args)> LogFunction;
@@ -133,19 +127,6 @@ namespace process_linux {
private:
- // Typedefs.
- class EventBase;
-
- class EventCallAfterThreadsStop;
- class EventThreadStopped;
- class EventThreadCreate;
- class EventThreadDeath;
- class EventRequestResume;
-
- class EventReset;
-
- typedef std::shared_ptr<EventBase> EventBaseSP;
-
enum class ThreadState
{
Running,
@@ -160,26 +141,95 @@ namespace process_linux {
};
typedef std::unordered_map<lldb::tid_t, ThreadContext> TIDContextMap;
+ struct PendingNotification
+ {
+ PendingNotification (lldb::tid_t triggering_tid,
+ const ThreadIDSet &wait_for_stop_tids,
+ const StopThreadFunction &request_thread_stop_function,
+ const ThreadIDFunction &call_after_function,
+ const ErrorFunction &error_function):
+ triggering_tid (triggering_tid),
+ wait_for_stop_tids (wait_for_stop_tids),
+ original_wait_for_stop_tids (wait_for_stop_tids),
+ request_thread_stop_function (request_thread_stop_function),
+ call_after_function (call_after_function),
+ error_function (error_function),
+ request_stop_on_all_unstopped_threads (false),
+ skip_stop_request_tids ()
+ {
+ }
+
+ PendingNotification (lldb::tid_t triggering_tid,
+ const StopThreadFunction &request_thread_stop_function,
+ const ThreadIDFunction &call_after_function,
+ const ErrorFunction &error_function) :
+ triggering_tid (triggering_tid),
+ wait_for_stop_tids (),
+ original_wait_for_stop_tids (),
+ request_thread_stop_function (request_thread_stop_function),
+ call_after_function (call_after_function),
+ error_function (error_function),
+ request_stop_on_all_unstopped_threads (true),
+ skip_stop_request_tids ()
+ {
+ }
+
+ PendingNotification (lldb::tid_t triggering_tid,
+ const StopThreadFunction &request_thread_stop_function,
+ const ThreadIDFunction &call_after_function,
+ const ThreadIDSet &skip_stop_request_tids,
+ const ErrorFunction &error_function) :
+ triggering_tid (triggering_tid),
+ wait_for_stop_tids (),
+ original_wait_for_stop_tids (),
+ request_thread_stop_function (request_thread_stop_function),
+ call_after_function (call_after_function),
+ error_function (error_function),
+ request_stop_on_all_unstopped_threads (true),
+ skip_stop_request_tids (skip_stop_request_tids)
+ {
+ }
+
+ const lldb::tid_t triggering_tid;
+ ThreadIDSet wait_for_stop_tids;
+ const ThreadIDSet original_wait_for_stop_tids;
+ StopThreadFunction request_thread_stop_function;
+ ThreadIDFunction call_after_function;
+ ErrorFunction error_function;
+ const bool request_stop_on_all_unstopped_threads;
+ ThreadIDSet skip_stop_request_tids;
+ };
+ typedef std::unique_ptr<PendingNotification> PendingNotificationUP;
+
+ // Fire pending notification if no pending thread stops remain.
+ void SignalIfRequirementsSatisfied();
+
+ bool
+ RequestStopOnAllSpecifiedThreads();
- std::mutex m_event_mutex; // Serializes execution of ProcessEvent.
+ void
+ RequestStopOnAllRunningThreads();
void
- ProcessEvent (const EventBaseSP &event_sp);
+ RequestThreadStop (lldb::tid_t tid, ThreadContext& context);
+
+ std::mutex m_event_mutex; // Serializes execution of TSC operations.
void
- SetPendingNotification (const EventBaseSP &event_sp);
+ ThreadDidStop (lldb::tid_t tid, bool initiated_by_llgs, const ErrorFunction &error_function);
void
- ThreadDidStop (lldb::tid_t tid, bool initiated_by_llgs, ErrorFunction &error_function);
+ DoResume(lldb::tid_t tid, ResumeThreadFunction request_thread_resume_function,
+ ErrorFunction error_function, bool error_when_already_running);
void
- ThreadWasCreated (lldb::tid_t tid, bool is_stopped, ErrorFunction &error_function);
+ DoCallAfterThreadsStop(PendingNotificationUP &¬ification_up);
void
- ThreadDidDie (lldb::tid_t tid, ErrorFunction &error_function);
+ ThreadWasCreated (lldb::tid_t tid, bool is_stopped, const ErrorFunction &error_function);
void
- ResetNow ();
+ ThreadDidDie (lldb::tid_t tid, const ErrorFunction &error_function);
bool
IsKnownThread(lldb::tid_t tid) const;
@@ -187,13 +237,9 @@ namespace process_linux {
void
Log (const char *format, ...);
- EventCallAfterThreadsStop *
- GetPendingThreadStopNotification ();
-
// Member variables.
LogFunction m_log_function;
-
- EventBaseSP m_pending_notification_sp;
+ PendingNotificationUP m_pending_notification_up;
// Maps known TIDs to ThreadContext.
TIDContextMap m_tid_map;
More information about the lldb-commits
mailing list