mirror of
https://github.com/86Box/86Box.git
synced 2026-02-22 09:35:32 -07:00
Call timeBeginPeriod only once on startup (#6273)
Use SetProcessInformation to make the OS better handle our threads on big/small cores
This commit is contained in:
@@ -98,6 +98,7 @@ extern "C" {
|
||||
#include <86box/timer.h>
|
||||
#include <86box/nvr.h>
|
||||
extern int qt_nvr_save(void);
|
||||
extern void exit_pause(void);
|
||||
|
||||
bool cpu_thread_running = false;
|
||||
}
|
||||
@@ -753,6 +754,14 @@ main(int argc, char *argv[])
|
||||
discord_load();
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
// On Win32 the accuracy of Sleep() depends on the timer resolution, which can be set by calling timeBeginPeriod
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/timeapi/nf-timeapi-timebeginperiod
|
||||
exit_pause();
|
||||
timeBeginPeriod(1);
|
||||
atexit([] () -> void { timeEndPeriod(1); });
|
||||
#endif
|
||||
|
||||
main_window = new MainWindow();
|
||||
if (startMaximized) {
|
||||
main_window->showMaximized();
|
||||
|
||||
@@ -453,6 +453,65 @@ plat_munmap(void *ptr, size_t size)
|
||||
}
|
||||
|
||||
extern bool cpu_thread_running;
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
/* SetThreadDescription was added in 14393 and SetProcessInformation in 8. Revisit if we ever start requiring 10. */
|
||||
static void *kernel32_handle = NULL;
|
||||
static HRESULT(WINAPI *pSetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription) = NULL;
|
||||
static HRESULT(WINAPI *pSetProcessInformation)(HANDLE hProcess, PROCESS_INFORMATION_CLASS ProcessInformationClass, LPVOID ProcessInformation, DWORD ProcessInformationSize) = NULL;
|
||||
static dllimp_t kernel32_imports[] = {
|
||||
// clang-format off
|
||||
{ "SetThreadDescription", &pSetThreadDescription },
|
||||
{ "SetProcessInformation", &pSetProcessInformation },
|
||||
{ NULL, NULL }
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
static void
|
||||
enter_pause(void)
|
||||
{
|
||||
PROCESS_POWER_THROTTLING_STATE state{};
|
||||
state.Version = PROCESS_POWER_THROTTLING_CURRENT_VERSION;
|
||||
state.ControlMask = PROCESS_POWER_THROTTLING_EXECUTION_SPEED | PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION;
|
||||
state.StateMask = PROCESS_POWER_THROTTLING_EXECUTION_SPEED | PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION;
|
||||
|
||||
if (!kernel32_handle) {
|
||||
kernel32_handle = dynld_module("kernel32.dll", kernel32_imports);
|
||||
if (!kernel32_handle) {
|
||||
kernel32_handle = kernel32_imports; /* store dummy pointer to avoid trying again */
|
||||
pSetThreadDescription = NULL;
|
||||
pSetProcessInformation = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (pSetProcessInformation) {
|
||||
pSetProcessInformation(GetCurrentProcess(), ProcessPowerThrottling, (LPVOID)&state, sizeof(state));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
exit_pause(void)
|
||||
{
|
||||
PROCESS_POWER_THROTTLING_STATE state{};
|
||||
state.Version = PROCESS_POWER_THROTTLING_CURRENT_VERSION;
|
||||
state.ControlMask = PROCESS_POWER_THROTTLING_EXECUTION_SPEED | PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION;
|
||||
state.StateMask = 0;
|
||||
|
||||
if (!kernel32_handle) {
|
||||
kernel32_handle = dynld_module("kernel32.dll", kernel32_imports);
|
||||
if (!kernel32_handle) {
|
||||
kernel32_handle = kernel32_imports; /* store dummy pointer to avoid trying again */
|
||||
pSetThreadDescription = NULL;
|
||||
pSetProcessInformation = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (pSetProcessInformation) {
|
||||
pSetProcessInformation(GetCurrentProcess(), ProcessPowerThrottling, (LPVOID)&state, sizeof(state));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
plat_pause(int p)
|
||||
{
|
||||
@@ -477,6 +536,14 @@ plat_pause(int p)
|
||||
if ((p == 0) && (time_sync & TIME_SYNC_ENABLED))
|
||||
nvr_time_sync();
|
||||
|
||||
#ifdef Q_OS_WINDOWS
|
||||
if (p) {
|
||||
enter_pause();
|
||||
} else {
|
||||
exit_pause();
|
||||
}
|
||||
#endif
|
||||
|
||||
do_pause(p);
|
||||
if (p) {
|
||||
if (mouse_capture)
|
||||
@@ -842,21 +909,12 @@ void
|
||||
plat_set_thread_name(void *thread, const char *name)
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
/* SetThreadDescription was added in 14393. Revisit if we ever start requiring 10. */
|
||||
static void *kernel32_handle = NULL;
|
||||
static HRESULT(WINAPI *pSetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription) = NULL;
|
||||
static dllimp_t kernel32_imports[] = {
|
||||
// clang-format off
|
||||
{ "SetThreadDescription", &pSetThreadDescription },
|
||||
{ NULL, NULL }
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
if (!kernel32_handle) {
|
||||
kernel32_handle = dynld_module("kernel32.dll", kernel32_imports);
|
||||
if (!kernel32_handle) {
|
||||
kernel32_handle = kernel32_imports; /* store dummy pointer to avoid trying again */
|
||||
pSetThreadDescription = NULL;
|
||||
pSetProcessInformation = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,11 +65,7 @@ void
|
||||
plat_delay_ms(uint32_t count)
|
||||
{
|
||||
#ifdef Q_OS_WINDOWS
|
||||
// On Win32 the accuracy of Sleep() depends on the timer resolution, which can be set by calling timeBeginPeriod
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/timeapi/nf-timeapi-timebeginperiod
|
||||
timeBeginPeriod(1);
|
||||
Sleep(count);
|
||||
timeEndPeriod(1);
|
||||
#else
|
||||
QThread::msleep(count);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user