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