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