-#ifndef FIO_OS_WINDOWS_H\r
-#define FIO_OS_WINDOWS_H\r
-\r
-#define FIO_OS os_windows\r
-\r
-#include <sys/types.h>\r
-#include <errno.h>\r
-#include <windows.h>\r
-#include <psapi.h>\r
-#include <stdlib.h>\r
-\r
-#include "../smalloc.h"\r
-#include "../file.h"\r
-#include "../log.h"\r
-\r
-#define FIO_HAVE_ODIRECT\r
-#define FIO_HAVE_CPU_AFFINITY\r
-#define FIO_HAVE_CHARDEV_SIZE\r
-#define FIO_HAVE_FALLOCATE\r
-#define FIO_HAVE_FDATASYNC\r
-#define FIO_HAVE_WINDOWSAIO\r
-#define FIO_HAVE_GETTID\r
-\r
-#define FIO_USE_GENERIC_RAND\r
-\r
-#define OS_MAP_ANON MAP_ANON\r
-\r
-#define OS_CLOCK CLOCK_REALTIME\r
-\r
-#define FIO_PREFERRED_ENGINE "windowsaio"\r
-\r
-#define FIO_LITTLE_ENDIAN\r
-#define fio_swap16(x) _byteswap_ushort(x)\r
-#define fio_swap32(x) _byteswap_ulong(x)\r
-#define fio_swap64(x) _byteswap_uint64(x)\r
-\r
-typedef off_t off64_t;\r
-\r
-typedef struct {\r
- LARGE_INTEGER Length;\r
-} GET_LENGTH_INFORMATION;\r
-\r
-#define IOCTL_DISK_GET_LENGTH_INFO 0x7405C\r
-\r
-pid_t cygwin_winpid_to_pid(int winpid);\r
-\r
-static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes)\r
-{\r
- int rc = 0;\r
- HANDLE hFile;\r
-\r
- if (f->hFile == NULL) {\r
- hFile = CreateFile(f->file_name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,\r
- NULL, OPEN_EXISTING, 0, NULL);\r
- } else {\r
- hFile = f->hFile;\r
- }\r
-\r
- GET_LENGTH_INFORMATION info;\r
- DWORD outBytes;\r
- LARGE_INTEGER size;\r
- size.QuadPart = 0;\r
- if (DeviceIoControl(hFile, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &info, sizeof(info), &outBytes, NULL))\r
- *bytes = info.Length.QuadPart;\r
- else\r
- rc = EIO;\r
-\r
- /* If we were passed a POSIX fd,\r
- * close the HANDLE we created via CreateFile */\r
- if (hFile != INVALID_HANDLE_VALUE && f->hFile == NULL)\r
- CloseHandle(hFile);\r
-\r
- return rc;\r
-}\r
-\r
-static inline int chardev_size(struct fio_file *f, unsigned long long *bytes)\r
-{\r
- return blockdev_size(f, bytes);\r
-}\r
-\r
-static inline int blockdev_invalidate_cache(struct fio_file *f)\r
-{\r
- /* There's no way to invalidate the cache in Windows\r
- * so just pretend to succeed */\r
- return 0;\r
-}\r
-\r
-static inline unsigned long long os_phys_mem(void)\r
-{\r
- SYSTEM_INFO sysInfo;\r
- unsigned long addr;\r
- GetSystemInfo(&sysInfo);\r
- addr = (unsigned long)sysInfo.lpMaximumApplicationAddress;\r
- return addr;\r
-}\r
-\r
-static inline void os_get_tmpdir(char *path, int len)\r
-{\r
- GetTempPath(len, path);\r
-}\r
-\r
-typedef DWORD_PTR os_cpu_mask_t;\r
-\r
-static inline int gettid(void)\r
-{\r
- return GetCurrentThreadId();\r
-}\r
-\r
-static inline int pid_to_winpid(int pid)\r
-{\r
- int winpid = 0;\r
- DWORD outbytes = 0;\r
- DWORD *ids = NULL;\r
- size_t allocsize;\r
- \r
- allocsize = sizeof(DWORD) * 1024;\r
- \r
- do {\r
- if (allocsize == outbytes)\r
- allocsize *= 2;\r
-\r
- ids = realloc(ids, allocsize);\r
- EnumProcesses(ids, allocsize, &outbytes);\r
- } while (allocsize == outbytes);\r
- \r
- for (int i = 0; i < (outbytes/sizeof(DWORD)); i++) {\r
- if (cygwin_winpid_to_pid(ids[i]) == pid) {\r
- winpid = ids[i];\r
- break;\r
- }\r
- }\r
- \r
- free(ids);\r
- return winpid;\r
-}\r
-\r
-HANDLE WINAPI OpenThread(\r
- DWORD dwDesiredAccess,\r
- BOOL bInheritHandle,\r
- DWORD dwThreadId);\r
- \r
-DWORD WINAPI GetProcessIdOfThread(HANDLE Thread);\r
-\r
-static inline int fio_setaffinity(int pid, os_cpu_mask_t cpumask)\r
-{\r
- HANDLE h;\r
- BOOL bSuccess;\r
- int winpid;\r
- \r
- h = OpenThread(THREAD_QUERY_INFORMATION | THREAD_SET_INFORMATION, TRUE, pid);\r
- if (h != NULL) {\r
- bSuccess = SetThreadAffinityMask(h, cpumask);\r
- } else {\r
- // then we might have a process id instead of a thread id\r
- winpid = pid_to_winpid(pid);\r
- h = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION, TRUE, winpid);\r
- if (h == NULL)\r
- return -1;\r
-\r
- bSuccess = SetProcessAffinityMask(h, cpumask);\r
- }\r
-\r
- CloseHandle(h);\r
-\r
- return (bSuccess)? 0 : -1;\r
-}\r
-\r
-static inline void fio_getaffinity(int pid, os_cpu_mask_t *mask)\r
-{\r
- os_cpu_mask_t systemMask;\r
- int winpid;\r
- \r
- HANDLE h = OpenThread(THREAD_QUERY_INFORMATION, TRUE, pid);\r
- if (h != NULL)\r
- winpid = GetProcessIdOfThread(h);\r
- else\r
- winpid = pid_to_winpid(pid);\r
- \r
- h = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, winpid);\r
-\r
- if (h != NULL) {\r
- GetProcessAffinityMask(h, mask, &systemMask);\r
- CloseHandle(h);\r
- } else {\r
- fprintf(stderr, "fio_getaffinity failed: failed to get handle for pid %d\n", pid);\r
- }\r
- \r
-}\r
-\r
-static inline void fio_cpu_clear(os_cpu_mask_t *mask, int cpu)\r
-{\r
- *mask ^= 1 << (cpu-1);\r
-}\r
-\r
-static inline void fio_cpu_set(os_cpu_mask_t *mask, int cpu)\r
-{\r
- *mask |= 1 << (cpu-1);\r
-}\r
-\r
-static inline int fio_cpuset_init(os_cpu_mask_t *mask)\r
-{\r
- *mask = 0;\r
- return 0;\r
-}\r
-\r
-static inline int fio_cpuset_exit(os_cpu_mask_t *mask)\r
-{\r
- return 0;\r
-}\r
-\r
-#define FIO_MAX_CPUS MAXIMUM_PROCESSORS\r
-\r
-#ifdef MADV_FREE\r
-#define FIO_MADV_FREE MADV_FREE\r
-#endif\r
-\r
-#endif /* FIO_OS_WINDOWS_H */\r
+#ifndef FIO_OS_WINDOWS_H
+#define FIO_OS_WINDOWS_H
+
+#define FIO_OS os_windows
+
+#include <sys/types.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <winsock2.h>
+#include <windows.h>
+#include <psapi.h>
+#include <stdlib.h>
+
+#include "../smalloc.h"
+#include "../file.h"
+#include "../log.h"
+#include "../lib/hweight.h"
+#include "../oslib/strcasestr.h"
+
+#include "windows/posix.h"
+
+/* Cygwin doesn't define rand_r if C99 or newer is being used */
+#if defined(WIN32) && !defined(rand_r)
+int rand_r(unsigned *);
+#endif
+
+#ifndef PTHREAD_STACK_MIN
+#define PTHREAD_STACK_MIN 65535
+#endif
+
+#define FIO_HAVE_ODIRECT
+#define FIO_HAVE_CPU_AFFINITY
+#define FIO_HAVE_CHARDEV_SIZE
+#define FIO_HAVE_GETTID
+#define FIO_USE_GENERIC_RAND
+
+#define FIO_PREFERRED_ENGINE "windowsaio"
+#define FIO_PREFERRED_CLOCK_SOURCE CS_CGETTIME
+#define FIO_OS_PATH_SEPARATOR "\\"
+
+#define FIO_MAX_CPUS MAXIMUM_PROCESSORS
+
+#define OS_MAP_ANON MAP_ANON
+
+#define fio_swap16(x) _byteswap_ushort(x)
+#define fio_swap32(x) _byteswap_ulong(x)
+#define fio_swap64(x) _byteswap_uint64(x)
+
+typedef DWORD_PTR os_cpu_mask_t;
+
+#define _SC_PAGESIZE 0x1
+#define _SC_NPROCESSORS_ONLN 0x2
+#define _SC_PHYS_PAGES 0x4
+
+#define SA_RESTART 0
+#define SIGPIPE 0
+
+/*
+ * Windows doesn't have O_DIRECT or O_SYNC, so define them
+ * here so we can reject them at runtime when using the _open
+ * interface (windowsaio uses CreateFile)
+ */
+#define O_DIRECT 0x1000000
+#define O_SYNC 0x2000000
+
+/* Windows doesn't support madvise, so any values will work */
+#define POSIX_MADV_DONTNEED 0
+#define POSIX_MADV_SEQUENTIAL 0
+#define POSIX_MADV_RANDOM 0
+
+#define F_SETFL 0x1
+#define F_GETFL 0x2
+#define O_NONBLOCK FIONBIO
+
+/* Winsock doesn't support MSG_WAIT */
+#define OS_MSG_DONTWAIT 0
+
+#define POLLOUT 1
+#define POLLIN 2
+#define POLLERR 0
+#define POLLHUP 1
+
+#define SIGCONT 0
+#define SIGUSR1 1
+#define SIGUSR2 2
+
+typedef int sigset_t;
+typedef int siginfo_t;
+
+struct sigaction
+{
+ void (*sa_handler)(int);
+ sigset_t sa_mask;
+ int sa_flags;
+ void* (*sa_sigaction)(int, siginfo_t *, void*);
+};
+
+long sysconf(int name);
+
+int kill(pid_t pid, int sig);
+pid_t setsid(void);
+int setgid(gid_t gid);
+int setuid(uid_t uid);
+int nice(int incr);
+int sigaction(int sig, const struct sigaction *act,
+ struct sigaction *oact);
+int fsync(int fildes);
+int fork(void);
+int fcntl(int fildes, int cmd, ...);
+int fdatasync(int fildes);
+int lstat(const char * path, struct stat * buf);
+uid_t geteuid(void);
+char* ctime_r(const time_t *t, char *buf);
+int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
+ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset);
+ssize_t pwrite(int fildes, const void *buf, size_t nbyte,
+ off_t offset);
+extern void td_fill_rand_seeds(struct thread_data *);
+
+static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes)
+{
+ int rc = 0;
+ HANDLE hFile;
+ GET_LENGTH_INFORMATION info;
+ DWORD outBytes;
+
+ if (f->hFile == NULL) {
+ hFile = CreateFile(f->file_name, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, OPEN_EXISTING, 0, NULL);
+ } else {
+ hFile = f->hFile;
+ }
+
+ if (DeviceIoControl(hFile, IOCTL_DISK_GET_LENGTH_INFO, NULL, 0, &info, sizeof(info), &outBytes, NULL))
+ *bytes = info.Length.QuadPart;
+ else
+ rc = EIO;
+
+ /* If we were passed a POSIX fd,
+ * close the HANDLE we created via CreateFile */
+ if (hFile != INVALID_HANDLE_VALUE && f->hFile == NULL)
+ CloseHandle(hFile);
+
+ return rc;
+}
+
+static inline int chardev_size(struct fio_file *f, unsigned long long *bytes)
+{
+ return blockdev_size(f, bytes);
+}
+
+static inline int blockdev_invalidate_cache(struct fio_file *f)
+{
+ /* There's no way to invalidate the cache in Windows
+ * so just pretend to succeed */
+ return 0;
+}
+
+static inline unsigned long long os_phys_mem(void)
+{
+ long pagesize, pages;
+
+ pagesize = sysconf(_SC_PAGESIZE);
+ pages = sysconf(_SC_PHYS_PAGES);
+ if (pages == -1 || pagesize == -1)
+ return 0;
+
+ return (unsigned long long) pages * (unsigned long long) pagesize;
+}
+
+static inline int gettid(void)
+{
+ return GetCurrentThreadId();
+}
+
+static inline int fio_setaffinity(int pid, os_cpu_mask_t cpumask)
+{
+ HANDLE h;
+ BOOL bSuccess = FALSE;
+
+ h = OpenThread(THREAD_QUERY_INFORMATION | THREAD_SET_INFORMATION, TRUE, pid);
+ if (h != NULL) {
+ bSuccess = SetThreadAffinityMask(h, cpumask);
+ if (!bSuccess)
+ log_err("fio_setaffinity failed: failed to set thread affinity (pid %d, mask %.16llx)\n", pid, cpumask);
+
+ CloseHandle(h);
+ } else {
+ log_err("fio_setaffinity failed: failed to get handle for pid %d\n", pid);
+ }
+
+ return (bSuccess)? 0 : -1;
+}
+
+static inline int fio_getaffinity(int pid, os_cpu_mask_t *mask)
+{
+ os_cpu_mask_t systemMask;
+
+ HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, pid);
+
+ if (h != NULL) {
+ GetProcessAffinityMask(h, mask, &systemMask);
+ CloseHandle(h);
+ } else {
+ log_err("fio_getaffinity failed: failed to get handle for pid %d\n", pid);
+ return -1;
+ }
+
+ return 0;
+}
+
+static inline void fio_cpu_clear(os_cpu_mask_t *mask, int cpu)
+{
+ *mask ^= 1 << (cpu-1);
+}
+
+static inline void fio_cpu_set(os_cpu_mask_t *mask, int cpu)
+{
+ *mask |= 1 << cpu;
+}
+
+static inline int fio_cpu_isset(os_cpu_mask_t *mask, int cpu)
+{
+ return (*mask & (1U << cpu));
+}
+
+static inline int fio_cpu_count(os_cpu_mask_t *mask)
+{
+ return hweight64(*mask);
+}
+
+static inline int fio_cpuset_init(os_cpu_mask_t *mask)
+{
+ *mask = 0;
+ return 0;
+}
+
+static inline int fio_cpuset_exit(os_cpu_mask_t *mask)
+{
+ return 0;
+}
+
+static inline int init_random_state(struct thread_data *td, unsigned long *rand_seeds, int size)
+{
+ HCRYPTPROV hCryptProv;
+
+ if (!CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
+ {
+ errno = GetLastError();
+ log_err("CryptAcquireContext() failed: error %d\n", errno);
+ return 1;
+ }
+
+ if (!CryptGenRandom(hCryptProv, size, (BYTE*)rand_seeds)) {
+ errno = GetLastError();
+ log_err("CryptGenRandom() failed, error %d\n", errno);
+ CryptReleaseContext(hCryptProv, 0);
+ return 1;
+ }
+
+ CryptReleaseContext(hCryptProv, 0);
+ td_fill_rand_seeds(td);
+ return 0;
+}
+
+
+static inline int fio_set_sched_idle(void)
+{
+ /* SetThreadPriority returns nonzero for success */
+ return (SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE))? 0 : -1;
+}
+
+
+#endif /* FIO_OS_WINDOWS_H */