#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_USE_GENERIC_RAND\r
+#define FIO_HAVE_CPU_AFFINITY\r
#define FIO_HAVE_CHARDEV_SIZE\r
-#define FIO_USE_GENERIC_RAND\r
-\r
#define FIO_HAVE_FALLOCATE\r
#define FIO_HAVE_FDATASYNC\r
#define FIO_HAVE_WINDOWSAIO\r
+#define FIO_HAVE_GETTID\r
\r
-/* TODO add support for FIO_HAVE_CPU_AFFINITY */\r
-\r
-#define OS_MAP_ANON MAP_ANON\r
-\r
-typedef off_t off64_t;\r
+#define FIO_OS_HAVE_SOCKLEN_T\r
+typedef int fio_socklen_t;\r
\r
+#define FIO_USE_GENERIC_RAND\r
\r
-#define FIO_NOTUNIX\r
+#define OS_MAP_ANON MAP_ANON\r
\r
-#include <windows.h>\r
-#include <io.h>\r
+#define OS_CLOCK CLOCK_REALTIME\r
\r
-typedef void* HANDLE;\r
+#define FIO_PREFERRED_ENGINE "windowsaio"\r
\r
-BOOL WINAPI GetFileSizeEx(\r
- HANDLE hFile,\r
- PLARGE_INTEGER lpFileSize\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
-long _get_osfhandle(\r
- int fd\r
-);\r
+typedef off_t off64_t;\r
\r
typedef struct {\r
LARGE_INTEGER Length;\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(int fd, unsigned long long *bytes)\r
+static inline int blockdev_size(struct fio_file *f, unsigned long long *bytes)\r
{\r
int rc = 0;\r
- HANDLE hFile = (HANDLE)_get_osfhandle(fd);\r
- if (hFile != INVALID_HANDLE_VALUE)\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
+ 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
- return 0;\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(int fd, unsigned long long *bytes)\r
+static inline int chardev_size(struct fio_file *f, unsigned long long *bytes)\r
{\r
- return blockdev_size(fd, bytes);\r
+ return blockdev_size(f, bytes);\r
}\r
\r
-static inline int blockdev_invalidate_cache(int fd)\r
+static inline int blockdev_invalidate_cache(struct fio_file *f)\r
{\r
- int rc = 0;\r
- HANDLE hFile = (HANDLE)_get_osfhandle(fd);\r
-\r
- if (hFile != INVALID_HANDLE_VALUE)\r
- FlushFileBuffers(hFile);\r
- else\r
- rc = EIO;\r
-\r
- return rc;\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
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
-\r
#endif /* FIO_OS_WINDOWS_H */\r