|
11 | 11 |
|
12 | 12 | #include <mutex>
|
13 | 13 |
|
| 14 | +#include "lldb/Host/ProcessRunLock.h" |
14 | 15 | #include "lldb/Target/StackID.h"
|
15 | 16 | #include "lldb/lldb-private.h"
|
16 | 17 |
|
@@ -315,14 +316,6 @@ class ExecutionContext {
|
315 | 316 | ExecutionContext(const ExecutionContextRef *exe_ctx_ref,
|
316 | 317 | bool thread_and_frame_only_if_stopped = false);
|
317 | 318 |
|
318 |
| - // These two variants take in a locker, and grab the target, lock the API |
319 |
| - // mutex into locker, then fill in the rest of the shared pointers. |
320 |
| - ExecutionContext(const ExecutionContextRef &exe_ctx_ref, |
321 |
| - std::unique_lock<std::recursive_mutex> &locker) |
322 |
| - : ExecutionContext(&exe_ctx_ref, locker) {} |
323 |
| - |
324 |
| - ExecutionContext(const ExecutionContextRef *exe_ctx_ref, |
325 |
| - std::unique_lock<std::recursive_mutex> &locker); |
326 | 319 | // Create execution contexts from execution context scopes
|
327 | 320 | ExecutionContext(ExecutionContextScope *exe_scope);
|
328 | 321 | ExecutionContext(ExecutionContextScope &exe_scope);
|
@@ -566,6 +559,53 @@ class ExecutionContext {
|
566 | 559 | lldb::StackFrameSP m_frame_sp; ///< The stack frame in thread.
|
567 | 560 | };
|
568 | 561 |
|
| 562 | +/// A wrapper class representing an execution context with non-null Target |
| 563 | +/// and Process pointers, a locked API mutex and a locked ProcessRunLock. |
| 564 | +/// The locks are private by design: to unlock them, destroy the |
| 565 | +/// StoppedExecutionContext. |
| 566 | +struct StoppedExecutionContext : ExecutionContext { |
| 567 | + StoppedExecutionContext(lldb::TargetSP &target_sp, |
| 568 | + lldb::ProcessSP &process_sp, |
| 569 | + lldb::ThreadSP &thread_sp, |
| 570 | + lldb::StackFrameSP &frame_sp, |
| 571 | + std::unique_lock<std::recursive_mutex> api_lock, |
| 572 | + ProcessRunLock::ProcessRunLocker stop_locker) |
| 573 | + : m_api_lock(std::move(api_lock)), m_stop_locker(std::move(stop_locker)) { |
| 574 | + assert(target_sp); |
| 575 | + assert(process_sp); |
| 576 | + assert(m_api_lock.owns_lock()); |
| 577 | + assert(m_stop_locker.IsLocked()); |
| 578 | + SetTargetSP(target_sp); |
| 579 | + SetProcessSP(process_sp); |
| 580 | + SetThreadSP(thread_sp); |
| 581 | + SetFrameSP(frame_sp); |
| 582 | + } |
| 583 | + |
| 584 | + /// Transfers ownership of the locks from `other` to `this`, making `other` |
| 585 | + /// unusable. |
| 586 | + StoppedExecutionContext(StoppedExecutionContext &&other) |
| 587 | + : StoppedExecutionContext(other.m_target_sp, other.m_process_sp, |
| 588 | + other.m_thread_sp, other.m_frame_sp, |
| 589 | + std::move(other.m_api_lock), |
| 590 | + std::move(other.m_stop_locker)) { |
| 591 | + other.Clear(); |
| 592 | + } |
| 593 | + |
| 594 | + /// Clears this context, unlocking the ProcessRunLock and returning the |
| 595 | + /// locked API lock. Like after a move operation, this object is no longer |
| 596 | + /// usable. |
| 597 | + [[nodiscard]] std::unique_lock<std::recursive_mutex> Destroy(); |
| 598 | + |
| 599 | +private: |
| 600 | + std::unique_lock<std::recursive_mutex> m_api_lock; |
| 601 | + ProcessRunLock::ProcessRunLocker m_stop_locker; |
| 602 | +}; |
| 603 | + |
| 604 | +llvm::Expected<StoppedExecutionContext> |
| 605 | +GetStoppedExecutionContext(const ExecutionContextRef *exe_ctx_ref_ptr); |
| 606 | +llvm::Expected<StoppedExecutionContext> |
| 607 | +GetStoppedExecutionContext(const lldb::ExecutionContextRefSP &exe_ctx_ref_ptr); |
| 608 | + |
569 | 609 | } // namespace lldb_private
|
570 | 610 |
|
571 | 611 | #endif // LLDB_TARGET_EXECUTIONCONTEXT_H
|
0 commit comments