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