From 6fb247d7854865ab5f6b8bab61cf6ddc06944d2f Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Fri, 17 Jul 2020 21:50:23 -0400 Subject: [PATCH] Changed QMutex to be recursive to prevent dead-locks in gui and emulator. A few bug fixes for the palette config window. --- src/drivers/Qt/ConsoleSoundConf.cpp | 78 ++++++++++++++++++----------- src/drivers/Qt/ConsoleWindow.cpp | 2 +- src/drivers/Qt/PaletteConf.cpp | 50 +++++++++++++----- src/drivers/Qt/fceuWrapper.cpp | 31 +++++++++--- src/drivers/Qt/fceuWrapper.h | 2 +- src/palette.cpp | 4 +- 6 files changed, 114 insertions(+), 53 deletions(-) diff --git a/src/drivers/Qt/ConsoleSoundConf.cpp b/src/drivers/Qt/ConsoleSoundConf.cpp index 4d716f3b..9932a7ca 100644 --- a/src/drivers/Qt/ConsoleSoundConf.cpp +++ b/src/drivers/Qt/ConsoleSoundConf.cpp @@ -262,10 +262,12 @@ void ConsoleSndConfDialog_t::bufSizeChanged(int value) g_config->setOption ("SDL.Sound.BufSize", value); // reset sound subsystem for changes to take effect - fceuWrapperLock(); - KillSound (); - InitSound (); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + KillSound (); + InitSound (); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void ConsoleSndConfDialog_t::volumeChanged(int value) @@ -278,9 +280,11 @@ void ConsoleSndConfDialog_t::volumeChanged(int value) g_config->setOption ("SDL.Sound.Volume", value); - fceuWrapperLock(); - FCEUI_SetSoundVolume (value); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + FCEUI_SetSoundVolume (value); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void ConsoleSndConfDialog_t::triangleChanged(int value) @@ -293,9 +297,11 @@ void ConsoleSndConfDialog_t::triangleChanged(int value) g_config->setOption ("SDL.Sound.TriangleVolume", value); - fceuWrapperLock(); - FCEUI_SetTriangleVolume (value); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + FCEUI_SetTriangleVolume (value); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void ConsoleSndConfDialog_t::square1Changed(int value) @@ -308,9 +314,11 @@ void ConsoleSndConfDialog_t::square1Changed(int value) g_config->setOption ("SDL.Sound.Square1Volume", value); - fceuWrapperLock(); - FCEUI_SetSquare1Volume (value); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + FCEUI_SetSquare1Volume (value); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void ConsoleSndConfDialog_t::square2Changed(int value) @@ -323,9 +331,11 @@ void ConsoleSndConfDialog_t::square2Changed(int value) g_config->setOption ("SDL.Sound.Square2Volume", value); - fceuWrapperLock(); - FCEUI_SetSquare2Volume (value); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + FCEUI_SetSquare2Volume (value); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void ConsoleSndConfDialog_t::noiseChanged(int value) @@ -338,9 +348,11 @@ void ConsoleSndConfDialog_t::noiseChanged(int value) g_config->setOption ("SDL.Sound.NoiseVolume", value); - fceuWrapperLock(); - FCEUI_SetNoiseVolume (value); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + FCEUI_SetNoiseVolume (value); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void ConsoleSndConfDialog_t::pcmChanged(int value) @@ -353,9 +365,11 @@ void ConsoleSndConfDialog_t::pcmChanged(int value) g_config->setOption ("SDL.Sound.PCMVolume", value); - fceuWrapperLock(); - FCEUI_SetPCMVolume (value); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + FCEUI_SetPCMVolume (value); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void ConsoleSndConfDialog_t::enaSoundStateChange(int value) @@ -427,10 +441,12 @@ void ConsoleSndConfDialog_t::soundQualityChanged(int index) g_config->setOption ("SDL.Sound.Quality", qualitySelect->itemData(index).toInt() ); // reset sound subsystem for changes to take effect - fceuWrapperLock(); - KillSound (); - InitSound (); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + KillSound (); + InitSound (); + fceuWrapperUnLock(); + } g_config->save (); } //---------------------------------------------------- @@ -440,10 +456,12 @@ void ConsoleSndConfDialog_t::soundRateChanged(int index) g_config->setOption ("SDL.Sound.Rate", rateSelect->itemData(index).toInt() ); // reset sound subsystem for changes to take effect - fceuWrapperLock(); - KillSound (); - InitSound (); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + KillSound (); + InitSound (); + fceuWrapperUnLock(); + } g_config->save (); } //---------------------------------------------------- diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index c0b120ee..e8eef4f1 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -40,7 +40,7 @@ consoleWin_t::consoleWin_t(QWidget *parent) setWindowIcon(QIcon(":fceux1.png")); gameTimer = new QTimer( this ); - mutex = new QMutex( QMutex::NonRecursive ); + mutex = new QMutex( QMutex::Recursive ); emulatorThread = new emulatorThread_t(); connect(emulatorThread, &QThread::finished, emulatorThread, &QObject::deleteLater); diff --git a/src/drivers/Qt/PaletteConf.cpp b/src/drivers/Qt/PaletteConf.cpp index bf167a27..b02c57e5 100644 --- a/src/drivers/Qt/PaletteConf.cpp +++ b/src/drivers/Qt/PaletteConf.cpp @@ -16,10 +16,11 @@ PaletteConfDialog_t::PaletteConfDialog_t(QWidget *parent) QVBoxLayout *mainLayout, *vbox; QHBoxLayout *hbox1; QGroupBox *frame; - QPushButton *closebutton; + //QPushButton *closebutton; QPushButton *button; int hue, tint; char stmp[64]; + std::string paletteFile; // sync with config g_config->getOption ("SDL.Hue", &hue); @@ -37,8 +38,11 @@ PaletteConfDialog_t::PaletteConfDialog_t(QWidget *parent) connect( button, SIGNAL(clicked(void)), this, SLOT(openPaletteFile(void)) ); + g_config->getOption ("SDL.Palette", &paletteFile); + custom_palette_path = new QLineEdit(); custom_palette_path->setReadOnly(true); + custom_palette_path->setText( paletteFile.c_str() ); hbox1->addWidget( custom_palette_path ); button = new QPushButton( tr("Clear") ); @@ -124,9 +128,11 @@ void PaletteConfDialog_t::hueChanged(int v) g_config->getOption ("SDL.Tint", &t); g_config->getOption ("SDL.NTSCpalette", &c); - fceuWrapperLock(); - FCEUI_SetNTSCTH (c, t, v); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + FCEUI_SetNTSCTH (c, t, v); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void PaletteConfDialog_t::tintChanged(int v) @@ -143,24 +149,42 @@ void PaletteConfDialog_t::tintChanged(int v) g_config->getOption ("SDL.NTSCpalette", &c); g_config->getOption ("SDL.Hue", &h); - fceuWrapperLock(); - FCEUI_SetNTSCTH (c, v, h); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + FCEUI_SetNTSCTH (c, v, h); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void PaletteConfDialog_t::use_NTSC_Changed(int state) { + int h, t; int value = (state == Qt::Unchecked) ? 0 : 1; g_config->setOption ("SDL.NTSCpalette", value); g_config->save (); - UpdateEMUCore (g_config); + + g_config->getOption ("SDL.Hue", &h); + g_config->getOption ("SDL.Tint", &t); + + if ( fceuWrapperTryLock() ) + { + FCEUI_SetNTSCTH (value, t, h); + //UpdateEMUCore (g_config); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void PaletteConfDialog_t::clearPalette(void) { - g_config->setOption ("SDL.Palette", 0); + g_config->setOption ("SDL.Palette", ""); custom_palette_path->setText(""); + + if ( fceuWrapperTryLock() ) + { + FCEUI_SetUserPalette( NULL, 0); + fceuWrapperUnLock(); + } } //---------------------------------------------------- void PaletteConfDialog_t::openPaletteFile(void) @@ -204,9 +228,11 @@ void PaletteConfDialog_t::openPaletteFile(void) g_config->setOption ("SDL.Palette", filename.toStdString().c_str() ); g_config->setOption ("SDL.NTSCpalette", 0); - fceuWrapperLock(); - LoadCPalette ( filename.toStdString().c_str() ); - fceuWrapperUnLock(); + if ( fceuWrapperTryLock() ) + { + LoadCPalette ( filename.toStdString().c_str() ); + fceuWrapperUnLock(); + } custom_palette_path->setText( filename.toStdString().c_str() ); diff --git a/src/drivers/Qt/fceuWrapper.cpp b/src/drivers/Qt/fceuWrapper.cpp index 7e1daca0..a43e3c15 100644 --- a/src/drivers/Qt/fceuWrapper.cpp +++ b/src/drivers/Qt/fceuWrapper.cpp @@ -56,7 +56,8 @@ static int inited = 0; static int noconfig=0; static int frameskip=0; static int periodic_saves = 0; -static bool mutexLocked = 0; +static int mutexLocks = 0; +static bool emulatorHasMutux = 0; extern double g_fpsScale; @@ -78,6 +79,7 @@ int mutecapture = 0; void FCEUD_Message(const char *text) { fputs(text, stdout); + fprintf(stdout, "\n"); } /** @@ -911,7 +913,7 @@ static void DoFun(int frameskip, int periodic_saves) void fceuWrapperLock(void) { consoleWindow->mutex->lock(); - mutexLocked = 1; + mutexLocks++; } bool fceuWrapperTryLock(int timeout) @@ -922,17 +924,17 @@ bool fceuWrapperTryLock(int timeout) if ( lockAcq ) { - mutexLocked = 1; + mutexLocks++; } return lockAcq; } void fceuWrapperUnLock(void) { - if ( mutexLocked ) + if ( mutexLocks > 0 ) { consoleWindow->mutex->unlock(); - mutexLocked = 0; + mutexLocks--; } else { @@ -942,12 +944,23 @@ void fceuWrapperUnLock(void) bool fceuWrapperIsLocked(void) { - return mutexLocked; + return mutexLocks > 0; } int fceuWrapperUpdate( void ) { - fceuWrapperLock(); + bool lock_acq; + + lock_acq = fceuWrapperTryLock(); + + if ( !lock_acq ) + { + printf("Error: Emulator Failed to Acquire Mutex\n"); + usleep( 100000 ); + + return -1; + } + emulatorHasMutux = 1; if ( GameInfo && !FCEUI_EmulationPaused() ) { @@ -955,6 +968,8 @@ int fceuWrapperUpdate( void ) fceuWrapperUnLock(); + emulatorHasMutux = 0; + while ( SpeedThrottle() ) { // Input device processing is in main thread @@ -966,6 +981,8 @@ int fceuWrapperUpdate( void ) { fceuWrapperUnLock(); + emulatorHasMutux = 0; + usleep( 100000 ); } return 0; diff --git a/src/drivers/Qt/fceuWrapper.h b/src/drivers/Qt/fceuWrapper.h index e3ce55a8..e0928e09 100644 --- a/src/drivers/Qt/fceuWrapper.h +++ b/src/drivers/Qt/fceuWrapper.h @@ -26,7 +26,7 @@ int fceuWrapperInit( int argc, char *argv[] ); int fceuWrapperClose( void ); int fceuWrapperUpdate( void ); void fceuWrapperLock(void); -bool fceuWrapperTryLock(int timeout); +bool fceuWrapperTryLock(int timeout = 1000); bool fceuWrapperIsLocked(void); void fceuWrapperUnLock(void); int fceuWrapperSoftReset(void); diff --git a/src/palette.cpp b/src/palette.cpp index 3ab97f4a..bc552d12 100644 --- a/src/palette.cpp +++ b/src/palette.cpp @@ -46,8 +46,8 @@ pal palette_game[64*8]; //custom palette for an individual game. (formerly palet pal palette_user[64*8]; //user's overridden palette (formerly palettec) pal palette_ntsc[64*8]; //mathematically generated NTSC palette (formerly paletten) -static bool palette_game_available; //whether palette_game is available -static bool palette_user_available; //whether palette_user is available +static bool palette_game_available=false; //whether palette_game is available +static bool palette_user_available=false; //whether palette_user is available //ntsc parameters: bool ntsccol_enable = false; //whether NTSC palette is selected