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