Fixed mem leak caused by not releasing pad & wiimote plugin when shutdown

Fixed main frame crash after shutdown

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4755 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
ayuanx 2009-12-30 14:37:12 +00:00
parent 97779ea295
commit 151ff28ab7
10 changed files with 71 additions and 96 deletions

View File

@ -213,19 +213,15 @@ void Stop() // - Hammertime!
PowerPC::Stop(); PowerPC::Stop();
CCPU::StepOpcode(); // Kick it if it's waiting (code stepping wait loop) CCPU::StepOpcode(); // Kick it if it's waiting (code stepping wait loop)
// Wait until the CPU finishes exiting the main run loop
cpuRunloopQuit.Wait();
cpuRunloopQuit.Shutdown();
// At this point, we must be out of the CPU:s runloop.
// Stop audio thread.
CPluginManager::GetInstance().GetDSP()->DSP_StopSoundStream();
// If dual core mode, the CPU thread should immediately exit here. // If dual core mode, the CPU thread should immediately exit here.
if (_CoreParameter.bCPUThread) { if (_CoreParameter.bCPUThread) {
NOTICE_LOG(CONSOLE, "%s", StopMessage(true, "Wait for Video Loop to exit ...").c_str()); NOTICE_LOG(CONSOLE, "%s", StopMessage(true, "Wait for Video Loop to exit ...").c_str());
CPluginManager::GetInstance().GetVideo()->Video_ExitLoop(); CPluginManager::GetInstance().GetVideo()->Video_ExitLoop();
} }
// Wait until the CPU finishes exiting the main run loop
cpuRunloopQuit.Wait();
cpuRunloopQuit.Shutdown();
// At this point, we must be out of the CPU:s runloop.
// Video_EnterLoop() should now exit so that EmuThread() will continue concurrently with the rest // Video_EnterLoop() should now exit so that EmuThread() will continue concurrently with the rest
// of the commands in this function. We no longer rely on Postmessage. // of the commands in this function. We no longer rely on Postmessage.
@ -296,7 +292,6 @@ THREAD_RETURN CpuThread(void *pArg)
// Enter CPU run loop. When we leave it - we are done. // Enter CPU run loop. When we leave it - we are done.
CCPU::Run(); CCPU::Run();
cpuRunloopQuit.Set();
return 0; return 0;
} }
@ -370,29 +365,12 @@ THREAD_RETURN EmuThread(void *pArg)
Plugins.GetDSP()->Initialize((void *)&dspInit); Plugins.GetDSP()->Initialize((void *)&dspInit);
// Load and Init PadPlugin
for (int i = 0; i < MAXPADS; i++)
{
SPADInitialize PADInitialize; SPADInitialize PADInitialize;
PADInitialize.hWnd = g_pWindowHandle; PADInitialize.hWnd = g_pWindowHandle;
PADInitialize.pLog = Callback_PADLog; PADInitialize.pLog = Callback_PADLog;
PADInitialize.padNumber = i;
// This is may be needed to avoid a SDL problem // This is may be needed to avoid a SDL problem
//Plugins.FreeWiimote(); //Plugins.FreeWiimote();
// Check if we should init the plugin Plugins.GetPad(0)->Initialize(&PADInitialize);
if (Plugins.OkayToInitPlugin(i))
{
Plugins.GetPad(i)->Initialize(&PADInitialize);
// Check if joypad open failed, in that case try again
if (PADInitialize.padNumber == -1)
{
Plugins.GetPad(i)->Shutdown();
Plugins.FreePad(i);
Plugins.GetPad(i)->Initialize(&PADInitialize);
}
}
}
// Load and Init WiimotePlugin - only if we are booting in wii mode // Load and Init WiimotePlugin - only if we are booting in wii mode
if (_CoreParameter.bWii) if (_CoreParameter.bWii)
@ -459,7 +437,6 @@ THREAD_RETURN EmuThread(void *pArg)
// then we lose the powerdown check. ... unless powerdown sends a message :P // then we lose the powerdown check. ... unless powerdown sends a message :P
while (PowerPC::GetState() != PowerPC::CPU_POWERDOWN) while (PowerPC::GetState() != PowerPC::CPU_POWERDOWN)
{ {
Host_UpdateMainFrame();
if (Callback_PeekMessages) if (Callback_PeekMessages)
Callback_PeekMessages(); Callback_PeekMessages();
Common::SleepCurrentThread(20); Common::SleepCurrentThread(20);
@ -507,6 +484,8 @@ THREAD_RETURN EmuThread(void *pArg)
// We have now exited the Video Loop and will shut down // We have now exited the Video Loop and will shut down
g_bHwInit = false; g_bHwInit = false;
// Stop audio thread.
Plugins.GetDSP()->DSP_StopSoundStream();
WARN_LOG(CONSOLE, "%s", StopMessage(false, "Shutting down plugins").c_str()); WARN_LOG(CONSOLE, "%s", StopMessage(false, "Shutting down plugins").c_str());
Plugins.ShutdownVideoPlugin(); Plugins.ShutdownVideoPlugin();
@ -521,8 +500,7 @@ THREAD_RETURN EmuThread(void *pArg)
NOTICE_LOG(CONSOLE, "Stop [Main Thread]\t\t---- Shutdown complete ----"); NOTICE_LOG(CONSOLE, "Stop [Main Thread]\t\t---- Shutdown complete ----");
g_bStopping = false; g_bStopping = false;
cpuRunloopQuit.Set();
Host_UpdateMainFrame();
return 0; return 0;
} }

View File

@ -25,7 +25,7 @@
#include "IniFile.h" #include "IniFile.h"
#include <string> #include <string>
#define MAXPADS 4 #define MAXPADS 1
#define MAXWIIMOTES 1 #define MAXWIIMOTES 1
struct SCoreStartupParameter struct SCoreStartupParameter

View File

@ -144,7 +144,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* _pBuffer, int _iLength)
DEBUG_LOG(AMBASEBOARDDEBUG, "GC-AM: CMD 10, %02x (READ STATUS&SWITCHES)", ptr(1)); DEBUG_LOG(AMBASEBOARDDEBUG, "GC-AM: CMD 10, %02x (READ STATUS&SWITCHES)", ptr(1));
SPADStatus PadStatus; SPADStatus PadStatus;
memset(&PadStatus, 0 ,sizeof(PadStatus)); memset(&PadStatus, 0 ,sizeof(PadStatus));
CPluginManager::GetInstance().GetPad(ISIDevice::m_iDeviceNumber) CPluginManager::GetInstance().GetPad(0)
->PAD_GetStatus(ISIDevice::m_iDeviceNumber, &PadStatus); ->PAD_GetStatus(ISIDevice::m_iDeviceNumber, &PadStatus);
res[resp++] = 0x10; res[resp++] = 0x10;
res[resp++] = 0x2; res[resp++] = 0x2;
@ -312,7 +312,7 @@ int CSIDevice_AMBaseboard::RunBuffer(u8* _pBuffer, int _iLength)
for (i=0; i<nr_players; ++i) for (i=0; i<nr_players; ++i)
{ {
SPADStatus PadStatus; SPADStatus PadStatus;
CPluginManager::GetInstance().GetPad(i) CPluginManager::GetInstance().GetPad(0)
->PAD_GetStatus(i, &PadStatus); ->PAD_GetStatus(i, &PadStatus);
unsigned char player_data[2] = {0,0}; unsigned char player_data[2] = {0,0};
if (PadStatus.button & PAD_BUTTON_START) if (PadStatus.button & PAD_BUTTON_START)

View File

@ -128,7 +128,7 @@ bool CSIDevice_GCController::GetData(u32& _Hi, u32& _Low)
{ {
SPADStatus PadStatus; SPADStatus PadStatus;
memset(&PadStatus, 0, sizeof(PadStatus)); memset(&PadStatus, 0, sizeof(PadStatus));
Common::PluginPAD* pad = CPluginManager::GetInstance().GetPad(ISIDevice::m_iDeviceNumber); Common::PluginPAD* pad = CPluginManager::GetInstance().GetPad(0);
pad->PAD_GetStatus(ISIDevice::m_iDeviceNumber, &PadStatus); pad->PAD_GetStatus(ISIDevice::m_iDeviceNumber, &PadStatus);
#if defined(HAVE_SFML) && HAVE_SFML #if defined(HAVE_SFML) && HAVE_SFML
@ -257,7 +257,7 @@ bool CSIDevice_GCController::GetData(u32& _Hi, u32& _Low)
// SendCommand // SendCommand
void CSIDevice_GCController::SendCommand(u32 _Cmd, u8 _Poll) void CSIDevice_GCController::SendCommand(u32 _Cmd, u8 _Poll)
{ {
Common::PluginPAD* pad = CPluginManager::GetInstance().GetPad(ISIDevice::m_iDeviceNumber); Common::PluginPAD* pad = CPluginManager::GetInstance().GetPad(0);
UCommand command(_Cmd); UCommand command(_Cmd);
switch (command.Command) switch (command.Command)

View File

@ -76,17 +76,21 @@ CPluginManager::~CPluginManager()
for (int i = 0; i < MAXPADS; i++) for (int i = 0; i < MAXPADS; i++)
{ {
if (m_pad[i] && (OkayToInitPlugin(i) == -1)) if (m_pad[i])
{ {
INFO_LOG(CONSOLE, "Delete: %i\n", i);
delete m_pad[i]; delete m_pad[i];
}
m_pad[i] = NULL; m_pad[i] = NULL;
} }
}
for (int i = 0; i < MAXWIIMOTES; i++) for (int i = 0; i < MAXWIIMOTES; i++)
{
if (m_wiimote[i]) if (m_wiimote[i])
{
delete m_wiimote[i]; delete m_wiimote[i];
m_wiimote[i] = NULL;
}
}
delete m_video; delete m_video;
} }
@ -139,15 +143,18 @@ bool CPluginManager::InitPlugins()
} }
// Init wiimote // Init wiimote
if (m_params->bWii) { if (m_params->bWii)
for (int i = 0; i < MAXWIIMOTES; i++) { {
for (int i = 0; i < MAXWIIMOTES; i++)
{
if (!m_params->m_strWiimotePlugin[i].empty()) if (!m_params->m_strWiimotePlugin[i].empty())
GetWiimote(i); GetWiimote(i);
if (m_wiimote[i] != NULL) if (m_wiimote[i] != NULL)
wiimote = true; wiimote = true;
} }
if (!wiimote) { if (!wiimote)
{
PanicAlert("Can't init any Wiimote Plugins"); PanicAlert("Can't init any Wiimote Plugins");
return false; return false;
} }
@ -161,13 +168,13 @@ bool CPluginManager::InitPlugins()
// for an explanation about the current LoadLibrary() and FreeLibrary() behavior. // for an explanation about the current LoadLibrary() and FreeLibrary() behavior.
void CPluginManager::ShutdownPlugins() void CPluginManager::ShutdownPlugins()
{ {
for (int i = 0; i < MAXPADS; i++) { for (int i = 0; i < MAXPADS; i++)
{
if (m_pad[i]) if (m_pad[i])
{ {
m_pad[i]->Shutdown(); m_pad[i]->Shutdown();
//delete m_pad[i]; FreePad(i);
} }
//m_pad[i] = NULL;
} }
for (int i = 0; i < MAXWIIMOTES; i++) for (int i = 0; i < MAXWIIMOTES; i++)
@ -175,9 +182,8 @@ void CPluginManager::ShutdownPlugins()
if (m_wiimote[i]) if (m_wiimote[i])
{ {
m_wiimote[i]->Shutdown(); m_wiimote[i]->Shutdown();
//delete m_wiimote[i]; FreeWiimote(i);
} }
//m_wiimote[i] = NULL;
} }
if (m_dsp) if (m_dsp)
@ -224,7 +230,9 @@ CPluginInfo::CPluginInfo(const char *_rFilename)
PanicAlert("Could not get info about plugin %s", _rFilename); PanicAlert("Could not get info about plugin %s", _rFilename);
// We are now done with this plugin and will call FreeLibrary() // We are now done with this plugin and will call FreeLibrary()
delete plugin; delete plugin;
} else { }
else
{
WARN_LOG(CONSOLE, "PluginInfo: %s is not a valid Dolphin plugin. Ignoring.", _rFilename); WARN_LOG(CONSOLE, "PluginInfo: %s is not a valid Dolphin plugin. Ignoring.", _rFilename);
} }
} }
@ -308,19 +316,6 @@ void *CPluginManager::LoadPlugin(const char *_rFilename, int Number)
return plugin; return plugin;
} }
/* Check if the plugin has already been initialized. If so, return the Id of
the duplicate pad so we can point the new m_pad[] to that */
int CPluginManager::OkayToInitPlugin(int Plugin)
{
// Compare it to the earlier plugins
for (int i = 0; i < Plugin; i++)
if (m_params->m_strPadPlugin[Plugin] == m_params->m_strPadPlugin[i])
return i;
// No there is no duplicate plugin
return -1;
}
PLUGIN_GLOBALS* CPluginManager::GetGlobals() PLUGIN_GLOBALS* CPluginManager::GetGlobals()
{ {
return m_PluginGlobals; return m_PluginGlobals;
@ -386,15 +381,8 @@ Common::PluginPAD *CPluginManager::GetPad(int controller)
if (m_pad[controller]->GetFilename() == m_params->m_strPadPlugin[controller]) if (m_pad[controller]->GetFilename() == m_params->m_strPadPlugin[controller])
return m_pad[controller]; return m_pad[controller];
// Else do this // Else load a new plugin
if (OkayToInitPlugin(controller) == -1) { m_pad[controller] = (Common::PluginPAD*)LoadPlugin(m_params->m_strPadPlugin[controller].c_str());
m_pad[controller] = (Common::PluginPAD*)LoadPlugin(m_params->m_strPadPlugin[controller].c_str(), controller);
INFO_LOG(CONSOLE, "LoadPlugin: %i", controller);
}
else {
INFO_LOG(CONSOLE, "Pointed: %i to %i", controller, OkayToInitPlugin(controller));
m_pad[controller] = m_pad[OkayToInitPlugin(controller)];
}
return m_pad[controller]; return m_pad[controller];
} }
@ -458,7 +446,8 @@ void CPluginManager::FreeDSP()
void CPluginManager::FreePad(u32 Pad) void CPluginManager::FreePad(u32 Pad)
{ {
if (Pad < MAXPADS) { if (Pad < MAXPADS)
{
delete m_pad[Pad]; delete m_pad[Pad];
m_pad[Pad] = NULL; m_pad[Pad] = NULL;
} }

View File

@ -60,7 +60,6 @@ public:
bool InitPlugins(); bool InitPlugins();
void ShutdownPlugins(); void ShutdownPlugins();
void ShutdownVideoPlugin(); void ShutdownVideoPlugin();
int OkayToInitPlugin(int Plugin);
void ScanForPlugins(); void ScanForPlugins();
void OpenConfig(void* _Parent, const char *_rFilename, PLUGIN_TYPE Type); void OpenConfig(void* _Parent, const char *_rFilename, PLUGIN_TYPE Type);
void OpenDebug(void* _Parent, const char *_rFilename, PLUGIN_TYPE Type, bool Show); void OpenDebug(void* _Parent, const char *_rFilename, PLUGIN_TYPE Type, bool Show);

View File

@ -133,11 +133,6 @@ inline void WriteHigh(volatile u32& _reg, u16 highbits) {Common::AtomicStore(_re
inline u16 ReadLow (u32 _reg) {return (u16)(_reg & 0xFFFF);} inline u16 ReadLow (u32 _reg) {return (u16)(_reg & 0xFFFF);}
inline u16 ReadHigh (u32 _reg) {return (u16)(_reg >> 16);} inline u16 ReadHigh (u32 _reg) {return (u16)(_reg >> 16);}
void UpdateInterrupts_Wrapper(u64 userdata, int cyclesLate)
{
UpdateInterrupts();
}
void Init() void Init()
{ {
m_CPStatusReg.Hex = 0; m_CPStatusReg.Hex = 0;
@ -161,7 +156,7 @@ void Init()
s_fifoIdleEvent.Init(); s_fifoIdleEvent.Init();
et_UpdateInterrupts = g_VideoInitialize.pRegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper); // et_UpdateInterrupts = g_VideoInitialize.pRegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper);
} }
void Shutdown() void Shutdown()
@ -187,7 +182,7 @@ void Read16(u16& _rReturnValue, const u32 _Address)
m_CPStatusReg.ReadIdle = fifo.CPReadIdle; // This seems not necessary though m_CPStatusReg.ReadIdle = fifo.CPReadIdle; // This seems not necessary though
m_CPStatusReg.Breakpoint = fifo.bFF_Breakpoint; m_CPStatusReg.Breakpoint = fifo.bFF_Breakpoint;
// Clear on Read // Clear on Read
g_VideoInitialize.pSetInterrupt(INT_CAUSE_CP, false); UpdateInterrupts(false);
_rReturnValue = m_CPStatusReg.Hex; _rReturnValue = m_CPStatusReg.Hex;
@ -358,14 +353,22 @@ void Write16(const u16 _Value, const u32 _Address)
{ {
// Instant Breakpoint and Interrupt, since we haven't implemented accurate BP on dual core // Instant Breakpoint and Interrupt, since we haven't implemented accurate BP on dual core
// Most likely the Read thread has already exceeded BP here, but it seems we are still cool // Most likely the Read thread has already exceeded BP here, but it seems we are still cool
Common::AtomicStore(fifo.bFF_Breakpoint, tmpCtrl.BPEnable && tmpCtrl.CPIntEnable && tmpCtrl.GPReadEnable); if (tmpCtrl.BPEnable && tmpCtrl.CPIntEnable && tmpCtrl.GPReadEnable && tmpCtrl.GPLinkEnable)
UpdateInterrupts(); {
Common::AtomicStore(fifo.bFF_Breakpoint, 1);
UpdateInterrupts(true);
}
else
{
Common::AtomicStore(fifo.bFF_Breakpoint, 0);
}
} }
else else
{ {
// fifo.bFF_BPEnable is only used in single core // fifo.bFF_BPEnable is only used in single core
Common::AtomicStore(fifo.bFF_BPEnable, tmpCtrl.BPEnable && tmpCtrl.CPIntEnable && tmpCtrl.GPReadEnable); Common::AtomicStore(fifo.bFF_BPEnable, tmpCtrl.BPEnable && tmpCtrl.CPIntEnable && tmpCtrl.GPReadEnable && tmpCtrl.GPLinkEnable);
if (!tmpCtrl.BPEnable || !tmpCtrl.CPIntEnable || !tmpCtrl.GPReadEnable) if (!tmpCtrl.BPEnable || !tmpCtrl.CPIntEnable || !tmpCtrl.GPReadEnable || !tmpCtrl.GPLinkEnable)
Common::AtomicStore(fifo.bFF_Breakpoint, 0); Common::AtomicStore(fifo.bFF_Breakpoint, 0);
} }
@ -608,7 +611,7 @@ void CatchUpGPU()
{ {
//_assert_msg_(POWERPC,0,"BP: %08x",fifo.CPBreakpoint); //_assert_msg_(POWERPC,0,"BP: %08x",fifo.CPBreakpoint);
fifo.bFF_Breakpoint = 1; fifo.bFF_Breakpoint = 1;
UpdateInterrupts(); UpdateInterrupts(true);
break; break;
} }
} }
@ -669,17 +672,24 @@ void UpdateFifoRegister()
CatchUpGPU(); CatchUpGPU();
} }
void UpdateInterrupts() void UpdateInterrupts(bool active)
{ {
DEBUG_LOG(COMMANDPROCESSOR, "Fifo Breakpoint Interrupt triggered"); DEBUG_LOG(COMMANDPROCESSOR, "Fifo Breakpoint Interrupt: %s", (active)? "Asserted" : "Deasserted");
g_VideoInitialize.pSetInterrupt(INT_CAUSE_CP, true); g_VideoInitialize.pSetInterrupt(INT_CAUSE_CP, active);
} }
/*
void UpdateInterruptsFromVideoPlugin() void UpdateInterruptsFromVideoPlugin()
{ {
g_VideoInitialize.pScheduleEvent_Threadsafe(0, et_UpdateInterrupts, 0); g_VideoInitialize.pScheduleEvent_Threadsafe(0, et_UpdateInterrupts, 0);
} }
void UpdateInterrupts_Wrapper(u64 userdata, int cyclesLate)
{
UpdateInterrupts();
}
*/
void SetFifoIdleFromVideoPlugin() void SetFifoIdleFromVideoPlugin()
{ {
s_fifoIdleEvent.Set(); s_fifoIdleEvent.Set();

View File

@ -148,8 +148,8 @@ void Write32(const u32 _Data, const u32 _Address);
void CatchUpGPU(); void CatchUpGPU();
void GatherPipeBursted(); void GatherPipeBursted();
void UpdateFifoRegister(); void UpdateFifoRegister();
void UpdateInterrupts(); void UpdateInterrupts(bool active);
void UpdateInterruptsFromVideoPlugin(); //void UpdateInterruptsFromVideoPlugin();
void SetFifoIdleFromVideoPlugin(); void SetFifoIdleFromVideoPlugin();
bool AllowIdleSkipping(); bool AllowIdleSkipping();

View File

@ -35,7 +35,6 @@ typedef struct
{ {
HWND hWnd; HWND hWnd;
TLog pLog; TLog pLog;
int padNumber;
} SPADInitialize; } SPADInitialize;
typedef struct typedef struct

View File

@ -714,7 +714,6 @@ void Shutdown()
g_EmulatorRunning = false; g_EmulatorRunning = false;
#ifdef _WIN32 #ifdef _WIN32
dinput.Free();
// Kill xpad rumble // Kill xpad rumble
XINPUT_VIBRATION vib; XINPUT_VIBRATION vib;
vib.wLeftMotorSpeed = 0; vib.wLeftMotorSpeed = 0;
@ -722,6 +721,7 @@ void Shutdown()
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
if (pad[i].bRumble) if (pad[i].bRumble)
XInputSetState(pad[i].XPadPlayer, &vib); XInputSetState(pad[i].XPadPlayer, &vib);
dinput.Free();
#endif #endif
SaveConfig(); SaveConfig();
} }