Add CPU affinity support to Windows
[fio.git] / os / os-windows.h
1 #ifndef FIO_OS_WINDOWS_H\r
2 #define FIO_OS_WINDOWS_H\r
3 \r
4 #include <sys/types.h>\r
5 #include <errno.h>\r
6 #include <windows.h>\r
7 #include <psapi.h>\r
8 \r
9 #include "../smalloc.h"\r
10 #include "../file.h"\r
11 #include "../log.h"\r
12 \r
13 #define FIO_HAVE_ODIRECT\r
14 #define FIO_HAVE_CPU_AFFINITY\r
15 #define FIO_HAVE_CHARDEV_SIZE\r
16 #define FIO_HAVE_FALLOCATE\r
17 #define FIO_HAVE_FDATASYNC\r
18 #define FIO_HAVE_WINDOWSAIO\r
19 \r
20 #define FIO_USE_GENERIC_RAND\r
21 \r
22 #define OS_MAP_ANON             MAP_ANON\r
23 \r
24 #define OS_CLOCK CLOCK_REALTIME\r
25 \r
26 #define FIO_PREFERRED_ENGINE    "windowsaio"\r
27 \r
28 typedef off_t off64_t;\r
29 \r
30 typedef struct {\r
31   LARGE_INTEGER Length;\r
32 } GET_LENGTH_INFORMATION;\r
33 \r
34 #define IOCTL_DISK_GET_LENGTH_INFO 0x7405C\r
35 \r
36 pid_t cygwin_winpid_to_pid(int winpid);\r
37 \r
38 static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes)\r
39 {\r
40         int rc = 0;\r
41         HANDLE hFile;\r
42 \r
43         if (f->hFile == NULL) {\r
44                 hFile = CreateFile(f->file_name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,\r
45                                 NULL, OPEN_EXISTING, 0, NULL);\r
46         } else {\r
47                 hFile = f->hFile;\r
48         }\r
49 \r
50         GET_LENGTH_INFORMATION info;\r
51         DWORD outBytes;\r
52         LARGE_INTEGER size;\r
53         size.QuadPart = 0;\r
54         if (DeviceIoControl(hFile, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &info, sizeof(info), &outBytes, NULL))\r
55                 *bytes = info.Length.QuadPart;\r
56         else\r
57                 rc = EIO;\r
58 \r
59         /* If we were passed a POSIX fd,\r
60          * close the HANDLE we created via CreateFile */\r
61         if (hFile != INVALID_HANDLE_VALUE && f->hFile == NULL)\r
62                 CloseHandle(hFile);\r
63 \r
64         return rc;\r
65 }\r
66 \r
67 static inline int chardev_size(struct fio_file *f, unsigned long long *bytes)\r
68 {\r
69         return blockdev_size(f, bytes);\r
70 }\r
71 \r
72 static inline int blockdev_invalidate_cache(struct fio_file *f)\r
73 {\r
74         /* There's no way to invalidate the cache in Windows\r
75          * so just pretend to succeed */\r
76         return 0;\r
77 }\r
78 \r
79 static inline unsigned long long os_phys_mem(void)\r
80 {\r
81         SYSTEM_INFO sysInfo;\r
82         unsigned long addr;\r
83         GetSystemInfo(&sysInfo);\r
84         addr = (unsigned long)sysInfo.lpMaximumApplicationAddress;\r
85         return addr;\r
86 }\r
87 \r
88 static inline void os_get_tmpdir(char *path, int len)\r
89 {\r
90         GetTempPath(len, path);\r
91 }\r
92 \r
93 typedef DWORD_PTR os_cpu_mask_t;\r
94 \r
95 static inline int pid_to_winpid(int pid)\r
96 {\r
97         int winpid = 0;\r
98         DWORD outbytes = 0;\r
99         DWORD *ids = NULL;\r
100         size_t allocsize;\r
101         \r
102         allocsize = sizeof(DWORD) * 1024;\r
103         \r
104         do {\r
105                 if (allocsize == outbytes)\r
106                         allocsize *= 2;\r
107 \r
108                 ids = realloc(ids, allocsize);\r
109                 EnumProcesses(ids, allocsize, &outbytes);\r
110         } while (allocsize == outbytes);\r
111         \r
112         for (int i = 0; i < (outbytes/sizeof(DWORD)); i++) {\r
113                 if (cygwin_winpid_to_pid(ids[i]) == pid) {\r
114                         winpid = ids[i];\r
115                         break;\r
116                 }\r
117         }\r
118         \r
119         free(ids);\r
120         return winpid;\r
121 }\r
122 \r
123 static inline int fio_setaffinity(int pid, os_cpu_mask_t cpumask)\r
124 {\r
125         int winpid = pid_to_winpid(pid);\r
126         HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION, TRUE, winpid);\r
127         if (h == NULL)\r
128                 return -1;\r
129         \r
130         BOOL bSuccess = SetProcessAffinityMask(h, cpumask);\r
131         CloseHandle(h);\r
132         return (bSuccess)? 0 : -1;\r
133 }\r
134 \r
135 static inline void fio_getaffinity(int pid, os_cpu_mask_t *mask)\r
136 {\r
137         os_cpu_mask_t systemMask;\r
138         int winpid = pid_to_winpid(pid);\r
139         HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, winpid);\r
140         if (h == NULL)\r
141         {\r
142                 printf("OpenProcess failed!\n");\r
143                 return;\r
144   }\r
145   \r
146         GetProcessAffinityMask(h, mask, &systemMask);\r
147         CloseHandle(h);\r
148 }\r
149 \r
150 static inline void fio_cpu_clear(os_cpu_mask_t *mask, int cpu)\r
151 {\r
152         *mask ^= 1 << (cpu-1);\r
153 }\r
154 \r
155 static inline void fio_cpu_set(os_cpu_mask_t *mask, int cpu)\r
156 {\r
157         *mask |= 1 << (cpu-1);\r
158 }\r
159 \r
160 static inline int fio_cpuset_init(os_cpu_mask_t *mask)\r
161 {\r
162         *mask = 0;\r
163         return 0;\r
164 }\r
165 \r
166 static inline int fio_cpuset_exit(os_cpu_mask_t *mask)\r
167 {\r
168         return 0;\r
169 }\r
170 \r
171 #define FIO_MAX_CPUS                    MAXIMUM_PROCESSORS\r
172 \r
173 #ifdef MADV_FREE\r
174 #define FIO_MADV_FREE   MADV_FREE\r
175 #endif\r
176 \r
177 #endif /* FIO_OS_WINDOWS_H */\r