ref: cdd3680b9e94640cc4956ae30de734cbe1e9bf76
parent: 39b7cb7bb2e14169af5dc07c7d429fc939200639
author: Simon Howard <fraggle@gmail.com>
date: Tue Mar 3 14:26:20 EST 2009
Look up SetProcessAffinityMask function at runtime, so that the program should work under Win9x again. Subversion-branch: /trunk/chocolate-doom Subversion-revision: 1443
--- a/src/i_main.c
+++ b/src/i_main.c
@@ -46,46 +46,90 @@
#include "m_argv.h"
#include "d_main.h"
-#if !defined(_WIN32) && !defined(HAVE_SCHED_SETAFFINITY)
-#warning No known way to set processor affinity on this platform.
-#warning You may experience crashes due to SDL_mixer.
-#endif
+#if defined(_WIN32)
-int main(int argc, char **argv)
-{
- // save arguments
+typedef BOOL WINAPI (*SetAffinityFunc)(HANDLE hProcess, DWORD_PTR mask);
- myargc = argc;
- myargv = argv;
+// This is a bit more complicated than it really needs to be. We really
+// just need to call the SetProcessAffinityMask function, but that
+// function doesn't exist on systems before Windows 2000. Instead,
+// dynamically look up the function and call the pointer to it. This
+// way, the program will run on older versions of Windows (Win9x, etc.)
-#ifdef _WIN32
+static void LockCPUAffinity(void)
+{
+ HMODULE kernel32_dll;
+ SetAffinityFunc SetAffinity;
- // 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.
+ // Find the kernel interface DLL.
- if (!SetProcessAffinityMask(GetCurrentProcess(), 1))
+ kernel32_dll = LoadLibrary("kernel32.dll");
+
+ if (kernel32_dll == NULL)
{
- fprintf(stderr, "Failed to set process affinity mask (%d)\n",
- (int) GetLastError());
+ // This should never happen...
+
+ fprintf(stderr, "Failed to load kernel32.dll\n");
+ return;
}
-#endif
+ // Find the SetProcessAffinityMask function.
-#ifdef HAVE_SCHED_SETAFFINITY
+ SetAffinity = GetProcAddress(kernel32_dll, "SetProcessAffinityMask");
- // Linux version:
+ // 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 != NULL)
{
- cpu_set_t set;
+ if (!SetAffinity(GetCurrentProcess(), 1))
+ {
+ fprintf(stderr, "Failed to set process affinity (%d)\n",
+ (int) GetLastError());
+ }
+ }
+}
- CPU_ZERO(&set);
- CPU_SET(0, &set);
+#elif defined(HAVE_SCHED_SETAFFINITY)
- sched_setaffinity(getpid(), sizeof(set), &set);
- }
+// Unix (Linux) version:
+static void LockCPUAffinity(void)
+{
+ cpu_set_t set;
+
+ CPU_ZERO(&set);
+ CPU_SET(0, &set);
+
+ sched_setaffinity(getpid(), sizeof(set), &set);
+}
+
+#else
+
+#warning No known way to set processor affinity on this platform.
+#warning You may experience crashes due to SDL_mixer.
+
+static void LockCPUAffinity(void)
+{
+ fprintf(stderr,
+ "WARNING: No known way to set processor affinity on this platform.\n"
+ " You may experience crashes due to SDL_mixer.\n");
+}
+
#endif
+
+int main(int argc, char **argv)
+{
+ // save arguments
+
+ myargc = argc;
+ myargv = argv;
+
+ // Only schedule on a single core, if we have multiple
+ // cores. This is to work around a bug in SDL_mixer.
+
+ LockCPUAffinity();
// start doom