Skip to content

Instantly share code, notes, and snippets.

@LibretroAdmin
Created December 22, 2022 14:49
Show Gist options
  • Save LibretroAdmin/ed7b65f8283483a3b42fba17ac37ab8b to your computer and use it in GitHub Desktop.
Save LibretroAdmin/ed7b65f8283483a3b42fba17ac37ab8b to your computer and use it in GitHub Desktop.
diff --git a/libretro/main.cpp b/libretro/main.cpp
index 2d9bef353..033981238 100644
--- a/libretro/main.cpp
+++ b/libretro/main.cpp
@@ -53,7 +53,8 @@ static struct retro_perf_callback perf_cb;
#endif
static bool libretro_supports_option_categories = false;
-static bool init_failed = false;
+bool libretro_init = true;
+bool libretro_deinit = false;
int option_upscale_mult = 1;
int option_pad_left_deadzone = 0;
int option_pad_right_deadzone = 0;
@@ -420,27 +421,33 @@ void retro_init(void)
}
else
- init_failed = true;
+ libretro_init = false;
+
+ libretro_deinit = false;
}
void retro_deinit(void)
{
libretro_supports_option_categories = false;
-
- /* FIXME: This is a workaround that resolves crashes on close content.
- When closing the frontend, we end up with a zombie process because the
- main thread tries to call vu1Thread.Cancel() within pcsx2's destructor
- and it gets stuck waiting for a mutex that will never unlock */
- vu1Thread.WaitVU();
- //vu1Thread.Cancel();
-
- pcsx2->CleanupOnExit();
- pcsx2->OnExit();
+ libretro_init = true;
+ libretro_deinit = true;
bios_files.clear();
custom_memcard_list_slot1.clear();
custom_memcard_list_slot2.clear();
+ vu1Thread.WaitVU();
+ vu1Thread.Cancel();
+ GetMTGS().Cancel();
+
+ GetMTGS().FinishTaskInThread();
+ //CoreThread.Cancel();
+
+ //pcsx2->CleanupOnExit();
+ //pcsx2->OnExit();
+ pcsx2->Exit();
+ wxTheApp->Exit();
+
#ifdef PERF_TEST
perf_cb.perf_log();
#endif
@@ -490,8 +497,14 @@ void retro_get_system_av_info(retro_system_av_info* info)
void retro_reset(void)
{
+ vu1Thread.WaitVU();
+ vu1Thread.Cancel();
+ GetMTGS().Cancel();
+
GetMTGS().FinishTaskInThread();
GetCoreThread().ResetQuick();
+ GetCoreThread().Resume();
+
DiskControl::eject_state = false;
}
@@ -513,7 +526,6 @@ static void context_destroy(void)
static bool set_hw_render(retro_hw_context_type type)
{
-
hw_render.context_type = type;
hw_render.context_reset = context_reset;
hw_render.context_destroy = context_destroy;
@@ -614,9 +626,9 @@ read_m3u_file(const wxFileName& m3u_file)
bool retro_load_game(const struct retro_game_info* game)
{
- if (init_failed)
+ if (!libretro_init)
{
- init_failed = false;
+ libretro_init = true;
return false;
}
@@ -852,19 +864,9 @@ bool retro_load_game_special(unsigned game_type, const struct retro_game_info* i
void retro_unload_game(void)
{
- // GetMTGS().FinishTaskInThread();
- // GetMTGS().CloseGS();
- GetMTGS().FinishTaskInThread();
-
- while (pcsx2->HasPendingEvents())
- pcsx2->ProcessPendingEvents();
- GetMTGS().CloseGS();
-
- while (pcsx2->HasPendingEvents())
- pcsx2->ProcessPendingEvents();
+ context_destroy();
}
-
void retro_run(void)
{
bool updated = false;
diff --git a/pcsx2/MTGS.cpp b/pcsx2/MTGS.cpp
index cc5a7cce1..4818649b1 100644
--- a/pcsx2/MTGS.cpp
+++ b/pcsx2/MTGS.cpp
@@ -24,6 +24,10 @@
#include "MTVU.h"
#include "Elfheader.h"
+#ifdef __LIBRETRO__
+extern bool libretro_deinit;
+#endif
+
using namespace Threading;
// =====================================================================================================
@@ -423,6 +427,7 @@ void SysMtgsThread::CloseGS()
if( !m_Opened ) return;
m_Opened = false;
GSclose();
+ log_cb(RETRO_LOG_INFO, "%s\n", __func__);
#ifdef __LIBRETRO__
m_thread = {};
#endif
@@ -468,6 +473,15 @@ void SysMtgsThread::WaitGS(bool syncRegs, bool weakWait, bool isMTVU)
if (isMTVU || m_ReadPos.load(std::memory_order_relaxed) != m_WritePos.load(std::memory_order_relaxed)) {
SetEvent();
for(;;) {
+#ifdef __LIBRETRO__
+ log_cb(RETRO_LOG_INFO, "%s isrunning=%d isopen=%d\n", __func__, IsRunning(), IsOpen());
+ if (libretro_deinit || !IsRunning())
+ {
+ log_cb(RETRO_LOG_INFO, "%s BREAK isrunning=%d\n", __func__, IsRunning());
+ Cancel();
+ break;
+ }
+#endif
if (weakWait) m_mtx_RingBufferBusy2.Wait();
else m_mtx_RingBufferBusy .Wait();
if(!isMTVU && m_ReadPos.load(std::memory_order_relaxed) == m_WritePos.load(std::memory_order_relaxed)) break;
diff --git a/pcsx2/MTVU.cpp b/pcsx2/MTVU.cpp
index fe28567bf..e6a274d81 100644
--- a/pcsx2/MTVU.cpp
+++ b/pcsx2/MTVU.cpp
@@ -22,6 +22,10 @@
#include <windows.h> /* for GetExceptionInformation */
#endif
+#ifdef __LIBRETRO__
+extern bool libretro_deinit;
+#endif
+
__aligned16 VU_Thread vu1Thread(CpuVU1, VU1);
// Use this when reading read_pos from ee thread
@@ -104,6 +108,7 @@ VU_Thread::~VU_Thread()
{
try
{
+ Reset();
pxThread::Cancel();
}
DESTRUCTOR_CATCHALL
@@ -139,6 +144,7 @@ void VU_Thread::ExecuteRingBuffer()
{
for (;;)
{
+ log_cb(RETRO_LOG_INFO, "%s read=%d write=%d\n", __func__, VU_Thread_GetReadPos(), VU_Thread_GetWritePos());
semaEvent.WaitWithoutYield();
ScopedLockBool lock(mtxBusy, isBusy);
while (m_ato_read_pos.load(std::memory_order_relaxed) != VU_Thread_GetWritePos())
@@ -212,6 +218,7 @@ __ri void VU_Thread::WaitOnSize(s32 size)
{
for (;;)
{
+ log_cb(RETRO_LOG_INFO, "%s isrunning=%d\n", __func__, IsRunning());
s32 readPos = VU_Thread_GetReadPos();
if (readPos <= m_write_pos)
break; // MTVU is reading in back of write_pos
@@ -362,6 +369,16 @@ void VU_Thread::WaitVU()
{
for (;;)
{
+#ifdef __LIBRETRO__
+ log_cb(RETRO_LOG_INFO, "%s isrunning=%d\n", __func__, IsRunning());
+ if (libretro_deinit || !IsRunning() || semaEvent.Count() > VU_Thread_GetWritePos() - VU_Thread_GetReadPos())
+ {
+ log_cb(RETRO_LOG_INFO, "%s BREAK isrunning=%d\n", __func__, IsRunning());
+ //Reset();
+ Cancel();
+ break;
+ }
+#endif
if (VU_Thread_IsDone())
break;
KickStart();
diff --git a/pcsx2/System.cpp b/pcsx2/System.cpp
index ad5e9c3e0..ac934955a 100644
--- a/pcsx2/System.cpp
+++ b/pcsx2/System.cpp
@@ -253,17 +253,21 @@ void SysMainMemory::ReserveAll()
void SysMainMemory::CommitAll()
{
- vtlb_Core_Alloc();
+ log_cb(RETRO_LOG_INFO, "Allocating host memory for virtual systems...\n" );
if (m_ee.IsCommitted() && m_iop.IsCommitted() && m_vu.IsCommitted()) return;
+
m_ee.Commit();
m_iop.Commit();
m_vu.Commit();
+ vtlb_Core_Alloc();
}
void SysMainMemory::ResetAll()
{
- CommitAll();
+ log_cb(RETRO_LOG_INFO, "Resetting host memory for virtual systems...\n" );
+
+ //CommitAll();
m_ee.Reset();
m_iop.Reset();
m_vu.Reset();
@@ -273,23 +277,16 @@ void SysMainMemory::ResetAll()
void SysMainMemory::DecommitAll()
{
- if (!m_ee.IsCommitted() && !m_iop.IsCommitted() && !m_vu.IsCommitted()) return;
+ log_cb(RETRO_LOG_INFO, "%s ee=%d iop=%d vu=%d\n", __func__, m_ee.IsCommitted(), m_iop.IsCommitted(), m_vu.IsCommitted());
+ //if (!m_ee.IsCommitted() && !m_iop.IsCommitted() && !m_vu.IsCommitted()) return;
log_cb(RETRO_LOG_INFO, "Decommitting host memory for virtual systems...\n" );
- // On linux, the MTVU isn't empty and the thread still uses the m_ee/m_vu memory
- vu1Thread.WaitVU();
- // The EE thread must be stopped here command mustn't be send
- // to the ring. Let's call it an extra safety valve :)
- vu1Thread.Reset();
-
- hwShutdown();
+ //vtlb_Core_Free();
m_ee.Decommit();
m_iop.Decommit();
m_vu.Decommit();
-
- vtlb_Core_Free();
}
void SysMainMemory::ReleaseAll()
@@ -297,13 +294,20 @@ void SysMainMemory::ReleaseAll()
DecommitAll();
log_cb(RETRO_LOG_INFO, "Releasing host memory maps for virtual systems...\n" );
+
+ psxRec.Shutdown();
+ recCpu.Shutdown();
+ hwShutdown();
+
// Just to be sure... (calling order could result
// in it getting missed during Decommit).
vtlb_Core_Free();
- m_ee.Decommit();
- m_iop.Decommit();
- m_vu.Decommit();
+ //vif0Reset();
+ dVifRelease(0);
+
+ //vif1Reset();
+ dVifRelease(1);
safe_delete(Source_PageFault);
}
@@ -351,6 +355,7 @@ BaseException* SysCpuProviderPack::GetException_MicroVU1() const { return CpuPro
void SysCpuProviderPack::CleanupMess() noexcept
{
+ log_cb(RETRO_LOG_INFO, "%s\n", __func__);
try
{
psxRec.Shutdown();
@@ -364,6 +369,7 @@ void SysCpuProviderPack::CleanupMess() noexcept
SysCpuProviderPack::~SysCpuProviderPack()
{
+ log_cb(RETRO_LOG_INFO, "%s\n", __func__);
CleanupMess();
}
diff --git a/pcsx2/System/SysCoreThread.cpp b/pcsx2/System/SysCoreThread.cpp
index b52fbb1bd..7e0dbc88c 100644
--- a/pcsx2/System/SysCoreThread.cpp
+++ b/pcsx2/System/SysCoreThread.cpp
@@ -40,14 +40,18 @@ USBhandler usbHandler;
static void modules_close(void)
{
+ log_cb(RETRO_LOG_INFO, "%s GSclose isself=%d isrunning=%d isopen=%d\n", __func__, GetMTGS().IsSelf(), GetMTGS().IsRunning(), GetMTGS().IsOpen());
if( GetMTGS().IsSelf() )
{
GSclose();
}
else
{
- log_cb(RETRO_LOG_INFO, "Closing GS\n");
+ //log_cb(RETRO_LOG_INFO, "Closing GS\n");
+ //GetMTGS().WaitGS();
GetMTGS().Suspend();
+ //GetMTGS().Cancel();
+ //GetMTGS().CloseGS();
}
DoCDVDclose();
FWclose();
@@ -100,7 +104,8 @@ static void modules_init(void)
static void modules_shutdown(void)
{
- GetMTGS().Cancel(); // cancel it for speedier shutdown!
+ log_cb(RETRO_LOG_INFO, "%s\n", __func__);
+ //GetMTGS().Cancel(); // cancel it for speedier shutdown!
GSshutdown();
SPU2shutdown();
PADshutdown();
@@ -339,17 +344,20 @@ void SysCoreThread::OnResumeInThread(bool isSuspended)
// Invoked by the pthread_exit or pthread_cancel.
void SysCoreThread::OnCleanupInThread()
{
+ log_cb(RETRO_LOG_INFO, "%s\n", __func__);
m_ExecMode = ExecMode_Closing;
m_hasActiveMachine = false;
m_resetVirtualMachine = true;
R3000A::ioman::reset();
- // FIXME: temporary workaround for deadlock on exit, which actually should be a crash
- vu1Thread.WaitVU();
+ vu1Thread.Cancel();
+
modules_close();
modules_shutdown();
+ GetMTGS().Cancel();
+
_mm_setcsr(m_mxcsr_saved.bitmask);
_parent::OnCleanupInThread();
diff --git a/plugins/GS/GS.cpp b/plugins/GS/GS.cpp
index f28041201..dfce4f7c6 100644
--- a/plugins/GS/GS.cpp
+++ b/plugins/GS/GS.cpp
@@ -97,6 +97,7 @@ EXPORT_C_(int) GSinit()
EXPORT_C GSshutdown()
{
+ log_cb(RETRO_LOG_INFO, "%s\n", __func__);
delete s_gs;
s_gs = nullptr;
@@ -105,6 +106,7 @@ EXPORT_C GSshutdown()
EXPORT_C GSclose()
{
+ log_cb(RETRO_LOG_INFO, "%s\n", __func__);
if(s_gs == NULL) return;
s_gs->ResetDevice();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment