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 44typedef 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 82typedef int sigset_t; 83typedef int siginfo_t; 84 85struct 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 93long sysconf(int name); 94 95int kill(pid_t pid, int sig); 96pid_t setsid(void); 97int setgid(gid_t gid); 98int setuid(uid_t uid); 99int nice(int incr); 100int sigaction(int sig, const struct sigaction *act, 101 struct sigaction *oact); 102int fsync(int fildes); 103int fork(void); 104int fcntl(int fildes, int cmd, ...); 105int fdatasync(int fildes); 106int lstat(const char * path, struct stat * buf); 107uid_t geteuid(void); 108int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); 109ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset); 110ssize_t pwrite(int fildes, const void *buf, size_t nbyte, 111 off_t offset); 112extern void td_fill_rand_seeds(struct thread_data *); 113 114static 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 141static inline int chardev_size(struct fio_file *f, unsigned long long *bytes) 142{ 143 return blockdev_size(f, bytes); 144} 145 146static 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 153static 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 165static inline int gettid(void) 166{ 167 return GetCurrentThreadId(); 168} 169 170static 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 189static 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 203static inline void fio_cpu_clear(os_cpu_mask_t *mask, int cpu) 204{ 205 *mask ^= 1 << (cpu-1); 206} 207 208static inline void fio_cpu_set(os_cpu_mask_t *mask, int cpu) 209{ 210 *mask |= 1 << cpu; 211} 212 213static inline int fio_cpu_isset(os_cpu_mask_t *mask, int cpu) 214{ 215 return (*mask & (1U << cpu)); 216} 217 218static inline int fio_cpu_count(os_cpu_mask_t *mask) 219{ 220 return hweight64(*mask); 221} 222 223static inline int fio_cpuset_init(os_cpu_mask_t *mask) 224{ 225 *mask = 0; 226 return 0; 227} 228 229static inline int fio_cpuset_exit(os_cpu_mask_t *mask) 230{ 231 return 0; 232} 233 234static 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 258static 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