Add CPU affinity support to Windows
authorBruce Cran <BCran@fusionio.com>
Thu, 14 Jul 2011 05:50:43 +0000 (07:50 +0200)
committerJens Axboe <jaxboe@fusionio.com>
Thu, 14 Jul 2011 05:50:43 +0000 (07:50 +0200)
Signed-off-by: Jens Axboe <jaxboe@fusionio.com>
Makefile
os/os-windows.h

index 17c652763a2949e1e675f3392a6f7d016df14af0..a80f4ca195d744ecf90eb0d30a1bf73cf7729f7a 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -57,7 +57,8 @@ ifeq ($(UNAME), Darwin)
 endif
 ifneq (,$(findstring CYGWIN,$(UNAME)))
   SOURCE += engines/windowsaio.c
-  LIBS  += -lpthread -lrt
+  LIBS  += -lpthread -lrt -lpsapi
+  CFLAGS += -DPSAPI_VERSION=1
 endif
 
 OBJS = $(SOURCE:.c=.o)
index e790a51322b3ce10b422c7c3894526cdba481036..9f2243eb34dadf5e2255a506bf0d0d050b3b3004 100644 (file)
@@ -4,20 +4,21 @@
 #include <sys/types.h>\r
 #include <errno.h>\r
 #include <windows.h>\r
+#include <psapi.h>\r
 \r
 #include "../smalloc.h"\r
 #include "../file.h"\r
 #include "../log.h"\r
 \r
 #define FIO_HAVE_ODIRECT\r
-#define FIO_USE_GENERIC_RAND\r
+#define FIO_HAVE_CPU_AFFINITY\r
 #define FIO_HAVE_CHARDEV_SIZE\r
-#define FIO_USE_GENERIC_RAND\r
-\r
 #define FIO_HAVE_FALLOCATE\r
 #define FIO_HAVE_FDATASYNC\r
 #define FIO_HAVE_WINDOWSAIO\r
 \r
+#define FIO_USE_GENERIC_RAND\r
+\r
 #define OS_MAP_ANON            MAP_ANON\r
 \r
 #define OS_CLOCK CLOCK_REALTIME\r
@@ -32,6 +33,8 @@ typedef struct {
 \r
 #define IOCTL_DISK_GET_LENGTH_INFO 0x7405C\r
 \r
+pid_t cygwin_winpid_to_pid(int winpid);\r
+\r
 static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes)\r
 {\r
        int rc = 0;\r
@@ -87,6 +90,86 @@ static inline void os_get_tmpdir(char *path, int len)
        GetTempPath(len, path);\r
 }\r
 \r
+typedef DWORD_PTR os_cpu_mask_t;\r
+\r
+static inline int pid_to_winpid(int pid)\r
+{\r
+       int winpid = 0;\r
+       DWORD outbytes = 0;\r
+       DWORD *ids = NULL;\r
+       size_t allocsize;\r
+       \r
+       allocsize = sizeof(DWORD) * 1024;\r
+       \r
+       do {\r
+               if (allocsize == outbytes)\r
+                       allocsize *= 2;\r
+\r
+               ids = realloc(ids, allocsize);\r
+               EnumProcesses(ids, allocsize, &outbytes);\r
+       } while (allocsize == outbytes);\r
+       \r
+       for (int i = 0; i < (outbytes/sizeof(DWORD)); i++) {\r
+               if (cygwin_winpid_to_pid(ids[i]) == pid) {\r
+                       winpid = ids[i];\r
+                       break;\r
+               }\r
+       }\r
+       \r
+       free(ids);\r
+       return winpid;\r
+}\r
+\r
+static inline int fio_setaffinity(int pid, os_cpu_mask_t cpumask)\r
+{\r
+       int winpid = pid_to_winpid(pid);\r
+       HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION, TRUE, winpid);\r
+       if (h == NULL)\r
+               return -1;\r
+       \r
+       BOOL bSuccess = SetProcessAffinityMask(h, cpumask);\r
+       CloseHandle(h);\r
+       return (bSuccess)? 0 : -1;\r
+}\r
+\r
+static inline void fio_getaffinity(int pid, os_cpu_mask_t *mask)\r
+{\r
+       os_cpu_mask_t systemMask;\r
+       int winpid = pid_to_winpid(pid);\r
+       HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, winpid);\r
+       if (h == NULL)\r
+       {\r
+               printf("OpenProcess failed!\n");\r
+               return;\r
+  }\r
+  \r
+       GetProcessAffinityMask(h, mask, &systemMask);\r
+       CloseHandle(h);\r
+}\r
+\r
+static inline void fio_cpu_clear(os_cpu_mask_t *mask, int cpu)\r
+{\r
+       *mask ^= 1 << (cpu-1);\r
+}\r
+\r
+static inline void fio_cpu_set(os_cpu_mask_t *mask, int cpu)\r
+{\r
+       *mask |= 1 << (cpu-1);\r
+}\r
+\r
+static inline int fio_cpuset_init(os_cpu_mask_t *mask)\r
+{\r
+       *mask = 0;\r
+       return 0;\r
+}\r
+\r
+static inline int fio_cpuset_exit(os_cpu_mask_t *mask)\r
+{\r
+       return 0;\r
+}\r
+\r
+#define FIO_MAX_CPUS                   MAXIMUM_PROCESSORS\r
+\r
 #ifdef MADV_FREE\r
 #define FIO_MADV_FREE  MADV_FREE\r
 #endif\r