Fix _SC_NPROCESSORS_ONLN on Windows
authorBruce Cran <bruce@cran.org.uk>
Mon, 21 Jan 2013 17:57:59 +0000 (10:57 -0700)
committerJens Axboe <axboe@kernel.dk>
Mon, 21 Jan 2013 17:57:59 +0000 (10:57 -0700)
_SC_NPROCESSORS_ONLN was returning the wrong value on Windows because
GetLogicalProcessorInformation() returns data about caches, nodes and
packages in addition to processors.

Modified by Jens to use hweight32()

Signed-off-by: Jens Axboe <axboe@kernel.dk>
os/windows/posix.c

index 8b45147..c4d738c 100755 (executable)
@@ -20,6 +20,7 @@
 #include <sys/poll.h>
 
 #include "../os-windows.h"
+#include "../../lib/hweight.h"
 
 extern unsigned long mtime_since_now(struct timeval *);
 extern void fio_gettime(struct timeval *, void *);
@@ -42,20 +43,52 @@ int vsprintf_s(
   const char *format,
   va_list argptr);
 
+int GetNumLogicalProcessors(void)
+{
+       SYSTEM_LOGICAL_PROCESSOR_INFORMATION *processor_info = NULL;
+       DWORD len = 0;
+       DWORD num_processors = 0;
+       DWORD error = 0;
+       DWORD i;
+
+       while (!GetLogicalProcessorInformation(processor_info, &len)) {
+               error = GetLastError();
+               if (error == ERROR_INSUFFICIENT_BUFFER)
+                       processor_info = malloc(len);
+               else {
+                       log_err("Error: GetLogicalProcessorInformation failed: %d\n", error);
+                       return -1;
+               }
+
+               if (processor_info == NULL) {
+                       log_err("Error: failed to allocate memory for GetLogicalProcessorInformation");
+                       return -1;
+               }
+       }
+
+       for (i = 0; i < len / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); i++)
+       {
+               if (processor_info[i].Relationship == RelationProcessorCore)
+                       num_processors += hweight32(processor_info[i].ProcessorMask);
+       }
+
+       free(processor_info);
+       return num_processors;
+}
+
 long sysconf(int name)
 {
-       long long val = -1;
-       DWORD len;
-       SYSTEM_LOGICAL_PROCESSOR_INFORMATION processorInfo;
+       long val = -1;
        SYSTEM_INFO sysInfo;
        MEMORYSTATUSEX status;
 
        switch (name)
        {
        case _SC_NPROCESSORS_ONLN:
-               len = sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
-               GetLogicalProcessorInformation(&processorInfo, &len);
-               val = len / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
+               val = GetNumLogicalProcessors();
+               if (val == -1)
+                       log_err("_SC_NPROCESSORS_ONLN failed\n");
+
                break;
 
        case _SC_PAGESIZE: