diff options
Diffstat (limited to 'lldb/source/Plugins/Process/Linux/NativeProcessLinux.h')
| -rw-r--r-- | lldb/source/Plugins/Process/Linux/NativeProcessLinux.h | 226 |
1 files changed, 222 insertions, 4 deletions
diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h index a35f0a731b7..886d077aac7 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h @@ -15,6 +15,8 @@ #include <signal.h> // C++ Includes +#include <mutex> +#include <unordered_map> #include <unordered_set> // Other libraries and framework includes @@ -33,8 +35,6 @@ namespace lldb_private { class Scalar; namespace process_linux { - class ThreadStateCoordinator; - /// @class NativeProcessLinux /// @brief Manages communication with the inferior (debugee) process. /// @@ -190,8 +190,6 @@ namespace process_linux { std::vector<MemoryRegionInfo> m_mem_region_cache; Mutex m_mem_region_cache_mutex; - std::unique_ptr<ThreadStateCoordinator> m_coordinator_up; - // List of thread ids stepping with a breakpoint with the address of // the relevan breakpoint std::map<lldb::tid_t, lldb::addr_t> m_threads_stepping_with_breakpoint; @@ -374,6 +372,226 @@ namespace process_linux { Error RequestThreadStop (const lldb::pid_t pid, const lldb::tid_t tid); + + + public: + // Typedefs. + typedef std::unordered_set<lldb::tid_t> ThreadIDSet; + + // Callback/block definitions. + typedef std::function<void (lldb::tid_t tid)> ThreadIDFunction; + typedef std::function<void (const char *format, va_list args)> LogFunction; + typedef std::function<void (const std::string &error_message)> ErrorFunction; + typedef std::function<Error (lldb::tid_t tid)> StopThreadFunction; + typedef std::function<Error (lldb::tid_t tid, bool supress_signal)> ResumeThreadFunction; + + private: + // Notify the coordinator when a thread is created and/or starting to be + // tracked. is_stopped should be true if the thread is currently stopped; + // otherwise, it should be set false if it is already running. Will + // call the error function if the thread id is already tracked. + void + NotifyThreadCreate (lldb::tid_t tid, + bool is_stopped, + const ErrorFunction &error_function); + + // Notify the coordinator when a previously-existing thread should no + // longer be tracked. The error_function will trigger if the thread + // is not being tracked. + void + NotifyThreadDeath (lldb::tid_t tid, + const ErrorFunction &error_function); + + + // This method is the main purpose of the class: triggering a deferred + // action after a given set of threads stop. The triggering_tid is the + // thread id passed to the call_after_function. The error_function will + // be fired if either the triggering tid or any of the wait_for_stop_tids + // are unknown at the time the method is processed. + void + CallAfterThreadsStop (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); + + // This method is the main purpose of the class: triggering a deferred + // action after all non-stopped threads stop. The triggering_tid is the + // thread id passed to the call_after_function. The error_function will + // be fired if the triggering tid is unknown at the time of execution. + void + CallAfterRunningThreadsStop (lldb::tid_t triggering_tid, + const StopThreadFunction &request_thread_stop_function, + const ThreadIDFunction &call_after_function, + const ErrorFunction &error_function); + + // This method is the main purpose of the class: triggering a deferred + // action after all non-stopped threads stop. The triggering_tid is the + // thread id passed to the call_after_function. The error_function will + // be fired if the triggering tid is unknown at the time of execution. + // This variant will send stop requests to all non-stopped threads except + // for any contained in skip_stop_request_tids. + void + 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); + + // Notify the thread stopped. Will trigger error at time of execution if we + // already think it is stopped. + void + NotifyThreadStop (lldb::tid_t tid, + bool initiated_by_llgs, + const ErrorFunction &error_function); + + // Request that the given thread id should have the request_thread_resume_function + // called. Will trigger the error_function if the thread is thought to be running + // already at that point. This call signals an error if the thread resume is for + // a thread that is already in a running state. + void + RequestThreadResume (lldb::tid_t tid, + const ResumeThreadFunction &request_thread_resume_function, + const ErrorFunction &error_function); + + // Request that the given thread id should have the request_thread_resume_function + // called. Will trigger the error_function if the thread is thought to be running + // already at that point. This call ignores threads that are already running and + // does not trigger an error in that case. + void + RequestThreadResumeAsNeeded (lldb::tid_t tid, + const ResumeThreadFunction &request_thread_resume_function, + const ErrorFunction &error_function); + + // Indicate the calling process did an exec and that the thread state + // should be 100% cleared. + void + ResetForExec (); + + // Enable/disable verbose logging of event processing. + void + LogEnableEventProcessing (bool enabled); + + private: + + enum class ThreadState + { + Running, + Stopped + }; + + struct ThreadContext + { + ThreadState m_state; + bool m_stop_requested = false; + ResumeThreadFunction m_request_resume_function; + }; + 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(); + + void + RequestStopOnAllRunningThreads(); + + void + RequestThreadStop (lldb::tid_t tid, ThreadContext& context); + + std::mutex m_event_mutex; // Serializes execution of ProcessEvent. XXX + + void + ThreadDidStop (lldb::tid_t tid, bool initiated_by_llgs, const ErrorFunction &error_function); + + void + DoResume(lldb::tid_t tid, ResumeThreadFunction request_thread_resume_function, + ErrorFunction error_function, bool error_when_already_running); + + void + DoCallAfterThreadsStop(PendingNotificationUP &¬ification_up); + + void + ThreadWasCreated (lldb::tid_t tid, bool is_stopped, const ErrorFunction &error_function); + + void + ThreadDidDie (lldb::tid_t tid, const ErrorFunction &error_function); + + bool + IsKnownThread(lldb::tid_t tid) const; + + void + TSCLog (const char *format, ...); + + // Member variables. + LogFunction m_log_function; + PendingNotificationUP m_pending_notification_up; + + // Maps known TIDs to ThreadContext. + TIDContextMap m_tid_map; + + bool m_log_event_processing; }; } // namespace process_linux |

