rpcsx/rpcs3/rpcs3qt/debugger_frame.h
Elad 575a245f8d
IDM: Implement lock-free smart pointers (#16403)
Replaces `std::shared_pointer` with `stx::atomic_ptr` and `stx::shared_ptr`.

Notes to programmers:

* This pr kills the use of `dynamic_cast`, `std::dynamic_pointer_cast` and `std::weak_ptr` on IDM objects, possible replacement is to save the object ID on the base object, then use idm::check/get_unlocked to the destination type via the saved ID which may be null. Null pointer check is how you can tell type mismatch (as dynamic cast) or object destruction (as weak_ptr locking).
* Double-inheritance on IDM objects should be used with care, `stx::shared_ptr` does not support constant-evaluated pointer offsetting to parent/child type.
* `idm::check/get_unlocked` can now be used anywhere.

Misc fixes:
* Fixes some segfaults with RPCN with interaction with IDM.
* Fix deadlocks in access violation handler due locking recursion.
* Fixes race condition in process exit-spawn on memory containers read.
* Fix bug that theoretically can prevent RPCS3 from booting - fix `id_manager::typeinfo` comparison to compare members instead of `memcmp` which can fail spuriously on padding bytes.
* Ensure all IDM inherited types of base, either has `id_base` or `id_type` defined locally, this allows to make getters such as `idm::get_unlocked<lv2_socket, lv2_socket_raw>()` which were broken before. (requires save-states invalidation)
* Removes broken operator[] overload of `stx::shared_ptr` and `stx::single_ptr` for non-array types.
2024-12-22 20:59:48 +02:00

145 lines
3.7 KiB
C++

#pragma once
#include "util/types.hpp"
#include "util/shared_ptr.hpp"
#include "custom_dock_widget.h"
#include <QSplitter>
#include <QPlainTextEdit>
#include <QPushButton>
#include <QComboBox>
#include <memory>
#include <vector>
#include <any>
#include <functional>
class CPUDisAsm;
class cpu_thread;
class gui_settings;
class debugger_list;
class breakpoint_list;
class breakpoint_handler;
class call_stack_list;
namespace rsx
{
class thread;
}
namespace utils
{
class shm;
}
enum class system_state : u32;
class instruction_editor_dialog;
class register_editor_dialog;
class debugger_frame : public custom_dock_widget
{
Q_OBJECT
const QString NoThreadString = tr("No Thread");
const QString RunString = tr("Run");
const QString PauseString = tr("Pause");
debugger_list* m_debugger_list;
QSplitter* m_right_splitter;
QFont m_mono;
QPlainTextEdit* m_misc_state;
QPlainTextEdit* m_regs;
QPushButton* m_go_to_addr;
QPushButton* m_go_to_pc;
QPushButton* m_btn_step;
QPushButton* m_btn_step_over;
QPushButton* m_btn_run;
QComboBox* m_choice_units;
QTimer* m_update;
QSplitter* m_splitter;
u64 m_threads_created = -1;
u64 m_threads_deleted = -1;
system_state m_emu_state{};
u64 m_emulation_id{};
u32 m_last_pc = -1;
std::vector<char> m_last_query_state;
std::string m_last_reg_state;
std::any m_dump_reg_func_data;
std::vector<std::function<cpu_thread*()>> m_threads_info;
u32 m_last_step_over_breakpoint = -1;
u64 m_ui_update_ctr = 0;
u64 m_ui_fast_update_permission_deadline = 0;
bool m_thread_list_pending_update = false;
std::shared_ptr<CPUDisAsm> m_disasm; // Only shared to allow base/derived functionality
shared_ptr<cpu_thread> m_cpu;
rsx::thread* m_rsx = nullptr;
std::shared_ptr<utils::shm> m_spu_disasm_memory;
u32 m_spu_disasm_origin_eal = 0;
u32 m_spu_disasm_pc = 0;
bool m_is_spu_disasm_mode = false;
breakpoint_list* m_breakpoint_list;
breakpoint_handler* m_ppu_breakpoint_handler;
call_stack_list* m_call_stack_list;
instruction_editor_dialog* m_inst_editor = nullptr;
register_editor_dialog* m_reg_editor = nullptr;
QDialog* m_goto_dialog = nullptr;
QDialog* m_spu_disasm_dialog = nullptr;
std::shared_ptr<gui_settings> m_gui_settings;
cpu_thread* get_cpu();
std::function<cpu_thread*()> make_check_cpu(cpu_thread* cpu, bool unlocked = false);
void open_breakpoints_settings();
public:
explicit debugger_frame(std::shared_ptr<gui_settings> settings, QWidget *parent = nullptr);
void SaveSettings() const;
void ChangeColors() const;
void UpdateUI();
void UpdateUnitList();
void DoUpdate();
void WritePanels();
void EnableButtons(bool enable);
void ShowGotoAddressDialog();
void PerformGoToRequest(const QString& text_argument);
void PerformGoToThreadRequest(const QString& text_argument);
void PerformAddBreakpointRequest(u32 addr);
u64 EvaluateExpression(const QString& expression);
void ClearBreakpoints() const; // Fallthrough method into breakpoint_list.
void ClearCallStack();
/** Needed so key press events work when other objects are selected in debugger_frame. */
bool eventFilter(QObject* object, QEvent* event) override;
protected:
/** Override inherited method from Qt to allow signalling when close happened.*/
void closeEvent(QCloseEvent* event) override;
void showEvent(QShowEvent* event) override;
void hideEvent(QHideEvent* event) override;
void keyPressEvent(QKeyEvent* event) override;
Q_SIGNALS:
void DebugFrameClosed();
void CallStackUpdateRequested(const std::vector<std::pair<u32, u32>>& call_stack);
public Q_SLOTS:
void DoStep(bool step_over = false);
private Q_SLOTS:
void OnSelectUnit();
void OnSelectSPUDisassembler();
void ShowPC(bool user_requested = false);
void EnableUpdateTimer(bool enable) const;
void RunBtnPress();
};
Q_DECLARE_METATYPE(u32)