diff --git a/prboom2/CMakeLists.txt b/prboom2/CMakeLists.txt index d317ddec..c86f76b0 100644 --- a/prboom2/CMakeLists.txt +++ b/prboom2/CMakeLists.txt @@ -53,6 +53,15 @@ endif() check_symbol_exists(getopt "unistd.h" HAVE_GETOPT) check_symbol_exists(mmap "sys/mman.h" HAVE_MMAP) check_symbol_exists(CreateFileMapping "windows.h" HAVE_CREATE_FILE_MAPPING) +if(NOT WIN32) + set(CMAKE_REQUIRED_DEFINITIONS_PREV ${CMAKE_REQUIRED_DEFINITIONS}) + set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -D_GNU_SOURCE) + check_symbol_exists(sched_setaffinity "sched.h" HAVE_SCHED_SETAFFINITY) + set(CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS_PREV}) + if(HAVE_SCHED_SETAFFINITY) + add_definitions(-D_GNU_SOURCE) + endif() +endif() check_symbol_exists(strsignal "string.h" HAVE_STRSIGNAL) check_symbol_exists(mkstemp "stdlib.h" HAVE_MKSTEMP) diff --git a/prboom2/cmake/config.h.cin b/prboom2/cmake/config.h.cin index f92f3d88..2ad70033 100644 --- a/prboom2/cmake/config.h.cin +++ b/prboom2/cmake/config.h.cin @@ -11,6 +11,7 @@ #cmakedefine HAVE_GETOPT #cmakedefine HAVE_MMAP #cmakedefine HAVE_CREATE_FILE_MAPPING +#cmakedefine HAVE_SCHED_SETAFFINITY #cmakedefine HAVE_STRSIGNAL #cmakedefine HAVE_MKSTEMP diff --git a/prboom2/src/SDL/i_main.c b/prboom2/src/SDL/i_main.c index 7537c53f..670f3dbd 100644 --- a/prboom2/src/SDL/i_main.c +++ b/prboom2/src/SDL/i_main.c @@ -45,6 +45,9 @@ #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include +typedef BOOL (WINAPI *SetAffinityFunc)(HANDLE hProcess, DWORD mask); +#else +#include #endif #include @@ -373,6 +376,83 @@ static void I_Quit (void) uid_t stored_euid = -1; #endif +// +// Ability to use only the allowed CPUs +// + +static void I_SetAffinityMask(void) +{ + // This was only set for the sdl music backend, + // but now the backend changes based on the music type. + // Not sure what the consequences are for this... + process_affinity_mask = 1; + + // Set the process affinity mask so that all threads + // run on the same processor. This is a workaround for a bug in + // SDL_mixer that causes occasional crashes. + if (process_affinity_mask) + { + const char *errbuf = NULL; +#ifdef _WIN32 + HMODULE kernel32_dll; + SetAffinityFunc SetAffinity = NULL; + int ok = false; + + // Find the kernel interface DLL. + kernel32_dll = LoadLibrary("kernel32.dll"); + + if (kernel32_dll) + { + // Find the SetProcessAffinityMask function. + SetAffinity = (SetAffinityFunc)GetProcAddress(kernel32_dll, "SetProcessAffinityMask"); + + // If the function was not found, we are on an old (Win9x) system + // that doesn't have this function. That's no problem, because + // those systems don't support SMP anyway. + + if (SetAffinity) + { + ok = SetAffinity(GetCurrentProcess(), process_affinity_mask); + } + } + + if (!ok) + { + errbuf = WINError(); + } +#elif defined(HAVE_SCHED_SETAFFINITY) + // POSIX version: + int i; + { + cpu_set_t set; + + CPU_ZERO(&set); + + for(i = 0; i < 16; i++) + { + CPU_SET((process_affinity_mask>>i)&1, &set); + } + + if (sched_setaffinity(getpid(), sizeof(set), &set) == -1) + { + errbuf = strerror(errno); + } + } +#else + return; +#endif + + if (errbuf == NULL) + { + lprintf(LO_INFO, "I_SetAffinityMask: manual affinity mask is %d\n", process_affinity_mask); + } + else + { + lprintf(LO_ERROR, "I_SetAffinityMask: failed to set process affinity mask (%s)\n", errbuf); + } + } +} + // // Sets the priority class for the prboom-plus process // @@ -482,6 +562,9 @@ int main(int argc, char **argv) signal(SIGABRT, I_SignalHandler); #endif + // Ability to use only the allowed CPUs + I_SetAffinityMask(); + // Priority class for the prboom-plus process I_SetProcessPriority(); diff --git a/prboom2/src/SDL/i_video.c b/prboom2/src/SDL/i_video.c index 5a564a5a..9b68aee7 100644 --- a/prboom2/src/SDL/i_video.c +++ b/prboom2/src/SDL/i_video.c @@ -895,6 +895,7 @@ static void I_ClosestResolution (int *width, int *height) } } +int process_affinity_mask; int process_priority; // e6y diff --git a/prboom2/src/i_video.h b/prboom2/src/i_video.h index 46f0fb71..c39a197e 100644 --- a/prboom2/src/i_video.h +++ b/prboom2/src/i_video.h @@ -109,6 +109,8 @@ void I_UpdateRenderSize(void); // Handle potential extern int renderW; // resolution scaling extern int renderH; // - DTIED +// Set the process affinity mask so that all threads +extern int process_affinity_mask; // Priority class for the prboom-plus process extern int process_priority; // Use vanilla keybaord mapping