From 2b05c7169d91b7bc082153c96f055528ee502312 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Thu, 26 Nov 2020 23:44:59 -0500 Subject: [PATCH 01/14] Initial add of logic to allow for high priority threads in Qt GUI. Modified speed throttle logic to have more accurate frame timing. --- src/drivers/Qt/ConsoleWindow.cpp | 110 +++++++++++++++++ src/drivers/Qt/ConsoleWindow.h | 14 ++- src/drivers/Qt/fceuWrapper.cpp | 7 -- src/drivers/Qt/sdl-throttle.cpp | 202 ++++++++++++++++++++++++++++--- 4 files changed, 309 insertions(+), 24 deletions(-) diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index bfead09d..4b14580e 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -1,5 +1,14 @@ // GameApp.cpp // +#ifdef __linux__ +#include +#include +#include +#include +#include +#include +#endif + #include #include #include @@ -99,7 +108,9 @@ consoleWin_t::consoleWin_t(QWidget *parent) gameTimer->start( 8 ); // 120hz emulatorThread->start(); + //emulatorThread->setPriority( QThread::TimeCriticalPriority ); + //setPriority( QThread::TimeCriticalPriority ); } consoleWin_t::~consoleWin_t(void) @@ -1770,6 +1781,36 @@ void consoleWin_t::aboutQt(void) return; } +void consoleWin_t::setPriority( QThread::Priority priority_req ) +{ +#ifdef __linux__ + struct sched_param p; + int minPrio, maxPrio; + + minPrio = sched_get_priority_min( SCHED_FIFO ); + maxPrio = sched_get_priority_max( SCHED_FIFO ); + + p.sched_priority = maxPrio; + + if ( ::setpriority( PRIO_PROCESS, getpid(), -20 ) ) + { + perror("Qt Window thread setpriority error: "); + } + printf("sched_getscheduler(): %i \n", sched_getscheduler( getpid() ) ); + printf("sched_get_priority_min(SCHED_FIFO): %i \n", minPrio ); + printf("sched_get_priority_max(SCHED_FIFO): %i \n", maxPrio ); + + printf("setpriority(): %i \n", ::getpriority( PRIO_PROCESS, getpid() ) ); + + if ( sched_setscheduler( getpid(), SCHED_FIFO, &p ) ) + { + perror("Qt Window thread sched_setscheduler error:"); + } + printf("sched_getscheduler(): %i \n", sched_getscheduler( getpid() ) ); + +#endif +} + void consoleWin_t::syncActionConfig( QAction *act, const char *property ) { if ( act->isCheckable() ) @@ -1821,11 +1862,80 @@ void consoleWin_t::updatePeriodic(void) return; } +emulatorThread_t::emulatorThread_t(void) +{ + +} + +#ifdef __linux__ +#ifndef SYS_gettid +#error "SYS_gettid unavailable on this system" +#endif + +#define gettid() ((pid_t)syscall(SYS_gettid)) +#endif + + +void emulatorThread_t::setPriority( QThread::Priority priority_req ) +{ + printf("New Priority: %i \n", priority_req ); + printf("Old Priority: %i \n", priority() ); + + QThread::setPriority( priority_req ); + + printf("Set Priority: %i \n", priority() ); + +#ifdef __linux__ + struct sched_param p; + int oldPolicy, newPolicy, minPrio, maxPrio; + pthread_t self; + + self = pthread_self(); + newPolicy = SCHED_FIFO; + + minPrio = sched_get_priority_min( SCHED_FIFO ); + maxPrio = sched_get_priority_max( SCHED_FIFO ); + + pthread_getschedparam( self, &oldPolicy, &p ); + + printf("pthread_getschedparam(): %i, %i \n", oldPolicy, p.sched_priority ); + + p.sched_priority = maxPrio; + + if ( ::pthread_setschedparam( self, newPolicy, &p ) != 0 ) + { + perror("Emulator thread pthread_setschedparam error: "); + } + + if ( ::setpriority( PRIO_PROCESS, gettid(), -20 ) ) + { + perror("Emulator thread setpriority error: "); + } + printf("sched_getscheduler(): %i \n", sched_getscheduler( getpid() ) ); + printf("sched_get_priority_min(SCHED_FIFO): %i \n", minPrio ); + printf("sched_get_priority_max(SCHED_FIFO): %i \n", maxPrio ); + + printf("setpriority(): %i \n", ::getpriority( PRIO_PROCESS, getpid() ) ); + + //if ( sched_setscheduler( getpid(), SCHED_FIFO, &p ) ) + //{ + // perror("Emulator thread sched_setscheduler error:"); + //} + printf("sched_getscheduler(): %i \n", sched_getscheduler( getpid() ) ); + + pthread_getschedparam( self, &oldPolicy, &p ); + + printf("pthread_getschedparam(): %i, %i \n", oldPolicy, p.sched_priority ); +#endif +} + void emulatorThread_t::run(void) { printf("Emulator Start\n"); nes_shm->runEmulator = 1; + setPriority( QThread::TimeCriticalPriority ); + while ( nes_shm->runEmulator ) { fceuWrapperUpdate(); diff --git a/src/drivers/Qt/ConsoleWindow.h b/src/drivers/Qt/ConsoleWindow.h index d883d779..643731cb 100644 --- a/src/drivers/Qt/ConsoleWindow.h +++ b/src/drivers/Qt/ConsoleWindow.h @@ -28,10 +28,18 @@ class emulatorThread_t : public QThread { Q_OBJECT - //public slots: + protected: void run( void ) override; + + public: + emulatorThread_t(void); + + void setPriority( QThread::Priority priority ); + + private: + signals: - void finished(); + void finished(); }; class consoleWin_t : public QMainWindow @@ -53,6 +61,8 @@ class consoleWin_t : public QMainWindow int showListSelectDialog( const char *title, std::vector &l ); + void setPriority( QThread::Priority priority_req ); + protected: QMenu *fileMenu; QMenu *optMenu; diff --git a/src/drivers/Qt/fceuWrapper.cpp b/src/drivers/Qt/fceuWrapper.cpp index 484ad880..6edcd4e5 100644 --- a/src/drivers/Qt/fceuWrapper.cpp +++ b/src/drivers/Qt/fceuWrapper.cpp @@ -958,13 +958,6 @@ FCEUD_Update(uint8 *XBuf, } else { - //if (!NoWaiting && (!(eoptions&EO_NOTHROTTLE) || FCEUI_EmulationPaused())) - //{ - // while (SpeedThrottle()) - // { - // FCEUD_UpdateInput(); - // } - //} if (XBuf && (inited&4)) { BlitScreen(XBuf); blitDone = 1; diff --git a/src/drivers/Qt/sdl-throttle.cpp b/src/drivers/Qt/sdl-throttle.cpp index 2ade8ae4..5d3e9833 100644 --- a/src/drivers/Qt/sdl-throttle.cpp +++ b/src/drivers/Qt/sdl-throttle.cpp @@ -4,16 +4,93 @@ #include "Qt/sdl.h" #include "Qt/throttle.h" +#if defined(__linux) || defined(__APPLE__) +#include +#endif + +#ifdef __linux__ +#include +#endif + static const double Slowest = 0.015625; // 1/64x speed (around 1 fps on NTSC) static const double Fastest = 32; // 32x speed (around 1920 fps on NTSC) static const double Normal = 1.0; // 1x speed (around 60 fps on NTSC) -static uint64 Lasttime, Nexttime; +static uint32 frameLateCounter = 0; +static double Lasttime=0, Nexttime=0, Latetime=0; static double desired_frametime = (1.0 / 60.099823); +static double frameDeltaMin = 99999.0; +static double frameDeltaMax = 0.0; +static bool keepFrameTimeStats = true; static int InFrame = 0; double g_fpsScale = Normal; // used by sdl.cpp bool MaxSpeed = false; +double getHighPrecTimeStamp(void) +{ +#if defined(__linux) || defined(__APPLE__) + struct timespec ts; + double t; + + clock_gettime( CLOCK_REALTIME, &ts ); + + t = (double)ts.tv_sec + (double)(ts.tv_nsec * 1.0e-9); +#else + double t; + + t = (double)SDL_GetTicks(); + + t = t * 1e-3; +#endif + + return t; +} + +#ifdef __linux__ +static char useTimerFD = 1; +static int timerfd = -1; + +static void setTimer( double hz ) +{ + struct itimerspec ispec; + + if ( !useTimerFD ) + { + if ( timerfd != -1 ) + { + ::close( timerfd ); timerfd = -1; + } + return; + } + + if ( timerfd == -1 ) + { + timerfd = timerfd_create( CLOCK_REALTIME, 0 ); + + if ( timerfd == -1 ) + { + perror("timerfd_create failed: "); + return; + } + } + ispec.it_interval.tv_sec = 0; + ispec.it_interval.tv_nsec = (long)( 1.0e9 / hz ); + ispec.it_value.tv_sec = ispec.it_interval.tv_sec; + ispec.it_value.tv_nsec = ispec.it_interval.tv_nsec; + + if ( timerfd_settime( timerfd, 0, &ispec, NULL ) == -1 ) + { + perror("timerfd_settime failed: "); + } + + printf("Timer Set: %li ns\n", ispec.it_value.tv_nsec ); + + Lasttime = getHighPrecTimeStamp(); + Nexttime = Lasttime + desired_frametime; + Latetime = Nexttime + desired_frametime; +} +#endif + /* LOGMUL = exp(log(2) / 3) * * This gives us a value such that if we do x*=LOGMUL three times, @@ -28,7 +105,7 @@ bool MaxSpeed = false; * Refreshes the FPS throttling variables. */ void -RefreshThrottleFPS() +RefreshThrottleFPS(void) { double hz; int32_t fps = FCEUI_GetDesiredFPS(); // Do >> 24 to get in Hz @@ -47,37 +124,67 @@ RefreshThrottleFPS() Lasttime=0; Nexttime=0; InFrame=0; + +#ifdef __linux__ + setTimer( hz * g_fpsScale ); +#endif + +} + +int highPrecSleep( double timeSeconds ) +{ + int ret = 0; +#if defined(__linux) || defined(__APPLE__) + struct timespec req, rem; + + req.tv_sec = (long)timeSeconds; + req.tv_nsec = (long)((timeSeconds - (double)req.tv_sec) * 1e9); + + ret = nanosleep( &req, &rem ); +#else + SDL_Delay( (long)(time_left * 1e3) ); +#endif + return ret; } /** * Perform FPS speed throttling by delaying until the next time slot. */ int -SpeedThrottle() +SpeedThrottle(void) { if (g_fpsScale >= 32) { return 0; /* Done waiting */ } - uint64 time_left; - uint64 cur_time; + double time_left; + double cur_time; + double frame_time = desired_frametime; + double quarterFrame = 0.250 * frame_time; - if (!Lasttime) + cur_time = getHighPrecTimeStamp(); + + if (Lasttime < 1.0) { - Lasttime = SDL_GetTicks(); + Lasttime = cur_time; + Latetime = Lasttime + frame_time; } if (!InFrame) { InFrame = 1; - Nexttime = Lasttime + desired_frametime * 1000; + Nexttime = Lasttime + frame_time; + Latetime = Nexttime + frame_time; } - cur_time = SDL_GetTicks(); - if(cur_time >= Nexttime) + if (cur_time >= Nexttime) + { time_left = 0; + } else + { time_left = Nexttime - cur_time; + } if (time_left > 50) { @@ -93,16 +200,81 @@ SpeedThrottle() //fprintf(stderr, "attempting to sleep %Ld ms, frame complete=%s\n", // time_left, InFrame?"no":"yes"); +#ifdef __linux__ + if ( timerfd != -1 ) + { + uint64_t val; + + if ( read( timerfd, &val, sizeof(val) ) > 0 ) + { + if ( val > 1 ) + { + frameLateCounter += (val - 1); + //printf("Late Frame: %u \n", frameLateCounter); + } + } + } + else if ( time_left > 0 ) + { + highPrecSleep( time_left ); + } + else + { + if ( cur_time >= Latetime ) + { + frameLateCounter++; + //printf("Late Frame: %u - %llu ms\n", frameLateCounter, cur_time - Latetime); + } + } +#else if ( time_left > 0 ) { - SDL_Delay(time_left); + highPrecSleep( time_left ); } - - if (!InFrame) + else { - Lasttime = SDL_GetTicks(); + if ( cur_time >= Latetime ) + { + frameLateCounter++; + //printf("Late Frame: %u - %llu ms\n", frameLateCounter, cur_time - Latetime); + } + } +#endif + + cur_time = getHighPrecTimeStamp(); + + if ( cur_time >= (Nexttime - quarterFrame) ) + { + if ( keepFrameTimeStats ) + { + double frameDelta; + + frameDelta = (cur_time - Lasttime); + + if ( frameDelta < frameDeltaMin ) + { + frameDeltaMin = frameDelta; + } + if ( frameDelta > frameDeltaMax ) + { + frameDeltaMax = frameDelta; + } + //printf("Frame Delta: %f us min:%f max:%f \n", frameDelta * 1e6, frameDeltaMin * 1e6, frameDeltaMax * 1e6 ); + //printf("Frame Sleep Time: %f Target Error: %f us\n", time_left * 1e6, (cur_time - Nexttime) * 1e6 ); + } + Lasttime = Nexttime; + Nexttime = Lasttime + frame_time; + Latetime = Nexttime + frame_time; + + if ( cur_time >= Nexttime ) + { + Lasttime = cur_time; + Nexttime = Lasttime + frame_time; + Latetime = Nexttime + frame_time; + } return 0; /* Done waiting */ } + return 1; /* Must still wait some more */ } @@ -113,7 +285,7 @@ void IncreaseEmulationSpeed(void) { g_fpsScale *= LOGMUL; - if(g_fpsScale > Fastest) g_fpsScale = Fastest; + if (g_fpsScale > Fastest) g_fpsScale = Fastest; RefreshThrottleFPS(); From 3982d1b897e424f0b8b246d2c424fd426531cc42 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Fri, 27 Nov 2020 14:23:17 -0500 Subject: [PATCH 02/14] CAdded --- src/drivers/Qt/ConsoleWindow.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index 4b14580e..a3da7570 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -110,7 +110,7 @@ consoleWin_t::consoleWin_t(QWidget *parent) emulatorThread->start(); //emulatorThread->setPriority( QThread::TimeCriticalPriority ); - //setPriority( QThread::TimeCriticalPriority ); + setPriority( QThread::TimeCriticalPriority ); } consoleWin_t::~consoleWin_t(void) @@ -1783,6 +1783,7 @@ void consoleWin_t::aboutQt(void) void consoleWin_t::setPriority( QThread::Priority priority_req ) { + #ifdef __linux__ struct sched_param p; int minPrio, maxPrio; @@ -1808,6 +1809,12 @@ void consoleWin_t::setPriority( QThread::Priority priority_req ) } printf("sched_getscheduler(): %i \n", sched_getscheduler( getpid() ) ); +#else + QThread *mainThread; + + mainThread = QThread::currentThread(); + + mainThread->setPriority( priority_req ); #endif } From a7b031ee81738a506e5494fac796c8e52a144655 Mon Sep 17 00:00:00 2001 From: mjbudd77 Date: Fri, 27 Nov 2020 19:53:14 -0500 Subject: [PATCH 03/14] Qt GUI thread priority functionality added for mac os --- src/drivers/Qt/ConsoleWindow.cpp | 109 ++++++++++++++++++++++++++++--- src/drivers/Qt/ConsoleWindow.h | 3 + 2 files changed, 103 insertions(+), 9 deletions(-) diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index 4b14580e..9b4ae71d 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -110,7 +110,7 @@ consoleWin_t::consoleWin_t(QWidget *parent) emulatorThread->start(); //emulatorThread->setPriority( QThread::TimeCriticalPriority ); - //setPriority( QThread::TimeCriticalPriority ); + setPriority( QThread::TimeCriticalPriority ); } consoleWin_t::~consoleWin_t(void) @@ -1783,7 +1783,7 @@ void consoleWin_t::aboutQt(void) void consoleWin_t::setPriority( QThread::Priority priority_req ) { -#ifdef __linux__ +#if defined(__linux__) struct sched_param p; int minPrio, maxPrio; @@ -1808,6 +1808,45 @@ void consoleWin_t::setPriority( QThread::Priority priority_req ) } printf("sched_getscheduler(): %i \n", sched_getscheduler( getpid() ) ); +#elif defined(__APPLE__) + + struct sched_param p; + int oldPolicy, newPolicy, minPrio, maxPrio; + QThread *qself; + pthread_t self; + + qself = QThread::currentThread(); + + self = pthread_self(); + newPolicy = SCHED_FIFO; + + printf("QThreadID: %p \n", QThread::currentThreadId() ); + printf("PThreadID: %p \n", self ); + + minPrio = sched_get_priority_min( SCHED_FIFO ); + maxPrio = sched_get_priority_max( SCHED_FIFO ); + + pthread_getschedparam( self, &oldPolicy, &p ); + + printf("GUI pthread_getschedparam(): %i, %i \n", oldPolicy, p.sched_priority ); + + qself->setPriority( priority_req ); + + p.sched_priority = maxPrio; + + //if ( ::pthread_setschedparam( self, newPolicy, &p ) != 0 ) + //{ + //perror("GUI thread pthread_setschedparam error: "); + //} + pthread_getschedparam( self, &oldPolicy, &p ); + + printf("GUI pthread_getschedparam(): %i, %i \n", oldPolicy, p.sched_priority ); + + if ( ::setpriority( PRIO_PROCESS, getpid(), -20 ) ) + { + perror("GUI thread setpriority error: "); + } + printf("GUI Thread setpriority(): %i \n", ::getpriority( PRIO_PROCESS, getpid() ) ); #endif } @@ -1864,6 +1903,9 @@ void consoleWin_t::updatePeriodic(void) emulatorThread_t::emulatorThread_t(void) { + #if defined(__linux__) || defined(__APPLE__) + pself = 0; + #endif } @@ -1881,28 +1923,26 @@ void emulatorThread_t::setPriority( QThread::Priority priority_req ) printf("New Priority: %i \n", priority_req ); printf("Old Priority: %i \n", priority() ); - QThread::setPriority( priority_req ); + //QThread::setPriority( priority_req ); printf("Set Priority: %i \n", priority() ); -#ifdef __linux__ +#if defined(__linux__) struct sched_param p; int oldPolicy, newPolicy, minPrio, maxPrio; - pthread_t self; - self = pthread_self(); newPolicy = SCHED_FIFO; minPrio = sched_get_priority_min( SCHED_FIFO ); maxPrio = sched_get_priority_max( SCHED_FIFO ); - pthread_getschedparam( self, &oldPolicy, &p ); + pthread_getschedparam( pself, &oldPolicy, &p ); printf("pthread_getschedparam(): %i, %i \n", oldPolicy, p.sched_priority ); p.sched_priority = maxPrio; - if ( ::pthread_setschedparam( self, newPolicy, &p ) != 0 ) + if ( ::pthread_setschedparam( pself, newPolicy, &p ) != 0 ) { perror("Emulator thread pthread_setschedparam error: "); } @@ -1923,9 +1963,52 @@ void emulatorThread_t::setPriority( QThread::Priority priority_req ) //} printf("sched_getscheduler(): %i \n", sched_getscheduler( getpid() ) ); - pthread_getschedparam( self, &oldPolicy, &p ); + pthread_getschedparam( pself, &oldPolicy, &p ); printf("pthread_getschedparam(): %i, %i \n", oldPolicy, p.sched_priority ); +#elif defined(__APPLE__) + struct sched_param p; + int oldPolicy, newPolicy, minPrio, maxPrio; + + newPolicy = SCHED_FIFO; + + if ( ::setpriority( PRIO_PROCESS, getpid(), -20 ) ) + { + perror("Emulator thread setpriority error: "); + } + printf("EMU setpriority(): %i \n", ::getpriority( PRIO_PROCESS, getpid() ) ); + + minPrio = sched_get_priority_min( SCHED_FIFO ); + maxPrio = sched_get_priority_max( SCHED_FIFO ); + + printf("sched_get_priority_min(SCHED_FIFO): %i \n", minPrio ); + printf("sched_get_priority_max(SCHED_FIFO): %i \n", maxPrio ); + + pthread_getschedparam( pself, &oldPolicy, &p ); + + printf("EMU pthread_getschedparam(): %i, %i \n", oldPolicy, p.sched_priority ); + + //for (int i=0; i<7; i++) + //{ + // QThread::setPriority( (QThread::Priority)i); + + // pthread_getschedparam( pself, &oldPolicy, &p ); + + // printf("%i: EMU pthread_getschedparam(): %i, %i \n", i, oldPolicy, p.sched_priority ); + //} + + p.sched_priority = maxPrio; + + if ( ::pthread_setschedparam( pself, newPolicy, &p ) != 0 ) + { + perror("Emulator thread pthread_setschedparam error: "); + } + + pthread_getschedparam( pself, &oldPolicy, &p ); + + printf("EMU pthread_getschedparam(): %i, %i \n", oldPolicy, p.sched_priority ); + + #endif } @@ -1934,6 +2017,14 @@ void emulatorThread_t::run(void) printf("Emulator Start\n"); nes_shm->runEmulator = 1; + #if defined(__linux__) || defined(__APPLE__) + if ( pthread_self() == QThread::currentThreadId() ) + { + pself = pthread_self(); + printf("EMU is using PThread: %p\n", pself); + } + #endif + setPriority( QThread::TimeCriticalPriority ); while ( nes_shm->runEmulator ) diff --git a/src/drivers/Qt/ConsoleWindow.h b/src/drivers/Qt/ConsoleWindow.h index 643731cb..e7494bc8 100644 --- a/src/drivers/Qt/ConsoleWindow.h +++ b/src/drivers/Qt/ConsoleWindow.h @@ -37,6 +37,9 @@ class emulatorThread_t : public QThread void setPriority( QThread::Priority priority ); private: + #if defined(__linux__) || defined(__APPLE__) + pthread_t pself; + #endif signals: void finished(); From 6b8e4f883be7be94108343e8e8424e6c030579ed Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Fri, 27 Nov 2020 22:18:04 -0500 Subject: [PATCH 04/14] Initial add of timing configuration window to Qt GUI. --- src/CMakeLists.txt | 1 + src/drivers/Qt/ConsoleWindow.cpp | 274 ++++++++++++++++++++----------- src/drivers/Qt/ConsoleWindow.h | 17 +- src/drivers/Qt/TimingConf.cpp | 196 ++++++++++++++++++++++ src/drivers/Qt/TimingConf.h | 51 ++++++ 5 files changed, 438 insertions(+), 101 deletions(-) create mode 100644 src/drivers/Qt/TimingConf.cpp create mode 100644 src/drivers/Qt/TimingConf.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 74382718..82db5765 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -430,6 +430,7 @@ set(SRC_DRIVERS_SDL ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/InputConf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/GamePadConf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/HotKeyConf.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/TimingConf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/PaletteConf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/GuiConf.cpp ${CMAKE_CURRENT_SOURCE_DIR}/drivers/Qt/MoviePlay.cpp diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index e7bc92f4..1078b838 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -36,6 +36,7 @@ #include "Qt/GuiConf.h" #include "Qt/MoviePlay.h" #include "Qt/MovieOptions.h" +#include "Qt/TimingConf.h" #include "Qt/LuaControl.h" #include "Qt/CheatsConf.h" #include "Qt/GameGenie.h" @@ -415,6 +416,14 @@ void consoleWin_t::createMainMenu(void) optMenu->addAction(guiConfig); + // Options -> Timing Config + timingConfig = new QAction(tr("Timing Config"), this); + //timingConfig->setShortcut( QKeySequence(tr("Ctrl+C"))); + timingConfig->setStatusTip(tr("Timing Configure")); + connect(timingConfig, SIGNAL(triggered()), this, SLOT(openTimingConfWin(void)) ); + + optMenu->addAction(timingConfig); + // Options -> Movie Options movieConfig = new QAction(tr("Movie Options"), this); //movieConfig->setShortcut( QKeySequence(tr("Ctrl+C"))); @@ -1263,6 +1272,17 @@ void consoleWin_t::openGuiConfWin(void) guiConfWin->show(); } +void consoleWin_t::openTimingConfWin(void) +{ + TimingConfDialog_t *tmConfWin; + + //printf("Open Timing Config Window\n"); + + tmConfWin = new TimingConfDialog_t(this); + + tmConfWin->show(); +} + void consoleWin_t::openMovieOptWin(void) { MovieOptionsDialog_t *win; @@ -1924,105 +1944,8 @@ emulatorThread_t::emulatorThread_t(void) #endif -void emulatorThread_t::setPriority( QThread::Priority priority_req ) +void emulatorThread_t::init(void) { - printf("New Priority: %i \n", priority_req ); - printf("Old Priority: %i \n", priority() ); - - //QThread::setPriority( priority_req ); - - printf("Set Priority: %i \n", priority() ); - -#if defined(__linux__) - struct sched_param p; - int oldPolicy, newPolicy, minPrio, maxPrio; - - newPolicy = SCHED_FIFO; - - minPrio = sched_get_priority_min( SCHED_FIFO ); - maxPrio = sched_get_priority_max( SCHED_FIFO ); - - pthread_getschedparam( pself, &oldPolicy, &p ); - - printf("pthread_getschedparam(): %i, %i \n", oldPolicy, p.sched_priority ); - - p.sched_priority = maxPrio; - - if ( ::pthread_setschedparam( pself, newPolicy, &p ) != 0 ) - { - perror("Emulator thread pthread_setschedparam error: "); - } - - if ( ::setpriority( PRIO_PROCESS, gettid(), -20 ) ) - { - perror("Emulator thread setpriority error: "); - } - printf("sched_getscheduler(): %i \n", sched_getscheduler( getpid() ) ); - printf("sched_get_priority_min(SCHED_FIFO): %i \n", minPrio ); - printf("sched_get_priority_max(SCHED_FIFO): %i \n", maxPrio ); - - printf("setpriority(): %i \n", ::getpriority( PRIO_PROCESS, getpid() ) ); - - //if ( sched_setscheduler( getpid(), SCHED_FIFO, &p ) ) - //{ - // perror("Emulator thread sched_setscheduler error:"); - //} - printf("sched_getscheduler(): %i \n", sched_getscheduler( getpid() ) ); - - pthread_getschedparam( pself, &oldPolicy, &p ); - - printf("pthread_getschedparam(): %i, %i \n", oldPolicy, p.sched_priority ); -#elif defined(__APPLE__) - struct sched_param p; - int oldPolicy, newPolicy, minPrio, maxPrio; - - newPolicy = SCHED_FIFO; - - if ( ::setpriority( PRIO_PROCESS, getpid(), -20 ) ) - { - perror("Emulator thread setpriority error: "); - } - printf("EMU setpriority(): %i \n", ::getpriority( PRIO_PROCESS, getpid() ) ); - - minPrio = sched_get_priority_min( SCHED_FIFO ); - maxPrio = sched_get_priority_max( SCHED_FIFO ); - - printf("sched_get_priority_min(SCHED_FIFO): %i \n", minPrio ); - printf("sched_get_priority_max(SCHED_FIFO): %i \n", maxPrio ); - - pthread_getschedparam( pself, &oldPolicy, &p ); - - printf("EMU pthread_getschedparam(): %i, %i \n", oldPolicy, p.sched_priority ); - - //for (int i=0; i<7; i++) - //{ - // QThread::setPriority( (QThread::Priority)i); - - // pthread_getschedparam( pself, &oldPolicy, &p ); - - // printf("%i: EMU pthread_getschedparam(): %i, %i \n", i, oldPolicy, p.sched_priority ); - //} - - p.sched_priority = maxPrio; - - if ( ::pthread_setschedparam( pself, newPolicy, &p ) != 0 ) - { - perror("Emulator thread pthread_setschedparam error: "); - } - - pthread_getschedparam( pself, &oldPolicy, &p ); - - printf("EMU pthread_getschedparam(): %i, %i \n", oldPolicy, p.sched_priority ); - - -#endif -} - -void emulatorThread_t::run(void) -{ - printf("Emulator Start\n"); - nes_shm->runEmulator = 1; - #if defined(__linux__) || defined(__APPLE__) if ( pthread_self() == (pthread_t)QThread::currentThreadId() ) { @@ -2031,7 +1954,160 @@ void emulatorThread_t::run(void) } #endif - setPriority( QThread::TimeCriticalPriority ); + #if defined(__linux__) + pid = gettid(); + #elif defined(__APPLE__) + pid = getpid(); + #endif +} + +void emulatorThread_t::setPriority( QThread::Priority priority_req ) +{ + //printf("New Priority: %i \n", priority_req ); + //printf("Old Priority: %i \n", priority() ); + + QThread::setPriority( priority_req ); + + //printf("Set Priority: %i \n", priority() ); +} + +int emulatorThread_t::setNicePriority( int value ) +{ + int ret = 0; +#if defined(__linux__) + + if ( value < -20 ) + { + value = -20; + } + else if ( value > 19 ) + { + value = 19; + } + + if ( ::setpriority( PRIO_PROCESS, pid, value ) ) + { + perror("Emulator thread setpriority error: "); + ret = -1; + } +#elif defined(__APPLE__) + + if ( value < -20 ) + { + value = -20; + } + else if ( value > 20 ) + { + value = 20; + } + + if ( ::setpriority( PRIO_PROCESS, pid, value ) ) + { + perror("Emulator thread setpriority error: "); + ret = -1; + } +#endif + return ret; +} + +int emulatorThread_t::getNicePriority(void) +{ + return ::getpriority( PRIO_PROCESS, pid ); +} + +int emulatorThread_t::getMinSchedPriority(void) +{ + int policy, prio; + + if ( getSchedParam( policy, prio ) ) + { + return 0; + } + return sched_get_priority_min( policy ); +} + +int emulatorThread_t::getMaxSchedPriority(void) +{ + int policy, prio; + + if ( getSchedParam( policy, prio ) ) + { + return 0; + } + return sched_get_priority_max( policy ); +} + +int emulatorThread_t::getSchedParam( int &policy, int &priority ) +{ + struct sched_param p; + + if ( pthread_getschedparam( pself, &policy, &p ) ) + { + perror("Emulator thread pthread_getschedparam error: "); + return -1; + } + return 0; +} + +int emulatorThread_t::setSchedParam( int policy, int priority ) +{ + int ret = 0; +#if defined(__linux__) + struct sched_param p; + int minPrio, maxPrio; + + minPrio = sched_get_priority_min( policy ); + maxPrio = sched_get_priority_max( policy ); + + if ( priority < minPrio ) + { + priority = minPrio; + } + else if ( priority > maxPrio ) + { + priority = maxPrio; + } + p.sched_priority = priority; + + if ( ::pthread_setschedparam( pself, policy, &p ) != 0 ) + { + perror("Emulator thread pthread_setschedparam error: "); + ret = -1; + } + +#elif defined(__APPLE__) + struct sched_param p; + int minPrio, maxPrio; + + minPrio = sched_get_priority_min( policy ); + maxPrio = sched_get_priority_max( policy ); + + if ( priority < minPrio ) + { + priority = minPrio; + } + else if ( priority > maxPrio ) + { + priority = maxPrio; + } + p.sched_priority = priority; + + if ( ::pthread_setschedparam( pself, policy, &p ) != 0 ) + { + perror("Emulator thread pthread_setschedparam error: "); + } +#endif + return ret; +} + +void emulatorThread_t::run(void) +{ + printf("Emulator Start\n"); + nes_shm->runEmulator = 1; + + init(); + + //setPriority( QThread::TimeCriticalPriority ); while ( nes_shm->runEmulator ) { diff --git a/src/drivers/Qt/ConsoleWindow.h b/src/drivers/Qt/ConsoleWindow.h index e7494bc8..88b9e631 100644 --- a/src/drivers/Qt/ConsoleWindow.h +++ b/src/drivers/Qt/ConsoleWindow.h @@ -36,9 +36,20 @@ class emulatorThread_t : public QThread void setPriority( QThread::Priority priority ); + #if defined(__linux__) || defined(__APPLE__) + int setSchedParam( int policy, int priority ); + int getSchedParam( int &policy, int &priority ); + int setNicePriority( int value ); + int getNicePriority( void ); + int getMinSchedPriority(void); + int getMaxSchedPriority(void); + #endif private: + void init(void); + #if defined(__linux__) || defined(__APPLE__) pthread_t pself; + int pid; #endif signals: @@ -66,6 +77,8 @@ class consoleWin_t : public QMainWindow void setPriority( QThread::Priority priority_req ); + emulatorThread_t *emulatorThread; + protected: QMenu *fileMenu; QMenu *optMenu; @@ -91,6 +104,7 @@ class consoleWin_t : public QMainWindow QAction *hotkeyConfig; QAction *paletteConfig; QAction *guiConfig; + QAction *timingConfig; QAction *movieConfig; QAction *autoResume; QAction *fullscreen; @@ -125,8 +139,6 @@ class consoleWin_t : public QMainWindow QTimer *gameTimer; - emulatorThread_t *emulatorThread; - std::string errorMsg; bool errorMsgValid; @@ -161,6 +173,7 @@ class consoleWin_t : public QMainWindow void openHotkeyConfWin(void); void openPaletteConfWin(void); void openGuiConfWin(void); + void openTimingConfWin(void); void openMovieOptWin(void); void openCodeDataLogger(void); void openTraceLogger(void); diff --git a/src/drivers/Qt/TimingConf.cpp b/src/drivers/Qt/TimingConf.cpp new file mode 100644 index 00000000..96cdaa9a --- /dev/null +++ b/src/drivers/Qt/TimingConf.cpp @@ -0,0 +1,196 @@ +// TimingConf.cpp +// +#include +#include +#include +#include + +#include +#include +#include + +#include "Qt/main.h" +#include "Qt/dface.h" +#include "Qt/input.h" +#include "Qt/config.h" +#include "Qt/keyscan.h" +#include "Qt/fceuWrapper.h" +#include "Qt/ConsoleWindow.h" +#include "Qt/TimingConf.h" + +//---------------------------------------------------------------------------- +TimingConfDialog_t::TimingConfDialog_t(QWidget *parent) + : QDialog( parent ) +{ + QVBoxLayout *mainLayout, *vbox; + QHBoxLayout *hbox; + QGridLayout *grid; + QGroupBox *emuPrioBox; + + setWindowTitle("Timing Configuration"); + + mainLayout = new QVBoxLayout(); + + emuPrioCtlEna = new QCheckBox( tr("Set Scheduling Parameters at Startup") ); + + emuPrioBox = new QGroupBox( tr("EMU Thread Scheduling Parameters") ); + grid = new QGridLayout(); + emuPrioBox->setLayout( grid ); + + emuSchedPolicyBox = new QComboBox(); + emuSchedPrioSlider = new QSlider( Qt::Horizontal ); + emuSchedNiceSlider = new QSlider( Qt::Horizontal ); + emuSchedPrioLabel = new QLabel( tr("Priority (RT)") ); + + emuSchedPolicyBox->addItem( tr("SCHED_OTHER") , SCHED_OTHER ); + emuSchedPolicyBox->addItem( tr("SCHED_FIFO") , SCHED_FIFO ); + emuSchedPolicyBox->addItem( tr("SCHED_RR") , SCHED_RR ); + + grid->addWidget( new QLabel( tr("Policy") ), 0, 0 ); + grid->addWidget( emuSchedPolicyBox, 0, 1 ); + grid->addWidget( emuSchedPrioLabel, 1, 0 ); + grid->addWidget( emuSchedPrioSlider, 1, 1 ); + grid->addWidget( new QLabel( tr("Priority (Nice)") ), 2, 0 ); + grid->addWidget( emuSchedNiceSlider, 2, 1 ); + + mainLayout->addWidget( emuPrioCtlEna ); + mainLayout->addWidget( emuPrioBox ); + + setLayout( mainLayout ); + + updatePolicyBox(); + updateSliderLimits(); + updateSliderValues(); + + connect( emuSchedPolicyBox , SIGNAL(activated(int)) , this, SLOT(emuSchedPolicyChange(int)) ); + connect( emuSchedNiceSlider , SIGNAL(valueChanged(int)), this, SLOT(emuSchedNiceChange(int)) ); + connect( emuSchedPrioSlider , SIGNAL(valueChanged(int)), this, SLOT(emuSchedPrioChange(int)) ); +} +//---------------------------------------------------------------------------- +TimingConfDialog_t::~TimingConfDialog_t(void) +{ + printf("Destroy Timing Config Window\n"); +} +//---------------------------------------------------------------------------- +void TimingConfDialog_t::closeEvent(QCloseEvent *event) +{ + printf("Timing Close Window Event\n"); + done(0); + deleteLater(); + event->accept(); +} +//---------------------------------------------------------------------------- +void TimingConfDialog_t::closeWindow(void) +{ + //printf("Close Window\n"); + done(0); + deleteLater(); +} +//---------------------------------------------------------------------------- +void TimingConfDialog_t::emuSchedNiceChange(int val) +{ + if ( consoleWindow == NULL ) + { + return; + } + if ( consoleWindow->emulatorThread->setNicePriority( -val ) ) + { + printf("Set Nice Failed\n"); + } +} +//---------------------------------------------------------------------------- +void TimingConfDialog_t::emuSchedPrioChange(int val) +{ + int policy, prio; + + if ( consoleWindow == NULL ) + { + return; + } + consoleWindow->emulatorThread->getSchedParam( policy, prio ); + + if ( consoleWindow->emulatorThread->setSchedParam( policy, val ) ) + { + printf("Set setSchedParam Failed\n"); + } +} +//---------------------------------------------------------------------------- +void TimingConfDialog_t::emuSchedPolicyChange( int index ) +{ + int policy, prio; + + if ( consoleWindow == NULL ) + { + return; + } + consoleWindow->emulatorThread->getSchedParam( policy, prio ); + + policy = emuSchedPolicyBox->itemData( index ).toInt(); + + consoleWindow->emulatorThread->setSchedParam( policy, prio ); + + updatePolicyBox(); + updateSliderLimits(); + updateSliderValues(); +} +//---------------------------------------------------------------------------- +void TimingConfDialog_t::updatePolicyBox(void) +{ + int policy, prio; + + if ( consoleWindow == NULL ) + { + return; + } + consoleWindow->emulatorThread->getSchedParam( policy, prio ); + + for (int j=0; jcount(); j++) + { + if ( emuSchedPolicyBox->itemData(j).toInt() == policy ) + { + //printf("Found Policy %i %i\n", j , policy ); + emuSchedPolicyBox->setCurrentIndex( j ); + } + } + +} +//---------------------------------------------------------------------------- +void TimingConfDialog_t::updateSliderValues(void) +{ + int policy, prio; + + if ( consoleWindow == NULL ) + { + return; + } + consoleWindow->emulatorThread->getSchedParam( policy, prio ); + + emuSchedNiceSlider->setValue( -consoleWindow->emulatorThread->getNicePriority() ); + emuSchedPrioSlider->setValue( prio ); + + if ( (policy == SCHED_RR) || (policy == SCHED_FIFO) ) + { + emuSchedPrioLabel->setEnabled(true); + emuSchedPrioSlider->setEnabled(true); + } + else + { + emuSchedPrioLabel->setEnabled(false); + emuSchedPrioSlider->setEnabled(false); + } +} +//---------------------------------------------------------------------------- +void TimingConfDialog_t::updateSliderLimits(void) +{ + if ( consoleWindow == NULL ) + { + return; + } + + emuSchedNiceSlider->setMinimum( -20 ); + emuSchedNiceSlider->setMaximum( 20 ); + emuSchedPrioSlider->setMinimum( consoleWindow->emulatorThread->getMinSchedPriority() ); + emuSchedPrioSlider->setMaximum( consoleWindow->emulatorThread->getMaxSchedPriority() ); + +} +//---------------------------------------------------------------------------- diff --git a/src/drivers/Qt/TimingConf.h b/src/drivers/Qt/TimingConf.h new file mode 100644 index 00000000..d6d8a23b --- /dev/null +++ b/src/drivers/Qt/TimingConf.h @@ -0,0 +1,51 @@ +// TimingConf.h +// + +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Qt/main.h" + +class TimingConfDialog_t : public QDialog +{ + Q_OBJECT + + public: + TimingConfDialog_t(QWidget *parent = 0); + ~TimingConfDialog_t(void); + + protected: + void closeEvent(QCloseEvent *event); + + QCheckBox *emuPrioCtlEna; + QComboBox *emuSchedPolicyBox; + QSlider *emuSchedPrioSlider; + QSlider *emuSchedNiceSlider; + QLabel *emuSchedPrioLabel; + + private: + void updatePolicyBox(void); + void updateSliderLimits(void); + void updateSliderValues(void); + + public slots: + void closeWindow(void); + private slots: + void emuSchedNiceChange( int val ); + void emuSchedPrioChange( int val ); + void emuSchedPolicyChange( int index ); + +}; From e154b38327c29a769b2cc46f8a83c228939ee773 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Fri, 27 Nov 2020 23:04:41 -0500 Subject: [PATCH 05/14] Qt Timing config window bug fixes for cases when OS does not have proper permissions. --- src/drivers/Qt/ConsoleWindow.cpp | 5 +-- src/drivers/Qt/TimingConf.cpp | 55 +++++++++++++++++++++++++++++--- 2 files changed, 52 insertions(+), 8 deletions(-) diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index 1078b838..4cd8a8f6 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -109,9 +109,8 @@ consoleWin_t::consoleWin_t(QWidget *parent) gameTimer->start( 8 ); // 120hz emulatorThread->start(); - //emulatorThread->setPriority( QThread::TimeCriticalPriority ); - setPriority( QThread::TimeCriticalPriority ); + //setPriority( QThread::TimeCriticalPriority ); } consoleWin_t::~consoleWin_t(void) @@ -2107,8 +2106,6 @@ void emulatorThread_t::run(void) init(); - //setPriority( QThread::TimeCriticalPriority ); - while ( nes_shm->runEmulator ) { fceuWrapperUpdate(); diff --git a/src/drivers/Qt/TimingConf.cpp b/src/drivers/Qt/TimingConf.cpp index 96cdaa9a..fa039e31 100644 --- a/src/drivers/Qt/TimingConf.cpp +++ b/src/drivers/Qt/TimingConf.cpp @@ -23,7 +23,7 @@ TimingConfDialog_t::TimingConfDialog_t(QWidget *parent) : QDialog( parent ) { QVBoxLayout *mainLayout, *vbox; - QHBoxLayout *hbox; + //QHBoxLayout *hbox; QGridLayout *grid; QGroupBox *emuPrioBox; @@ -93,10 +93,25 @@ void TimingConfDialog_t::emuSchedNiceChange(int val) { return; } + fceuWrapperLock(); if ( consoleWindow->emulatorThread->setNicePriority( -val ) ) { - printf("Set Nice Failed\n"); + char msg[1024]; + + sprintf( msg, "Error: system call setPriority Failed\nReason: %s\n", strerror(errno) ); +#ifdef __linux__ + strcat( msg, "Ensure that your system has the proper resource permissions set in the file:\n\n"); + strcat( msg, " /etc/security/limits.conf \n\n"); + strcat( msg, "Adding the following lines to that file and rebooting will usually fix the issue:\n\n"); + strcat( msg, "* - priority 99 \n"); + strcat( msg, "* - rtprio 99 \n"); + strcat( msg, "* - nice -20 \n"); +#endif + printf("%s\n", msg ); + consoleWindow->QueueErrorMsgWindow( msg ); + updateSliderValues(); } + fceuWrapperUnLock(); } //---------------------------------------------------------------------------- void TimingConfDialog_t::emuSchedPrioChange(int val) @@ -107,12 +122,27 @@ void TimingConfDialog_t::emuSchedPrioChange(int val) { return; } + fceuWrapperLock(); consoleWindow->emulatorThread->getSchedParam( policy, prio ); if ( consoleWindow->emulatorThread->setSchedParam( policy, val ) ) { - printf("Set setSchedParam Failed\n"); + char msg[1024]; + + sprintf( msg, "Error: system call pthread_setschedparam Failed\nReason: %s\n", strerror(errno) ); +#ifdef __linux__ + strcat( msg, "Ensure that your system has the proper resource permissions set in the file:\n\n"); + strcat( msg, " /etc/security/limits.conf \n\n"); + strcat( msg, "Adding the following lines to that file and rebooting will usually fix the issue:\n\n"); + strcat( msg, "* - priority 99 \n"); + strcat( msg, "* - rtprio 99 \n"); + strcat( msg, "* - nice -20 \n"); +#endif + printf("%s\n", msg ); + consoleWindow->QueueErrorMsgWindow( msg ); + updateSliderValues(); } + fceuWrapperUnLock(); } //---------------------------------------------------------------------------- void TimingConfDialog_t::emuSchedPolicyChange( int index ) @@ -123,15 +153,32 @@ void TimingConfDialog_t::emuSchedPolicyChange( int index ) { return; } + fceuWrapperLock(); consoleWindow->emulatorThread->getSchedParam( policy, prio ); policy = emuSchedPolicyBox->itemData( index ).toInt(); - consoleWindow->emulatorThread->setSchedParam( policy, prio ); + if ( consoleWindow->emulatorThread->setSchedParam( policy, prio ) ) + { + char msg[1024]; + + sprintf( msg, "Error: system call pthread_setschedparam Failed\nReason: %s\n", strerror(errno) ); +#ifdef __linux__ + strcat( msg, "Ensure that your system has the proper resource permissions set in the file:\n\n"); + strcat( msg, " /etc/security/limits.conf \n\n"); + strcat( msg, "Adding the following lines to that file and rebooting will usually fix the issue:\n\n"); + strcat( msg, "* - priority 99 \n"); + strcat( msg, "* - rtprio 99 \n"); + strcat( msg, "* - nice -20 \n"); +#endif + printf("%s\n", msg ); + consoleWindow->QueueErrorMsgWindow( msg ); + } updatePolicyBox(); updateSliderLimits(); updateSliderValues(); + fceuWrapperUnLock(); } //---------------------------------------------------------------------------- void TimingConfDialog_t::updatePolicyBox(void) From d5d6b32787751f93af7e86ff4372200a4b8d67cb Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Fri, 27 Nov 2020 23:42:32 -0500 Subject: [PATCH 06/14] Added GUI scheduling parameters to Qt timing config window --- src/drivers/Qt/ConsoleWindow.cpp | 253 ++++++++++++++++++++++++------- src/drivers/Qt/ConsoleWindow.h | 9 +- src/drivers/Qt/TimingConf.cpp | 153 ++++++++++++++++++- src/drivers/Qt/TimingConf.h | 7 + 4 files changed, 366 insertions(+), 56 deletions(-) diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index 4cd8a8f6..d62bd326 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -1800,81 +1800,226 @@ void consoleWin_t::aboutQt(void) return; } -void consoleWin_t::setPriority( QThread::Priority priority_req ) +int consoleWin_t::setNicePriority( int value ) { + int ret = 0; +#if defined(__linux__) + + if ( value < -20 ) + { + value = -20; + } + else if ( value > 19 ) + { + value = 19; + } + + if ( ::setpriority( PRIO_PROCESS, getpid(), value ) ) + { + perror("Emulator thread setpriority error: "); + ret = -1; + } +#elif defined(__APPLE__) + + if ( value < -20 ) + { + value = -20; + } + else if ( value > 20 ) + { + value = 20; + } + + if ( ::setpriority( PRIO_PROCESS, getpid(), value ) ) + { + perror("Emulator thread setpriority error: "); + ret = -1; + } +#endif + return ret; +} + +int consoleWin_t::getNicePriority(void) +{ + return ::getpriority( PRIO_PROCESS, getpid() ); +} + +int consoleWin_t::getMinSchedPriority(void) +{ + int policy, prio; + + if ( getSchedParam( policy, prio ) ) + { + return 0; + } + return sched_get_priority_min( policy ); +} + +int consoleWin_t::getMaxSchedPriority(void) +{ + int policy, prio; + + if ( getSchedParam( policy, prio ) ) + { + return 0; + } + return sched_get_priority_max( policy ); +} + +int consoleWin_t::getSchedParam( int &policy, int &priority ) +{ + int ret = 0; + +#if defined(__linux__) + struct sched_param p; + + policy = sched_getscheduler( getpid() ); + + if ( sched_getparam( getpid(), &p ) ) + { + ret = -1; + } + + priority = p.sched_priority; + +#elif defined(__APPLE__) + struct sched_param p; + + if ( pthread_getschedparam( pself, &policy, &p ) ) + { + perror("GUI thread pthread_getschedparam error: "); + ret = -1; + } +#endif + return ret; +} + +int consoleWin_t::setSchedParam( int policy, int priority ) +{ + int ret = 0; #if defined(__linux__) struct sched_param p; int minPrio, maxPrio; - minPrio = sched_get_priority_min( SCHED_FIFO ); - maxPrio = sched_get_priority_max( SCHED_FIFO ); + minPrio = sched_get_priority_min( policy ); + maxPrio = sched_get_priority_max( policy ); - p.sched_priority = maxPrio; - - if ( ::setpriority( PRIO_PROCESS, getpid(), -20 ) ) + if ( priority < minPrio ) { - perror("Qt Window thread setpriority error: "); + priority = minPrio; } - printf("sched_getscheduler(): %i \n", sched_getscheduler( getpid() ) ); - printf("sched_get_priority_min(SCHED_FIFO): %i \n", minPrio ); - printf("sched_get_priority_max(SCHED_FIFO): %i \n", maxPrio ); - - printf("setpriority(): %i \n", ::getpriority( PRIO_PROCESS, getpid() ) ); - - if ( sched_setscheduler( getpid(), SCHED_FIFO, &p ) ) + else if ( priority > maxPrio ) { - perror("Qt Window thread sched_setscheduler error:"); + priority = maxPrio; } - printf("sched_getscheduler(): %i \n", sched_getscheduler( getpid() ) ); + p.sched_priority = priority; + if ( sched_setscheduler( getpid(), policy, &p ) ) + { + perror("GUI thread sched_setscheduler error"); + ret = -1; + } #elif defined(__APPLE__) - struct sched_param p; - int oldPolicy, newPolicy, minPrio, maxPrio; - QThread *qself; - pthread_t self; + int minPrio, maxPrio; - qself = QThread::currentThread(); + minPrio = sched_get_priority_min( policy ); + maxPrio = sched_get_priority_max( policy ); - self = pthread_self(); - newPolicy = SCHED_FIFO; - - printf("QThreadID: %p \n", QThread::currentThreadId() ); - printf("PThreadID: %p \n", self ); - - minPrio = sched_get_priority_min( SCHED_FIFO ); - maxPrio = sched_get_priority_max( SCHED_FIFO ); - - pthread_getschedparam( self, &oldPolicy, &p ); - - printf("GUI pthread_getschedparam(): %i, %i \n", oldPolicy, p.sched_priority ); - - qself->setPriority( priority_req ); - - p.sched_priority = maxPrio; - - //if ( ::pthread_setschedparam( self, newPolicy, &p ) != 0 ) - //{ - //perror("GUI thread pthread_setschedparam error: "); - //} - pthread_getschedparam( self, &oldPolicy, &p ); - - printf("GUI pthread_getschedparam(): %i, %i \n", oldPolicy, p.sched_priority ); - - if ( ::setpriority( PRIO_PROCESS, getpid(), -20 ) ) + if ( priority < minPrio ) { - perror("GUI thread setpriority error: "); + priority = minPrio; } - printf("GUI Thread setpriority(): %i \n", ::getpriority( PRIO_PROCESS, getpid() ) ); -#else - QThread *mainThread; + else if ( priority > maxPrio ) + { + priority = maxPrio; + } + p.sched_priority = priority; - mainThread = QThread::currentThread(); - - mainThread->setPriority( priority_req ); + if ( ::pthread_setschedparam( pself, policy, &p ) != 0 ) + { + perror("GUI thread pthread_setschedparam error: "); + } #endif + return ret; } + +//void consoleWin_t::setPriority( QThread::Priority priority_req ) +//{ +//#if defined(__linux__) +// struct sched_param p; +// int minPrio, maxPrio; +// +// minPrio = sched_get_priority_min( SCHED_FIFO ); +// maxPrio = sched_get_priority_max( SCHED_FIFO ); +// +// p.sched_priority = maxPrio; +// +// if ( ::setpriority( PRIO_PROCESS, getpid(), -20 ) ) +// { +// perror("Qt Window thread setpriority error "); +// } +// printf("sched_getscheduler(): %i \n", sched_getscheduler( getpid() ) ); +// printf("sched_get_priority_min(SCHED_FIFO): %i \n", minPrio ); +// printf("sched_get_priority_max(SCHED_FIFO): %i \n", maxPrio ); +// +// printf("setpriority(): %i \n", ::getpriority( PRIO_PROCESS, getpid() ) ); +// +// if ( sched_setscheduler( getpid(), SCHED_FIFO, &p ) ) +// { +// perror("Qt Window thread sched_setscheduler error:"); +// } +// printf("sched_getscheduler(): %i \n", sched_getscheduler( getpid() ) ); +// +//#elif defined(__APPLE__) +// +// struct sched_param p; +// int oldPolicy, newPolicy, minPrio, maxPrio; +// QThread *qself; +// pthread_t self; +// +// qself = QThread::currentThread(); +// +// self = pthread_self(); +// newPolicy = SCHED_FIFO; +// +// printf("QThreadID: %p \n", QThread::currentThreadId() ); +// printf("PThreadID: %p \n", self ); +// +// minPrio = sched_get_priority_min( SCHED_FIFO ); +// maxPrio = sched_get_priority_max( SCHED_FIFO ); +// +// pthread_getschedparam( self, &oldPolicy, &p ); +// +// printf("GUI pthread_getschedparam(): %i, %i \n", oldPolicy, p.sched_priority ); +// +// qself->setPriority( priority_req ); +// +// p.sched_priority = maxPrio; +// +// //if ( ::pthread_setschedparam( self, newPolicy, &p ) != 0 ) +// //{ +// //perror("GUI thread pthread_setschedparam error: "); +// //} +// pthread_getschedparam( self, &oldPolicy, &p ); +// +// printf("GUI pthread_getschedparam(): %i, %i \n", oldPolicy, p.sched_priority ); +// +// if ( ::setpriority( PRIO_PROCESS, getpid(), -20 ) ) +// { +// perror("GUI thread setpriority error: "); +// } +// printf("GUI Thread setpriority(): %i \n", ::getpriority( PRIO_PROCESS, getpid() ) ); +//#else +// QThread *mainThread; +// +// mainThread = QThread::currentThread(); +// +// mainThread->setPriority( priority_req ); +//#endif +//} + void consoleWin_t::syncActionConfig( QAction *act, const char *property ) { if ( act->isCheckable() ) diff --git a/src/drivers/Qt/ConsoleWindow.h b/src/drivers/Qt/ConsoleWindow.h index 88b9e631..971f2c85 100644 --- a/src/drivers/Qt/ConsoleWindow.h +++ b/src/drivers/Qt/ConsoleWindow.h @@ -75,7 +75,14 @@ class consoleWin_t : public QMainWindow int showListSelectDialog( const char *title, std::vector &l ); - void setPriority( QThread::Priority priority_req ); + #if defined(__linux__) || defined(__APPLE__) + int setSchedParam( int policy, int priority ); + int getSchedParam( int &policy, int &priority ); + int setNicePriority( int value ); + int getNicePriority( void ); + int getMinSchedPriority(void); + int getMaxSchedPriority(void); + #endif emulatorThread_t *emulatorThread; diff --git a/src/drivers/Qt/TimingConf.cpp b/src/drivers/Qt/TimingConf.cpp index fa039e31..58e9cd38 100644 --- a/src/drivers/Qt/TimingConf.cpp +++ b/src/drivers/Qt/TimingConf.cpp @@ -25,7 +25,7 @@ TimingConfDialog_t::TimingConfDialog_t(QWidget *parent) QVBoxLayout *mainLayout, *vbox; //QHBoxLayout *hbox; QGridLayout *grid; - QGroupBox *emuPrioBox; + QGroupBox *emuPrioBox, *guiPrioBox; setWindowTitle("Timing Configuration"); @@ -34,6 +34,7 @@ TimingConfDialog_t::TimingConfDialog_t(QWidget *parent) emuPrioCtlEna = new QCheckBox( tr("Set Scheduling Parameters at Startup") ); emuPrioBox = new QGroupBox( tr("EMU Thread Scheduling Parameters") ); + guiPrioBox = new QGroupBox( tr("GUI Thread Scheduling Parameters") ); grid = new QGridLayout(); emuPrioBox->setLayout( grid ); @@ -56,6 +57,27 @@ TimingConfDialog_t::TimingConfDialog_t(QWidget *parent) mainLayout->addWidget( emuPrioCtlEna ); mainLayout->addWidget( emuPrioBox ); + grid = new QGridLayout(); + guiPrioBox->setLayout( grid ); + + guiSchedPolicyBox = new QComboBox(); + guiSchedPrioSlider = new QSlider( Qt::Horizontal ); + guiSchedNiceSlider = new QSlider( Qt::Horizontal ); + guiSchedPrioLabel = new QLabel( tr("Priority (RT)") ); + + guiSchedPolicyBox->addItem( tr("SCHED_OTHER") , SCHED_OTHER ); + guiSchedPolicyBox->addItem( tr("SCHED_FIFO") , SCHED_FIFO ); + guiSchedPolicyBox->addItem( tr("SCHED_RR") , SCHED_RR ); + + grid->addWidget( new QLabel( tr("Policy") ), 0, 0 ); + grid->addWidget( guiSchedPolicyBox, 0, 1 ); + grid->addWidget( guiSchedPrioLabel, 1, 0 ); + grid->addWidget( guiSchedPrioSlider, 1, 1 ); + grid->addWidget( new QLabel( tr("Priority (Nice)") ), 2, 0 ); + grid->addWidget( guiSchedNiceSlider, 2, 1 ); + + mainLayout->addWidget( guiPrioBox ); + setLayout( mainLayout ); updatePolicyBox(); @@ -65,6 +87,9 @@ TimingConfDialog_t::TimingConfDialog_t(QWidget *parent) connect( emuSchedPolicyBox , SIGNAL(activated(int)) , this, SLOT(emuSchedPolicyChange(int)) ); connect( emuSchedNiceSlider , SIGNAL(valueChanged(int)), this, SLOT(emuSchedNiceChange(int)) ); connect( emuSchedPrioSlider , SIGNAL(valueChanged(int)), this, SLOT(emuSchedPrioChange(int)) ); + connect( guiSchedPolicyBox , SIGNAL(activated(int)) , this, SLOT(guiSchedPolicyChange(int)) ); + connect( guiSchedNiceSlider , SIGNAL(valueChanged(int)), this, SLOT(guiSchedNiceChange(int)) ); + connect( guiSchedPrioSlider , SIGNAL(valueChanged(int)), this, SLOT(guiSchedPrioChange(int)) ); } //---------------------------------------------------------------------------- TimingConfDialog_t::~TimingConfDialog_t(void) @@ -181,6 +206,100 @@ void TimingConfDialog_t::emuSchedPolicyChange( int index ) fceuWrapperUnLock(); } //---------------------------------------------------------------------------- +void TimingConfDialog_t::guiSchedNiceChange(int val) +{ + if ( consoleWindow == NULL ) + { + return; + } + fceuWrapperLock(); + if ( consoleWindow->setNicePriority( -val ) ) + { + char msg[1024]; + + sprintf( msg, "Error: system call setPriority Failed\nReason: %s\n", strerror(errno) ); +#ifdef __linux__ + strcat( msg, "Ensure that your system has the proper resource permissions set in the file:\n\n"); + strcat( msg, " /etc/security/limits.conf \n\n"); + strcat( msg, "Adding the following lines to that file and rebooting will usually fix the issue:\n\n"); + strcat( msg, "* - priority 99 \n"); + strcat( msg, "* - rtprio 99 \n"); + strcat( msg, "* - nice -20 \n"); +#endif + printf("%s\n", msg ); + consoleWindow->QueueErrorMsgWindow( msg ); + updateSliderValues(); + } + fceuWrapperUnLock(); +} +//---------------------------------------------------------------------------- +void TimingConfDialog_t::guiSchedPrioChange(int val) +{ + int policy, prio; + + if ( consoleWindow == NULL ) + { + return; + } + fceuWrapperLock(); + consoleWindow->getSchedParam( policy, prio ); + + if ( consoleWindow->setSchedParam( policy, val ) ) + { + char msg[1024]; + + sprintf( msg, "Error: system call pthread_setschedparam Failed\nReason: %s\n", strerror(errno) ); +#ifdef __linux__ + strcat( msg, "Ensure that your system has the proper resource permissions set in the file:\n\n"); + strcat( msg, " /etc/security/limits.conf \n\n"); + strcat( msg, "Adding the following lines to that file and rebooting will usually fix the issue:\n\n"); + strcat( msg, "* - priority 99 \n"); + strcat( msg, "* - rtprio 99 \n"); + strcat( msg, "* - nice -20 \n"); +#endif + printf("%s\n", msg ); + consoleWindow->QueueErrorMsgWindow( msg ); + updateSliderValues(); + } + fceuWrapperUnLock(); +} +//---------------------------------------------------------------------------- +void TimingConfDialog_t::guiSchedPolicyChange( int index ) +{ + int policy, prio; + + if ( consoleWindow == NULL ) + { + return; + } + fceuWrapperLock(); + consoleWindow->getSchedParam( policy, prio ); + + policy = guiSchedPolicyBox->itemData( index ).toInt(); + + if ( consoleWindow->setSchedParam( policy, prio ) ) + { + char msg[1024]; + + sprintf( msg, "Error: system call pthread_setschedparam Failed\nReason: %s\n", strerror(errno) ); +#ifdef __linux__ + strcat( msg, "Ensure that your system has the proper resource permissions set in the file:\n\n"); + strcat( msg, " /etc/security/limits.conf \n\n"); + strcat( msg, "Adding the following lines to that file and rebooting will usually fix the issue:\n\n"); + strcat( msg, "* - priority 99 \n"); + strcat( msg, "* - rtprio 99 \n"); + strcat( msg, "* - nice -20 \n"); +#endif + printf("%s\n", msg ); + consoleWindow->QueueErrorMsgWindow( msg ); + } + + updatePolicyBox(); + updateSliderLimits(); + updateSliderValues(); + fceuWrapperUnLock(); +} +//---------------------------------------------------------------------------- void TimingConfDialog_t::updatePolicyBox(void) { int policy, prio; @@ -200,6 +319,17 @@ void TimingConfDialog_t::updatePolicyBox(void) } } + consoleWindow->getSchedParam( policy, prio ); + + for (int j=0; jcount(); j++) + { + if ( guiSchedPolicyBox->itemData(j).toInt() == policy ) + { + //printf("Found Policy %i %i\n", j , policy ); + guiSchedPolicyBox->setCurrentIndex( j ); + } + } + } //---------------------------------------------------------------------------- void TimingConfDialog_t::updateSliderValues(void) @@ -225,6 +355,22 @@ void TimingConfDialog_t::updateSliderValues(void) emuSchedPrioLabel->setEnabled(false); emuSchedPrioSlider->setEnabled(false); } + + consoleWindow->getSchedParam( policy, prio ); + + guiSchedNiceSlider->setValue( -consoleWindow->getNicePriority() ); + guiSchedPrioSlider->setValue( prio ); + + if ( (policy == SCHED_RR) || (policy == SCHED_FIFO) ) + { + guiSchedPrioLabel->setEnabled(true); + guiSchedPrioSlider->setEnabled(true); + } + else + { + guiSchedPrioLabel->setEnabled(false); + guiSchedPrioSlider->setEnabled(false); + } } //---------------------------------------------------------------------------- void TimingConfDialog_t::updateSliderLimits(void) @@ -239,5 +385,10 @@ void TimingConfDialog_t::updateSliderLimits(void) emuSchedPrioSlider->setMinimum( consoleWindow->emulatorThread->getMinSchedPriority() ); emuSchedPrioSlider->setMaximum( consoleWindow->emulatorThread->getMaxSchedPriority() ); + guiSchedNiceSlider->setMinimum( -20 ); + guiSchedNiceSlider->setMaximum( 20 ); + guiSchedPrioSlider->setMinimum( consoleWindow->getMinSchedPriority() ); + guiSchedPrioSlider->setMaximum( consoleWindow->getMaxSchedPriority() ); + } //---------------------------------------------------------------------------- diff --git a/src/drivers/Qt/TimingConf.h b/src/drivers/Qt/TimingConf.h index d6d8a23b..ec80908a 100644 --- a/src/drivers/Qt/TimingConf.h +++ b/src/drivers/Qt/TimingConf.h @@ -35,6 +35,10 @@ class TimingConfDialog_t : public QDialog QSlider *emuSchedPrioSlider; QSlider *emuSchedNiceSlider; QLabel *emuSchedPrioLabel; + QComboBox *guiSchedPolicyBox; + QSlider *guiSchedPrioSlider; + QSlider *guiSchedNiceSlider; + QLabel *guiSchedPrioLabel; private: void updatePolicyBox(void); @@ -47,5 +51,8 @@ class TimingConfDialog_t : public QDialog void emuSchedNiceChange( int val ); void emuSchedPrioChange( int val ); void emuSchedPolicyChange( int index ); + void guiSchedNiceChange( int val ); + void guiSchedPrioChange( int val ); + void guiSchedPolicyChange( int index ); }; From ab31c760d5b6e41728df85b57027b3340727e994 Mon Sep 17 00:00:00 2001 From: mjbudd77 Date: Fri, 27 Nov 2020 23:48:57 -0500 Subject: [PATCH 07/14] Build fix for mac os --- src/drivers/Qt/ConsoleWindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index d62bd326..6bfc942a 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -1885,7 +1885,7 @@ int consoleWin_t::getSchedParam( int &policy, int &priority ) #elif defined(__APPLE__) struct sched_param p; - if ( pthread_getschedparam( pself, &policy, &p ) ) + if ( pthread_getschedparam( pthread_self(), &policy, &p ) ) { perror("GUI thread pthread_getschedparam error: "); ret = -1; @@ -1936,7 +1936,7 @@ int consoleWin_t::setSchedParam( int policy, int priority ) } p.sched_priority = priority; - if ( ::pthread_setschedparam( pself, policy, &p ) != 0 ) + if ( ::pthread_setschedparam( pthread_self(), policy, &p ) != 0 ) { perror("GUI thread pthread_setschedparam error: "); } From e67b17795c06f765352800ea2a01c44382043408 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Sat, 28 Nov 2020 00:28:28 -0500 Subject: [PATCH 08/14] Added scheduler config parameters to Qt GUI. --- src/drivers/Qt/ConsoleWindow.cpp | 7 +++++-- src/drivers/Qt/TimingConf.cpp | 36 ++++++++++++++++++++++++++++++++ src/drivers/Qt/TimingConf.h | 2 ++ src/drivers/Qt/config.cpp | 8 +++++++ 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index 6bfc942a..4921487a 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -1878,9 +1878,12 @@ int consoleWin_t::getSchedParam( int &policy, int &priority ) if ( sched_getparam( getpid(), &p ) ) { ret = -1; + priority = 0; + } + else + { + priority = p.sched_priority; } - - priority = p.sched_priority; #elif defined(__APPLE__) struct sched_param p; diff --git a/src/drivers/Qt/TimingConf.cpp b/src/drivers/Qt/TimingConf.cpp index 58e9cd38..1650747b 100644 --- a/src/drivers/Qt/TimingConf.cpp +++ b/src/drivers/Qt/TimingConf.cpp @@ -22,6 +22,7 @@ TimingConfDialog_t::TimingConfDialog_t(QWidget *parent) : QDialog( parent ) { + int opt; QVBoxLayout *mainLayout, *vbox; //QHBoxLayout *hbox; QGridLayout *grid; @@ -80,6 +81,10 @@ TimingConfDialog_t::TimingConfDialog_t(QWidget *parent) setLayout( mainLayout ); + g_config->getOption( "SDL.SetSchedParam", &opt ); + + emuPrioCtlEna->setChecked( opt ); + updatePolicyBox(); updateSliderLimits(); updateSliderValues(); @@ -90,6 +95,7 @@ TimingConfDialog_t::TimingConfDialog_t(QWidget *parent) connect( guiSchedPolicyBox , SIGNAL(activated(int)) , this, SLOT(guiSchedPolicyChange(int)) ); connect( guiSchedNiceSlider , SIGNAL(valueChanged(int)), this, SLOT(guiSchedNiceChange(int)) ); connect( guiSchedPrioSlider , SIGNAL(valueChanged(int)), this, SLOT(guiSchedPrioChange(int)) ); + connect( emuPrioCtlEna , SIGNAL(stateChanged(int)), this, SLOT(emuSchedCtlChange(int)) ); } //---------------------------------------------------------------------------- TimingConfDialog_t::~TimingConfDialog_t(void) @@ -103,6 +109,7 @@ void TimingConfDialog_t::closeEvent(QCloseEvent *event) done(0); deleteLater(); event->accept(); + saveValues(); } //---------------------------------------------------------------------------- void TimingConfDialog_t::closeWindow(void) @@ -110,6 +117,35 @@ void TimingConfDialog_t::closeWindow(void) //printf("Close Window\n"); done(0); deleteLater(); + saveValues(); +} +//---------------------------------------------------------------------------- +void TimingConfDialog_t::emuSchedCtlChange( int state ) +{ + g_config->setOption( "SDL.SetSchedParam", (state != Qt::Unchecked) ); +} +//---------------------------------------------------------------------------- +void TimingConfDialog_t::saveValues(void) +{ + int policy, prio; + + if ( consoleWindow == NULL ) + { + return; + } + consoleWindow->emulatorThread->getSchedParam( policy, prio ); + + g_config->setOption( "SDL.EmuSchedPolicy", policy ); + g_config->setOption( "SDL.EmuSchedPrioRt", prio ); + g_config->setOption( "SDL.EmuSchedNice" , consoleWindow->emulatorThread->getNicePriority() ); + + consoleWindow->getSchedParam( policy, prio ); + + g_config->setOption( "SDL.GuiSchedPolicy", policy ); + g_config->setOption( "SDL.GuiSchedPrioRt", prio ); + g_config->setOption( "SDL.GuiSchedNice" , consoleWindow->getNicePriority() ); + + g_config->save(); } //---------------------------------------------------------------------------- void TimingConfDialog_t::emuSchedNiceChange(int val) diff --git a/src/drivers/Qt/TimingConf.h b/src/drivers/Qt/TimingConf.h index ec80908a..11af5fd9 100644 --- a/src/drivers/Qt/TimingConf.h +++ b/src/drivers/Qt/TimingConf.h @@ -44,10 +44,12 @@ class TimingConfDialog_t : public QDialog void updatePolicyBox(void); void updateSliderLimits(void); void updateSliderValues(void); + void saveValues(void); public slots: void closeWindow(void); private slots: + void emuSchedCtlChange( int state ); void emuSchedNiceChange( int val ); void emuSchedPrioChange( int val ); void emuSchedPolicyChange( int index ); diff --git a/src/drivers/Qt/config.cpp b/src/drivers/Qt/config.cpp index 7c5aba61..42ca7dc6 100644 --- a/src/drivers/Qt/config.cpp +++ b/src/drivers/Qt/config.cpp @@ -315,6 +315,14 @@ InitConfig() config->addOption("_useNativeFileDialog", "SDL.UseNativeFileDialog", false); config->addOption("_useNativeMenuBar" , "SDL.UseNativeMenuBar", false); + config->addOption("_setSchedParam" , "SDL.SetSchedParam" , 0); + config->addOption("_emuSchedPolicy" , "SDL.EmuSchedPolicy", 0); + config->addOption("_emuSchedNice" , "SDL.EmuSchedNice ", 0); + config->addOption("_emuSchedPrioRt" , "SDL.EmuSchedPrioRt", 40); + config->addOption("_guiSchedPolicy" , "SDL.GuiSchedPolicy", 0); + config->addOption("_guiSchedNice" , "SDL.GuiSchedNice ", 0); + config->addOption("_guiSchedPrioRt" , "SDL.GuiSchedPrioRt", 40); + // fcm -> fm2 conversion config->addOption("fcmconvert", "SDL.FCMConvert", ""); From 18e9dc1a9e6007cf6fdfea5d6a4a72ab8111ad3c Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Sat, 28 Nov 2020 15:40:27 -0500 Subject: [PATCH 09/14] Added logic to check whether the user has the permissions necessary to increase the priority (nice) of the process. If not, disable the slider on the Qt timing window. --- src/drivers/Qt/TimingConf.cpp | 53 +++++++++++++++++++++++++++++++++-- src/drivers/Qt/TimingConf.h | 2 ++ 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/src/drivers/Qt/TimingConf.cpp b/src/drivers/Qt/TimingConf.cpp index 1650747b..b5ef59e8 100644 --- a/src/drivers/Qt/TimingConf.cpp +++ b/src/drivers/Qt/TimingConf.cpp @@ -5,6 +5,11 @@ #include #include +#include +#include +#include +#include + #include #include #include @@ -18,6 +23,38 @@ #include "Qt/ConsoleWindow.h" #include "Qt/TimingConf.h" +//---------------------------------------------------------------------------- +static bool hasNicePermissions( int val ) +{ + int usrID; + bool usrRoot; + + usrID = geteuid(); + + usrRoot = (usrID == 0); + + if ( usrRoot ) + { + return true; + } +#ifdef __linux__ + struct rlimit r; + + if ( getrlimit( RLIMIT_NICE, &r ) == 0 ) + { + int ncur = 20 - r.rlim_cur; + + if ( val >= ncur ) + { + return true; + } + //printf("RLim Cur: %lu \n", r.rlim_cur ); + //printf("RLim Max: %lu \n", r.rlim_max ); + } +#endif + + return false; +} //---------------------------------------------------------------------------- TimingConfDialog_t::TimingConfDialog_t(QWidget *parent) : QDialog( parent ) @@ -43,6 +80,7 @@ TimingConfDialog_t::TimingConfDialog_t(QWidget *parent) emuSchedPrioSlider = new QSlider( Qt::Horizontal ); emuSchedNiceSlider = new QSlider( Qt::Horizontal ); emuSchedPrioLabel = new QLabel( tr("Priority (RT)") ); + emuSchedNiceLabel = new QLabel( tr("Priority (Nice)") ); emuSchedPolicyBox->addItem( tr("SCHED_OTHER") , SCHED_OTHER ); emuSchedPolicyBox->addItem( tr("SCHED_FIFO") , SCHED_FIFO ); @@ -52,7 +90,7 @@ TimingConfDialog_t::TimingConfDialog_t(QWidget *parent) grid->addWidget( emuSchedPolicyBox, 0, 1 ); grid->addWidget( emuSchedPrioLabel, 1, 0 ); grid->addWidget( emuSchedPrioSlider, 1, 1 ); - grid->addWidget( new QLabel( tr("Priority (Nice)") ), 2, 0 ); + grid->addWidget( emuSchedNiceLabel, 2, 0 ); grid->addWidget( emuSchedNiceSlider, 2, 1 ); mainLayout->addWidget( emuPrioCtlEna ); @@ -65,6 +103,7 @@ TimingConfDialog_t::TimingConfDialog_t(QWidget *parent) guiSchedPrioSlider = new QSlider( Qt::Horizontal ); guiSchedNiceSlider = new QSlider( Qt::Horizontal ); guiSchedPrioLabel = new QLabel( tr("Priority (RT)") ); + guiSchedNiceLabel = new QLabel( tr("Priority (Nice)") ); guiSchedPolicyBox->addItem( tr("SCHED_OTHER") , SCHED_OTHER ); guiSchedPolicyBox->addItem( tr("SCHED_FIFO") , SCHED_FIFO ); @@ -74,7 +113,7 @@ TimingConfDialog_t::TimingConfDialog_t(QWidget *parent) grid->addWidget( guiSchedPolicyBox, 0, 1 ); grid->addWidget( guiSchedPrioLabel, 1, 0 ); grid->addWidget( guiSchedPrioSlider, 1, 1 ); - grid->addWidget( new QLabel( tr("Priority (Nice)") ), 2, 0 ); + grid->addWidget( guiSchedNiceLabel, 2, 0 ); grid->addWidget( guiSchedNiceSlider, 2, 1 ); mainLayout->addWidget( guiPrioBox ); @@ -371,6 +410,7 @@ void TimingConfDialog_t::updatePolicyBox(void) void TimingConfDialog_t::updateSliderValues(void) { int policy, prio; + bool hasNicePerms; if ( consoleWindow == NULL ) { @@ -391,6 +431,10 @@ void TimingConfDialog_t::updateSliderValues(void) emuSchedPrioLabel->setEnabled(false); emuSchedPrioSlider->setEnabled(false); } + hasNicePerms = hasNicePermissions( consoleWindow->emulatorThread->getNicePriority() ); + + emuSchedNiceLabel->setEnabled( hasNicePerms ); + emuSchedNiceSlider->setEnabled( hasNicePerms ); consoleWindow->getSchedParam( policy, prio ); @@ -407,6 +451,11 @@ void TimingConfDialog_t::updateSliderValues(void) guiSchedPrioLabel->setEnabled(false); guiSchedPrioSlider->setEnabled(false); } + hasNicePerms = hasNicePermissions( consoleWindow->getNicePriority() ); + + guiSchedNiceLabel->setEnabled( hasNicePerms ); + guiSchedNiceSlider->setEnabled( hasNicePerms ); + } //---------------------------------------------------------------------------- void TimingConfDialog_t::updateSliderLimits(void) diff --git a/src/drivers/Qt/TimingConf.h b/src/drivers/Qt/TimingConf.h index 11af5fd9..71075177 100644 --- a/src/drivers/Qt/TimingConf.h +++ b/src/drivers/Qt/TimingConf.h @@ -35,10 +35,12 @@ class TimingConfDialog_t : public QDialog QSlider *emuSchedPrioSlider; QSlider *emuSchedNiceSlider; QLabel *emuSchedPrioLabel; + QLabel *emuSchedNiceLabel; QComboBox *guiSchedPolicyBox; QSlider *guiSchedPrioSlider; QSlider *guiSchedNiceSlider; QLabel *guiSchedPrioLabel; + QLabel *guiSchedNiceLabel; private: void updatePolicyBox(void); From 961aa83a517fa4364a3d18794c8f419144ed3953 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Sat, 28 Nov 2020 20:43:34 -0500 Subject: [PATCH 10/14] Bug fixes for Qt timing priority configs. --- src/drivers/Qt/ConsoleWindow.cpp | 8 ++++++++ src/drivers/Qt/TimingConf.cpp | 19 +++++++++++++------ src/drivers/Qt/config.cpp | 4 ++-- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index 4921487a..86c4a69f 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -1877,6 +1877,7 @@ int consoleWin_t::getSchedParam( int &policy, int &priority ) if ( sched_getparam( getpid(), &p ) ) { + perror("GUI thread sched_getparam error: "); ret = -1; priority = 0; } @@ -1892,6 +1893,11 @@ int consoleWin_t::getSchedParam( int &policy, int &priority ) { perror("GUI thread pthread_getschedparam error: "); ret = -1; + priority = 0; + } + else + { + priority = p.sched_priority; } #endif return ret; @@ -2193,6 +2199,8 @@ int emulatorThread_t::getSchedParam( int &policy, int &priority ) perror("Emulator thread pthread_getschedparam error: "); return -1; } + priority = p.sched_priority; + return 0; } diff --git a/src/drivers/Qt/TimingConf.cpp b/src/drivers/Qt/TimingConf.cpp index b5ef59e8..5996e9b6 100644 --- a/src/drivers/Qt/TimingConf.cpp +++ b/src/drivers/Qt/TimingConf.cpp @@ -60,7 +60,7 @@ TimingConfDialog_t::TimingConfDialog_t(QWidget *parent) : QDialog( parent ) { int opt; - QVBoxLayout *mainLayout, *vbox; + QVBoxLayout *mainLayout; //QHBoxLayout *hbox; QGridLayout *grid; QGroupBox *emuPrioBox, *guiPrioBox; @@ -140,6 +140,7 @@ TimingConfDialog_t::TimingConfDialog_t(QWidget *parent) TimingConfDialog_t::~TimingConfDialog_t(void) { printf("Destroy Timing Config Window\n"); + saveValues(); } //---------------------------------------------------------------------------- void TimingConfDialog_t::closeEvent(QCloseEvent *event) @@ -148,7 +149,6 @@ void TimingConfDialog_t::closeEvent(QCloseEvent *event) done(0); deleteLater(); event->accept(); - saveValues(); } //---------------------------------------------------------------------------- void TimingConfDialog_t::closeWindow(void) @@ -156,7 +156,6 @@ void TimingConfDialog_t::closeWindow(void) //printf("Close Window\n"); done(0); deleteLater(); - saveValues(); } //---------------------------------------------------------------------------- void TimingConfDialog_t::emuSchedCtlChange( int state ) @@ -166,23 +165,31 @@ void TimingConfDialog_t::emuSchedCtlChange( int state ) //---------------------------------------------------------------------------- void TimingConfDialog_t::saveValues(void) { - int policy, prio; + int policy, prio, nice; if ( consoleWindow == NULL ) { return; } + nice = consoleWindow->emulatorThread->getNicePriority(); + consoleWindow->emulatorThread->getSchedParam( policy, prio ); g_config->setOption( "SDL.EmuSchedPolicy", policy ); g_config->setOption( "SDL.EmuSchedPrioRt", prio ); - g_config->setOption( "SDL.EmuSchedNice" , consoleWindow->emulatorThread->getNicePriority() ); + g_config->setOption( "SDL.EmuSchedNice" , nice ); + + //printf("EMU Sched: %i %i %i\n", policy, prio, nice ); + + nice = consoleWindow->getNicePriority(); consoleWindow->getSchedParam( policy, prio ); g_config->setOption( "SDL.GuiSchedPolicy", policy ); g_config->setOption( "SDL.GuiSchedPrioRt", prio ); - g_config->setOption( "SDL.GuiSchedNice" , consoleWindow->getNicePriority() ); + g_config->setOption( "SDL.GuiSchedNice" , nice ); + + //printf("GUI Sched: %i %i %i\n", policy, prio, nice ); g_config->save(); } diff --git a/src/drivers/Qt/config.cpp b/src/drivers/Qt/config.cpp index 42ca7dc6..7463851a 100644 --- a/src/drivers/Qt/config.cpp +++ b/src/drivers/Qt/config.cpp @@ -317,10 +317,10 @@ InitConfig() config->addOption("_setSchedParam" , "SDL.SetSchedParam" , 0); config->addOption("_emuSchedPolicy" , "SDL.EmuSchedPolicy", 0); - config->addOption("_emuSchedNice" , "SDL.EmuSchedNice ", 0); + config->addOption("_emuSchedNice" , "SDL.EmuSchedNice" , 0); config->addOption("_emuSchedPrioRt" , "SDL.EmuSchedPrioRt", 40); config->addOption("_guiSchedPolicy" , "SDL.GuiSchedPolicy", 0); - config->addOption("_guiSchedNice" , "SDL.GuiSchedNice ", 0); + config->addOption("_guiSchedNice" , "SDL.GuiSchedNice" , 0); config->addOption("_guiSchedPrioRt" , "SDL.GuiSchedPrioRt", 40); // fcm -> fm2 conversion From f198996cd48d29d9cb77a0853975078f2471cbb3 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Sat, 28 Nov 2020 21:03:26 -0500 Subject: [PATCH 11/14] Added logic to auto set process scheduling priorities at startup. --- src/drivers/Qt/ConsoleWindow.cpp | 110 +++++++++---------------------- 1 file changed, 32 insertions(+), 78 deletions(-) diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index 86c4a69f..12b34921 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -60,6 +60,7 @@ consoleWin_t::consoleWin_t(QWidget *parent) : QMainWindow( parent ) { + int opt; int use_SDL_video = false; int setFullScreen = false; @@ -105,12 +106,24 @@ consoleWin_t::consoleWin_t(QWidget *parent) connect( gameTimer, &QTimer::timeout, this, &consoleWin_t::updatePeriodic ); gameTimer->setTimerType( Qt::PreciseTimer ); - //gameTimer->start( 16 ); // 60hz gameTimer->start( 8 ); // 120hz emulatorThread->start(); - //setPriority( QThread::TimeCriticalPriority ); + g_config->getOption( "SDL.SetSchedParam", &opt ); + + if ( opt ) + { + int policy, prio, nice; + + g_config->getOption( "SDL.GuiSchedPolicy", &policy ); + g_config->getOption( "SDL.GuiSchedPrioRt", &prio ); + g_config->getOption( "SDL.GuiSchedNice" , &nice ); + + setNicePriority( nice ); + + setSchedParam( policy, prio ); + } } consoleWin_t::~consoleWin_t(void) @@ -1953,82 +1966,6 @@ int consoleWin_t::setSchedParam( int policy, int priority ) return ret; } - -//void consoleWin_t::setPriority( QThread::Priority priority_req ) -//{ -//#if defined(__linux__) -// struct sched_param p; -// int minPrio, maxPrio; -// -// minPrio = sched_get_priority_min( SCHED_FIFO ); -// maxPrio = sched_get_priority_max( SCHED_FIFO ); -// -// p.sched_priority = maxPrio; -// -// if ( ::setpriority( PRIO_PROCESS, getpid(), -20 ) ) -// { -// perror("Qt Window thread setpriority error "); -// } -// printf("sched_getscheduler(): %i \n", sched_getscheduler( getpid() ) ); -// printf("sched_get_priority_min(SCHED_FIFO): %i \n", minPrio ); -// printf("sched_get_priority_max(SCHED_FIFO): %i \n", maxPrio ); -// -// printf("setpriority(): %i \n", ::getpriority( PRIO_PROCESS, getpid() ) ); -// -// if ( sched_setscheduler( getpid(), SCHED_FIFO, &p ) ) -// { -// perror("Qt Window thread sched_setscheduler error:"); -// } -// printf("sched_getscheduler(): %i \n", sched_getscheduler( getpid() ) ); -// -//#elif defined(__APPLE__) -// -// struct sched_param p; -// int oldPolicy, newPolicy, minPrio, maxPrio; -// QThread *qself; -// pthread_t self; -// -// qself = QThread::currentThread(); -// -// self = pthread_self(); -// newPolicy = SCHED_FIFO; -// -// printf("QThreadID: %p \n", QThread::currentThreadId() ); -// printf("PThreadID: %p \n", self ); -// -// minPrio = sched_get_priority_min( SCHED_FIFO ); -// maxPrio = sched_get_priority_max( SCHED_FIFO ); -// -// pthread_getschedparam( self, &oldPolicy, &p ); -// -// printf("GUI pthread_getschedparam(): %i, %i \n", oldPolicy, p.sched_priority ); -// -// qself->setPriority( priority_req ); -// -// p.sched_priority = maxPrio; -// -// //if ( ::pthread_setschedparam( self, newPolicy, &p ) != 0 ) -// //{ -// //perror("GUI thread pthread_setschedparam error: "); -// //} -// pthread_getschedparam( self, &oldPolicy, &p ); -// -// printf("GUI pthread_getschedparam(): %i, %i \n", oldPolicy, p.sched_priority ); -// -// if ( ::setpriority( PRIO_PROCESS, getpid(), -20 ) ) -// { -// perror("GUI thread setpriority error: "); -// } -// printf("GUI Thread setpriority(): %i \n", ::getpriority( PRIO_PROCESS, getpid() ) ); -//#else -// QThread *mainThread; -// -// mainThread = QThread::currentThread(); -// -// mainThread->setPriority( priority_req ); -//#endif -//} - void consoleWin_t::syncActionConfig( QAction *act, const char *property ) { if ( act->isCheckable() ) @@ -2099,6 +2036,8 @@ emulatorThread_t::emulatorThread_t(void) void emulatorThread_t::init(void) { + int opt; + #if defined(__linux__) || defined(__APPLE__) if ( pthread_self() == (pthread_t)QThread::currentThreadId() ) { @@ -2112,6 +2051,21 @@ void emulatorThread_t::init(void) #elif defined(__APPLE__) pid = getpid(); #endif + + g_config->getOption( "SDL.SetSchedParam", &opt ); + + if ( opt ) + { + int policy, prio, nice; + + g_config->getOption( "SDL.EmuSchedPolicy", &policy ); + g_config->getOption( "SDL.EmuSchedPrioRt", &prio ); + g_config->getOption( "SDL.EmuSchedNice" , &nice ); + + setNicePriority( nice ); + + setSchedParam( policy, prio ); + } } void emulatorThread_t::setPriority( QThread::Priority priority_req ) From 4812c804fd65f987cee2c26fbb41c0d63e3ef882 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Sat, 28 Nov 2020 21:46:41 -0500 Subject: [PATCH 12/14] Added timing options selection combo box to timing window on Qt GUI. --- src/drivers/Qt/TimingConf.cpp | 50 ++++++++++++++++++++++++++++++++- src/drivers/Qt/TimingConf.h | 3 ++ src/drivers/Qt/config.cpp | 1 + src/drivers/Qt/fceuWrapper.cpp | 9 ++++++ src/drivers/Qt/sdl-throttle.cpp | 23 +++++++++++++-- src/drivers/Qt/throttle.h | 5 +++- 6 files changed, 87 insertions(+), 4 deletions(-) diff --git a/src/drivers/Qt/TimingConf.cpp b/src/drivers/Qt/TimingConf.cpp index 5996e9b6..7dc92dbc 100644 --- a/src/drivers/Qt/TimingConf.cpp +++ b/src/drivers/Qt/TimingConf.cpp @@ -19,6 +19,7 @@ #include "Qt/input.h" #include "Qt/config.h" #include "Qt/keyscan.h" +#include "Qt/throttle.h" #include "Qt/fceuWrapper.h" #include "Qt/ConsoleWindow.h" #include "Qt/TimingConf.h" @@ -61,7 +62,7 @@ TimingConfDialog_t::TimingConfDialog_t(QWidget *parent) { int opt; QVBoxLayout *mainLayout; - //QHBoxLayout *hbox; + QHBoxLayout *hbox; QGridLayout *grid; QGroupBox *emuPrioBox, *guiPrioBox; @@ -118,6 +119,17 @@ TimingConfDialog_t::TimingConfDialog_t(QWidget *parent) mainLayout->addWidget( guiPrioBox ); + hbox = new QHBoxLayout(); + timingDevSelBox = new QComboBox(); + timingDevSelBox->addItem( tr("NanoSleep") , 0 ); + +#ifdef __linux__ + timingDevSelBox->addItem( tr("Timer FD") , 1 ); +#endif + hbox->addWidget( new QLabel( tr("Timing Mechanism:") ) ); + hbox->addWidget( timingDevSelBox ); + mainLayout->addLayout( hbox ); + setLayout( mainLayout ); g_config->getOption( "SDL.SetSchedParam", &opt ); @@ -127,6 +139,7 @@ TimingConfDialog_t::TimingConfDialog_t(QWidget *parent) updatePolicyBox(); updateSliderLimits(); updateSliderValues(); + updateTimingMech(); connect( emuSchedPolicyBox , SIGNAL(activated(int)) , this, SLOT(emuSchedPolicyChange(int)) ); connect( emuSchedNiceSlider , SIGNAL(valueChanged(int)), this, SLOT(emuSchedNiceChange(int)) ); @@ -135,6 +148,7 @@ TimingConfDialog_t::TimingConfDialog_t(QWidget *parent) connect( guiSchedNiceSlider , SIGNAL(valueChanged(int)), this, SLOT(guiSchedNiceChange(int)) ); connect( guiSchedPrioSlider , SIGNAL(valueChanged(int)), this, SLOT(guiSchedPrioChange(int)) ); connect( emuPrioCtlEna , SIGNAL(stateChanged(int)), this, SLOT(emuSchedCtlChange(int)) ); + connect( timingDevSelBox , SIGNAL(activated(int)) , this, SLOT(emuTimingMechChange(int)) ); } //---------------------------------------------------------------------------- TimingConfDialog_t::~TimingConfDialog_t(void) @@ -484,3 +498,37 @@ void TimingConfDialog_t::updateSliderLimits(void) } //---------------------------------------------------------------------------- +void TimingConfDialog_t::emuTimingMechChange( int index ) +{ + int mode; + + if ( consoleWindow == NULL ) + { + return; + } + fceuWrapperLock(); + + mode = timingDevSelBox->itemData( index ).toInt(); + + setTimingMode( mode ); + + RefreshThrottleFPS(); + + g_config->setOption("SDL.EmuTimingMech", mode); + + fceuWrapperUnLock(); +} +//---------------------------------------------------------------------------- +void TimingConfDialog_t::updateTimingMech(void) +{ + int mode = getTimingMode(); + + for (int j=0; jcount(); j++) + { + if ( timingDevSelBox->itemData(j).toInt() == mode ) + { + timingDevSelBox->setCurrentIndex( j ); + } + } +} +//---------------------------------------------------------------------------- diff --git a/src/drivers/Qt/TimingConf.h b/src/drivers/Qt/TimingConf.h index 71075177..51b3d8e7 100644 --- a/src/drivers/Qt/TimingConf.h +++ b/src/drivers/Qt/TimingConf.h @@ -41,11 +41,13 @@ class TimingConfDialog_t : public QDialog QSlider *guiSchedNiceSlider; QLabel *guiSchedPrioLabel; QLabel *guiSchedNiceLabel; + QComboBox *timingDevSelBox; private: void updatePolicyBox(void); void updateSliderLimits(void); void updateSliderValues(void); + void updateTimingMech(void); void saveValues(void); public slots: @@ -58,5 +60,6 @@ class TimingConfDialog_t : public QDialog void guiSchedNiceChange( int val ); void guiSchedPrioChange( int val ); void guiSchedPolicyChange( int index ); + void emuTimingMechChange( int index ); }; diff --git a/src/drivers/Qt/config.cpp b/src/drivers/Qt/config.cpp index 7463851a..125f017f 100644 --- a/src/drivers/Qt/config.cpp +++ b/src/drivers/Qt/config.cpp @@ -322,6 +322,7 @@ InitConfig() config->addOption("_guiSchedPolicy" , "SDL.GuiSchedPolicy", 0); config->addOption("_guiSchedNice" , "SDL.GuiSchedNice" , 0); config->addOption("_guiSchedPrioRt" , "SDL.GuiSchedPrioRt", 40); + config->addOption("_emuTimingMech" , "SDL.EmuTimingMech" , 0); // fcm -> fm2 conversion config->addOption("fcmconvert", "SDL.FCMConvert", ""); diff --git a/src/drivers/Qt/fceuWrapper.cpp b/src/drivers/Qt/fceuWrapper.cpp index 6edcd4e5..79abd540 100644 --- a/src/drivers/Qt/fceuWrapper.cpp +++ b/src/drivers/Qt/fceuWrapper.cpp @@ -737,6 +737,15 @@ int fceuWrapperInit( int argc, char *argv[] ) g_config->getOption("SDL.SubtitleDisplay", &id); movieSubtitles = id ? true : false; } + + // Emulation Timing Mechanism + { + int timingMode; + + g_config->getOption("SDL.EmuTimingMech", &timingMode); + + setTimingMode( timingMode ); + } // load the hotkeys from the config life setHotKeys(); diff --git a/src/drivers/Qt/sdl-throttle.cpp b/src/drivers/Qt/sdl-throttle.cpp index 5d3e9833..56329582 100644 --- a/src/drivers/Qt/sdl-throttle.cpp +++ b/src/drivers/Qt/sdl-throttle.cpp @@ -47,7 +47,7 @@ double getHighPrecTimeStamp(void) } #ifdef __linux__ -static char useTimerFD = 1; +static char useTimerFD = 0; static int timerfd = -1; static void setTimer( double hz ) @@ -83,7 +83,7 @@ static void setTimer( double hz ) perror("timerfd_settime failed: "); } - printf("Timer Set: %li ns\n", ispec.it_value.tv_nsec ); + //printf("Timer Set: %li ns\n", ispec.it_value.tv_nsec ); Lasttime = getHighPrecTimeStamp(); Nexttime = Lasttime + desired_frametime; @@ -91,6 +91,25 @@ static void setTimer( double hz ) } #endif +int getTimingMode(void) +{ +#ifdef __linux__ + if ( useTimerFD ) + { + return 1; + } +#endif + return 0; +} + +int setTimingMode( int mode ) +{ +#ifdef __linux__ + useTimerFD = (mode == 1); +#endif + return 0; +} + /* LOGMUL = exp(log(2) / 3) * * This gives us a value such that if we do x*=LOGMUL three times, diff --git a/src/drivers/Qt/throttle.h b/src/drivers/Qt/throttle.h index 5709c88a..410ebff9 100644 --- a/src/drivers/Qt/throttle.h +++ b/src/drivers/Qt/throttle.h @@ -1,2 +1,5 @@ -void RefreshThrottleFPS(); +// throttle.h int SpeedThrottle(void); +void RefreshThrottleFPS(void); +int getTimingMode(void); +int setTimingMode(int mode); From 35e0bc441f63696c0e531c6fbc3162623f298599 Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Sat, 28 Nov 2020 21:55:55 -0500 Subject: [PATCH 13/14] Removed debug print statement. --- src/drivers/Qt/ConsoleWindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/Qt/ConsoleWindow.cpp b/src/drivers/Qt/ConsoleWindow.cpp index 12b34921..fe910d7e 100644 --- a/src/drivers/Qt/ConsoleWindow.cpp +++ b/src/drivers/Qt/ConsoleWindow.cpp @@ -2042,7 +2042,7 @@ void emulatorThread_t::init(void) if ( pthread_self() == (pthread_t)QThread::currentThreadId() ) { pself = pthread_self(); - printf("EMU is using PThread: %p\n", (void*)pself); + //printf("EMU is using PThread: %p\n", (void*)pself); } #endif From d13c1518178bbc34debcffa2ce7627f31a9804ca Mon Sep 17 00:00:00 2001 From: Matthew Budd Date: Sat, 28 Nov 2020 22:05:39 -0500 Subject: [PATCH 14/14] Default Qt GUI Timing statistics calcutions to off. TODO make timing stats enable via GUI. --- src/drivers/Qt/sdl-throttle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/drivers/Qt/sdl-throttle.cpp b/src/drivers/Qt/sdl-throttle.cpp index 56329582..f94612b8 100644 --- a/src/drivers/Qt/sdl-throttle.cpp +++ b/src/drivers/Qt/sdl-throttle.cpp @@ -21,7 +21,7 @@ static double Lasttime=0, Nexttime=0, Latetime=0; static double desired_frametime = (1.0 / 60.099823); static double frameDeltaMin = 99999.0; static double frameDeltaMax = 0.0; -static bool keepFrameTimeStats = true; +static bool keepFrameTimeStats = false; static int InFrame = 0; double g_fpsScale = Normal; // used by sdl.cpp bool MaxSpeed = false;