diff --git a/rpcs3/Emu/Cell/Modules/cellCrossController.cpp b/rpcs3/Emu/Cell/Modules/cellCrossController.cpp index 1f28328c78..af4662efb6 100644 --- a/rpcs3/Emu/Cell/Modules/cellCrossController.cpp +++ b/rpcs3/Emu/Cell/Modules/cellCrossController.cpp @@ -107,13 +107,8 @@ struct cross_controller void stop_thread() { - if (connection_thread) - { - auto& thread = *connection_thread; - thread = thread_state::aborting; - thread(); - connection_thread.reset(); - } + // Join thread + connection_thread.reset(); }; }; diff --git a/rpcs3/Emu/Cell/Modules/cellRec.cpp b/rpcs3/Emu/Cell/Modules/cellRec.cpp index 19e3279d14..5d19388f2b 100644 --- a/rpcs3/Emu/Cell/Modules/cellRec.cpp +++ b/rpcs3/Emu/Cell/Modules/cellRec.cpp @@ -828,13 +828,8 @@ void rec_info::stop_video_provider(bool flush) { cellRec.notice("Stopping video provider."); - if (video_provider_thread) - { - auto& thread = *video_provider_thread; - thread = thread_state::aborting; - thread(); - video_provider_thread.reset(); - } + // Join thread + video_provider_thread.reset(); // Flush the ringbuffer if necessary. // This should only happen if the video sink is not the encoder itself. diff --git a/rpcs3/Emu/Cell/Modules/sceNpUtil.cpp b/rpcs3/Emu/Cell/Modules/sceNpUtil.cpp index b26d604a25..b8f1341d85 100644 --- a/rpcs3/Emu/Cell/Modules/sceNpUtil.cpp +++ b/rpcs3/Emu/Cell/Modules/sceNpUtil.cpp @@ -59,13 +59,7 @@ struct sce_np_util_manager void join_thread() { - if (bandwidth_test_thread) - { - auto& thread = *bandwidth_test_thread; - thread = thread_state::aborting; - thread(); - bandwidth_test_thread.reset(); - } + bandwidth_test_thread.reset(); } }; diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 8f812b5a4c..a227480a48 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -4781,6 +4781,26 @@ bool spu_thread::process_mfc_cmd() return true; } + if (last_getllar != pc || last_getllar_lsa != ch_mfc_cmd.lsa) + { + getllar_busy_waiting_switch = umax; + getllar_spin_count = 0; + return true; + } + + // Check if LSA points to an OUT buffer on the stack from a caller - unlikely to be a loop + if (last_getllar_lsa >= SPU_LS_SIZE - 0x10000 && last_getllar_lsa > last_getllar_gpr1) + { + auto cs = dump_callstack_list(); + + if (!cs.empty() && last_getllar_lsa > cs[0].second) + { + getllar_busy_waiting_switch = umax; + getllar_spin_count = 0; + return true; + } + } + getllar_spin_count = std::min(getllar_spin_count + 1, u16{umax}); if (getllar_busy_waiting_switch == umax && getllar_spin_count == 4) @@ -4826,6 +4846,7 @@ bool spu_thread::process_mfc_cmd() last_getllar = pc; last_getllar_gpr1 = gpr[1]._u32[3]; + last_getllar_lsa = ch_mfc_cmd.lsa; if (getllar_busy_waiting_switch == 1) { diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index ce84e9e1b1..5a0d9bab31 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -802,6 +802,7 @@ public: u32 last_getllar = umax; // LS address of last GETLLAR (if matches current GETLLAR we can let the thread rest) u32 last_getllar_gpr1 = umax; u32 last_getllar_addr = umax; + u32 last_getllar_lsa = umax; u32 getllar_spin_count = 0; u32 getllar_busy_waiting_switch = umax; // umax means the test needs evaluation, otherwise it's a boolean u64 getllar_evaluate_time = 0; diff --git a/rpcs3/Emu/Io/LogitechG27.cpp b/rpcs3/Emu/Io/LogitechG27.cpp index 423c3ca145..e291117cf5 100644 --- a/rpcs3/Emu/Io/LogitechG27.cpp +++ b/rpcs3/Emu/Io/LogitechG27.cpp @@ -88,14 +88,8 @@ static void clear_sdl_joysticks(std::map>& joyst usb_device_logitech_g27::~usb_device_logitech_g27() { - // wait for the house keeping thread to finish - if (m_house_keeping_thread) - { - auto& thread = *m_house_keeping_thread; - thread = thread_state::aborting; - thread(); - m_house_keeping_thread.reset(); - } + // Wait for the house keeping thread to finish + m_house_keeping_thread.reset(); // Close sdl handles { diff --git a/rpcs3/Input/gui_pad_thread.cpp b/rpcs3/Input/gui_pad_thread.cpp index aa6e2a9d77..f0bf833a46 100644 --- a/rpcs3/Input/gui_pad_thread.cpp +++ b/rpcs3/Input/gui_pad_thread.cpp @@ -47,13 +47,8 @@ gui_pad_thread::gui_pad_thread() gui_pad_thread::~gui_pad_thread() { - if (m_thread) - { - auto& thread = *m_thread; - thread = thread_state::aborting; - thread(); - m_thread.reset(); - } + // Join thread + m_thread.reset(); #ifdef __linux__ if (m_uinput_fd != 1) diff --git a/rpcs3/Input/hid_pad_handler.cpp b/rpcs3/Input/hid_pad_handler.cpp index 291728fbc1..a972cd4fbe 100644 --- a/rpcs3/Input/hid_pad_handler.cpp +++ b/rpcs3/Input/hid_pad_handler.cpp @@ -101,12 +101,8 @@ hid_pad_handler::hid_pad_handler(pad_handler type, std::vector template hid_pad_handler::~hid_pad_handler() { - if (m_enumeration_thread) - { - auto& enumeration_thread = *m_enumeration_thread; - enumeration_thread = thread_state::aborting; - enumeration_thread(); - } + // Join thread + m_enumeration_thread.reset(); for (auto& controller : m_controllers) { diff --git a/rpcs3/Input/pad_thread.cpp b/rpcs3/Input/pad_thread.cpp index df50ec2bc4..2f4bea7b34 100644 --- a/rpcs3/Input/pad_thread.cpp +++ b/rpcs3/Input/pad_thread.cpp @@ -309,13 +309,10 @@ void pad_thread::operator()() for (auto& thread : threads) { - if (thread) - { - auto& enumeration_thread = *thread; - enumeration_thread = thread_state::aborting; - enumeration_thread(); - } + // Join thread (ordered explicitly) + thread.reset(); } + threads.clear(); input_log.notice("Pad threads stopped"); diff --git a/rpcs3/Input/raw_mouse_handler.cpp b/rpcs3/Input/raw_mouse_handler.cpp index d60dfaec0b..874eccdde6 100644 --- a/rpcs3/Input/raw_mouse_handler.cpp +++ b/rpcs3/Input/raw_mouse_handler.cpp @@ -277,13 +277,8 @@ void raw_mouse::update_values(s32 scan_code, bool pressed) raw_mouse_handler::~raw_mouse_handler() { - if (m_thread) - { - auto& thread = *m_thread; - thread = thread_state::aborting; - thread(); - m_thread.reset(); - } + // Join thread + m_thread.reset(); #ifdef _WIN32 unregister_raw_input_devices(); diff --git a/rpcs3/rpcs3qt/pad_motion_settings_dialog.cpp b/rpcs3/rpcs3qt/pad_motion_settings_dialog.cpp index 0ebdbdb7c9..433f9adb5a 100644 --- a/rpcs3/rpcs3qt/pad_motion_settings_dialog.cpp +++ b/rpcs3/rpcs3qt/pad_motion_settings_dialog.cpp @@ -231,13 +231,9 @@ pad_motion_settings_dialog::pad_motion_settings_dialog(QDialog* parent, std::sha pad_motion_settings_dialog::~pad_motion_settings_dialog() { - if (m_input_thread) - { - m_input_thread_state = input_thread_state::pausing; - auto& thread = *m_input_thread; - thread = thread_state::aborting; - thread(); - } + // Join thread + m_input_thread_state = input_thread_state::pausing; + m_input_thread.reset(); } void pad_motion_settings_dialog::change_device(int index) diff --git a/rpcs3/rpcs3qt/ps_move_tracker_dialog.cpp b/rpcs3/rpcs3qt/ps_move_tracker_dialog.cpp index 3ce46f9249..f00d66245a 100644 --- a/rpcs3/rpcs3qt/ps_move_tracker_dialog.cpp +++ b/rpcs3/rpcs3qt/ps_move_tracker_dialog.cpp @@ -269,13 +269,8 @@ ps_move_tracker_dialog::~ps_move_tracker_dialog() m_camera_handler->close_camera(); } - if (m_input_thread) - { - auto& thread = *m_input_thread; - thread = thread_state::aborting; - thread(); - m_input_thread.reset(); - } + // Join thread + m_input_thread.reset(); } void ps_move_tracker_dialog::update_color(bool update_sliders) diff --git a/rpcs3/util/media_utils.cpp b/rpcs3/util/media_utils.cpp index 73bc86ef46..d4f450ab69 100644 --- a/rpcs3/util/media_utils.cpp +++ b/rpcs3/util/media_utils.cpp @@ -827,10 +827,7 @@ namespace utils } } - auto& thread = *m_thread; - thread = thread_state::aborting; - thread(); - + // Join thread m_thread.reset(); }