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) 25int 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 50typedef 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 88typedef int sigset_t; 89typedef int siginfo_t; 90 91struct 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 99long sysconf(int name); 100 101int kill(pid_t pid, int sig); 102pid_t setsid(void); 103int setgid(gid_t gid); 104int setuid(uid_t uid); 105int nice(int incr); 106int sigaction(int sig, const struct sigaction *act, 107 struct sigaction *oact); 108int fsync(int fildes); 109int fork(void); 110int fcntl(int fildes, int cmd, ...); 111int fdatasync(int fildes); 112int lstat(const char * path, struct stat * buf); 113uid_t geteuid(void); 114char* ctime_r(const time_t *t, char *buf); 115int nanosleep(const struct timespec *rqtp, struct timespec *rmtp); 116ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset); 117ssize_t pwrite(int fildes, const void *buf, size_t nbyte, 118 off_t offset); 119extern void td_fill_rand_seeds(struct thread_data *); 120 121static 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 148static inline int chardev_size(struct fio_file *f, unsigned long long *bytes) 149{ 150 return blockdev_size(f, bytes); 151} 152 153static inline int blockdev_invalidate_cache(struct fio_file *f) 154{ 155 return ENOTSUP; 156} 157 158static 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 170static inline int gettid(void) 171{ 172 return GetCurrentThreadId(); 173} 174 175static 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 194static 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 211static inline void fio_cpu_clear(os_cpu_mask_t *mask, int cpu) 212{ 213 *mask ^= 1 << (cpu-1); 214} 215 216static inline void fio_cpu_set(os_cpu_mask_t *mask, int cpu) 217{ 218 *mask |= 1 << cpu; 219} 220 221static inline int fio_cpu_isset(os_cpu_mask_t *mask, int cpu) 222{ 223 return (*mask & (1U << cpu)); 224} 225 226static inline int fio_cpu_count(os_cpu_mask_t *mask) 227{ 228 return hweight64(*mask); 229} 230 231static inline int fio_cpuset_init(os_cpu_mask_t *mask) 232{ 233 *mask = 0; 234 return 0; 235} 236 237static inline int fio_cpuset_exit(os_cpu_mask_t *mask) 238{ 239 return 0; 240} 241 242static 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 266static 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