shithub: choc

Download patch

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