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