1 #ifndef FIO_OS_WINDOWS_H 2 #define FIO_OS_WINDOWS_H 3 4 #define FIO_OS os_windows 5 6 #include <sys/types.h> 7 #include <sys/shm.h> 8 #include <sys/stat.h> 9 #include <errno.h> 10 #include <winsock2.h> 11 #include <windows.h> 12 #include <psapi.h> 13 #include <stdlib.h> 14 15 #include "../smalloc.h" 16 #include "../file.h" 17 #include "../log.h" 18 #include "../lib/hweight.h" 19 20 #include "windows/posix.h" 21 22 #ifndef PTHREAD_STACK_MIN 23 #define PTHREAD_STACK_MIN 65535 24 #endif 25 26 #define FIO_HAVE_ODIRECT 27 #define FIO_HAVE_CPU_AFFINITY 28 #define FIO_HAVE_CHARDEV_SIZE 29 #define FIO_HAVE_GETTID 30 #define FIO_USE_GENERIC_RAND 31 32 #define FIO_PREFERRED_ENGINE "windowsaio" 33 #define FIO_PREFERRED_CLOCK_SOURCE CS_CGETTIME 34 #define FIO_OS_PATH_SEPARATOR "\\" 35 36 #define FIO_MAX_CPUS MAXIMUM_PROCESSORS 37 38 #define OS_MAP_ANON MAP_ANON 39 40 #define fio_swap16(x) _byteswap_ushort(x) 41 #define fio_swap32(x) _byteswap_ulong(x) 42 #define fio_swap64(x) _byteswap_uint64(x) 43 44 typedef DWORD_PTR os_cpu_mask_t; 45 46 #define _SC_PAGESIZE 0x1 47 #define _SC_NPROCESSORS_ONLN 0x2 48 #define _SC_PHYS_PAGES 0x4 49 50 #define SA_RESTART 0 51 #define SIGPIPE 0 52 53 /* 54 * Windows doesn't have O_DIRECT or O_SYNC, so define them 55 * here so we can reject them at runtime when using the _open 56 * interface (windowsaio uses CreateFile) 57 */ 58 #define O_DIRECT 0x1000000 59 #define O_SYNC 0x2000000 60 61 /* Windows doesn't support madvise, so any values will work */ 62 #define POSIX_MADV_DONTNEED 0 63 #define POSIX_MADV_SEQUENTIAL 0 64 #define POSIX_MADV_RANDOM 0 65 66 #define F_SETFL 0x1 67 #define F_GETFL 0x2 68 #define O_NONBLOCK FIONBIO 69 70 /* Winsock doesn't support MSG_WAIT */ 71 #define OS_MSG_DONTWAIT 0 72 73 #define POLLOUT 1 74 #define POLLIN 2 75 #define POLLERR 0 76 #define POLLHUP 1 77 78 #define SIGCONT 0 79 #define SIGUSR1 1 80 #define SIGUSR2 2 81 82 typedef int sigset_t; 83 typedef int siginfo_t; 84 85 struct sigaction 86 { 87 void (*sa_handler)(int); 88 sigset_t sa_mask; 89 int sa_flags; 90 void* (*sa_sigaction)(int, siginfo_t *, void*); 91 }; 92 93 long sysconf(int name); 94 95 int kill(pid_t pid, int sig); 96 pid_t setsid(void); 97 int setgid(gid_t gid); 98 int setuid(uid_t uid); 99 int nice(int incr); 100 int sigaction(int sig, const struct sigaction *act, 101 struct sigaction *oact); 102 int fsync(int fildes); 103 int fork(void); 104 int fcntl(int fildes, int cmd, ...); 105 int fdatasync(int fildes); 106 int lstat(const char * path, struct stat * buf); 107 uid_t geteuid(void); 108 int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); 109 ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset); 110 ssize_t pwrite(int fildes, const void *buf, size_t nbyte, 111 off_t offset); 112 extern void td_fill_rand_seeds(struct thread_data *); 113 114 static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes) 115 { 116 int rc = 0; 117 HANDLE hFile; 118 GET_LENGTH_INFORMATION info; 119 DWORD outBytes; 120 121 if (f->hFile == NULL) { 122 hFile = CreateFile(f->file_name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 123 NULL, OPEN_EXISTING, 0, NULL); 124 } else { 125 hFile = f->hFile; 126 } 127 128 if (DeviceIoControl(hFile, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &info, sizeof(info), &outBytes, NULL)) 129 *bytes = info.Length.QuadPart; 130 else 131 rc = EIO; 132 133 /* If we were passed a POSIX fd, 134 * close the HANDLE we created via CreateFile */ 135 if (hFile != INVALID_HANDLE_VALUE && f->hFile == NULL) 136 CloseHandle(hFile); 137 138 return rc; 139 } 140 141 static inline int chardev_size(struct fio_file *f, unsigned long long *bytes) 142 { 143 return blockdev_size(f, bytes); 144 } 145 146 static inline int blockdev_invalidate_cache(struct fio_file *f) 147 { 148 /* There's no way to invalidate the cache in Windows 149 * so just pretend to succeed */ 150 return 0; 151 } 152 153 static inline unsigned long long os_phys_mem(void) 154 { 155 long pagesize, pages; 156 157 pagesize = sysconf(_SC_PAGESIZE); 158 pages = sysconf(_SC_PHYS_PAGES); 159 if (pages == -1 || pagesize == -1) 160 return 0; 161 162 return (unsigned long long) pages * (unsigned long long) pagesize; 163 } 164 165 static inline int gettid(void) 166 { 167 return GetCurrentThreadId(); 168 } 169 170 static inline int fio_setaffinity(int pid, os_cpu_mask_t cpumask) 171 { 172 HANDLE h; 173 BOOL bSuccess = FALSE; 174 175 h = OpenThread(THREAD_QUERY_INFORMATION | THREAD_SET_INFORMATION, TRUE, pid); 176 if (h != NULL) { 177 bSuccess = SetThreadAffinityMask(h, cpumask); 178 if (!bSuccess) 179 log_err("fio_setaffinity failed: failed to set thread affinity (pid %d, mask %.16llx)\n", pid, cpumask); 180 181 CloseHandle(h); 182 } else { 183 log_err("fio_setaffinity failed: failed to get handle for pid %d\n", pid); 184 } 185 186 return (bSuccess)? 0 : -1; 187 } 188 189 static inline void fio_getaffinity(int pid, os_cpu_mask_t *mask) 190 { 191 os_cpu_mask_t systemMask; 192 193 HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, pid); 194 195 if (h != NULL) { 196 GetProcessAffinityMask(h, mask, &systemMask); 197 CloseHandle(h); 198 } else { 199 log_err("fio_getaffinity failed: failed to get handle for pid %d\n", pid); 200 } 201 } 202 203 static inline void fio_cpu_clear(os_cpu_mask_t *mask, int cpu) 204 { 205 *mask ^= 1 << (cpu-1); 206 } 207 208 static inline void fio_cpu_set(os_cpu_mask_t *mask, int cpu) 209 { 210 *mask |= 1 << cpu; 211 } 212 213 static inline int fio_cpu_isset(os_cpu_mask_t *mask, int cpu) 214 { 215 return (*mask & (1U << cpu)); 216 } 217 218 static inline int fio_cpu_count(os_cpu_mask_t *mask) 219 { 220 return hweight64(*mask); 221 } 222 223 static inline int fio_cpuset_init(os_cpu_mask_t *mask) 224 { 225 *mask = 0; 226 return 0; 227 } 228 229 static inline int fio_cpuset_exit(os_cpu_mask_t *mask) 230 { 231 return 0; 232 } 233 234 static inline int init_random_state(struct thread_data *td, unsigned long *rand_seeds, int size) 235 { 236 HCRYPTPROV hCryptProv; 237 238 if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) 239 { 240 errno = GetLastError(); 241 log_err("CryptAcquireContext() failed: error %d\n", errno); 242 return 1; 243 } 244 245 if (!CryptGenRandom(hCryptProv, size, (BYTE*)rand_seeds)) { 246 errno = GetLastError(); 247 log_err("CryptGenRandom() failed, error %d\n", errno); 248 CryptReleaseContext(hCryptProv, 0); 249 return 1; 250 } 251 252 CryptReleaseContext(hCryptProv, 0); 253 td_fill_rand_seeds(td); 254 return 0; 255 } 256 257 258 static inline int fio_set_sched_idle(void) 259 { 260 /* SetThreadPriority returns nonzero for success */ 261 return (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE))? 0 : -1; 262 } 263 264 265 #endif /* FIO_OS_WINDOWS_H */ 266