#include <unistd.h>
#include <dirent.h>
#include <pthread.h>
+#include <time.h>
#include <semaphore.h>
#include <sys/shm.h>
#include <sys/mman.h>
#include <sys/uio.h>
#include <sys/resource.h>
#include <sys/poll.h>
+#include <sys/wait.h>
+#include <setjmp.h>
#include "../os-windows.h"
#include "../../lib/hweight.h"
-extern unsigned long mtime_since_now(struct timeval *);
-extern void fio_gettime(struct timeval *, void *);
+extern unsigned long mtime_since_now(struct timespec *);
+extern void fio_gettime(struct timespec *, void *);
/* These aren't defined in the MinGW headers */
HRESULT WINAPI StringCchCopyA(
const char *pszFormat,
...);
-int vsprintf_s(
- char *buffer,
- size_t numberOfElements,
- const char *format,
- va_list argptr);
-
int win_to_posix_error(DWORD winerr)
{
switch (winerr)
return dl_error;
}
+/* Copied from http://blogs.msdn.com/b/joshpoley/archive/2007/12/19/date-time-formats-and-conversions.aspx */
+void Time_tToSystemTime(time_t dosTime, SYSTEMTIME *systemTime)
+{
+ FILETIME utcFT;
+ LONGLONG jan1970;
+ SYSTEMTIME tempSystemTime;
+
+ jan1970 = Int32x32To64(dosTime, 10000000) + 116444736000000000;
+ utcFT.dwLowDateTime = (DWORD)jan1970;
+ utcFT.dwHighDateTime = jan1970 >> 32;
+
+ FileTimeToSystemTime((FILETIME*)&utcFT, &tempSystemTime);
+ SystemTimeToTzSpecificLocalTime(NULL, &tempSystemTime, systemTime);
+}
+
+char* ctime_r(const time_t *t, char *buf)
+{
+ SYSTEMTIME systime;
+ const char * const dayOfWeek[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
+ const char * const monthOfYear[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
+
+ Time_tToSystemTime(*t, &systime);
+ /* We don't know how long `buf` is, but assume it's rounded up from the minimum of 25 to 32 */
+ StringCchPrintfA(buf, 31, "%s %s %d %02d:%02d:%02d %04d\n", dayOfWeek[systime.wDayOfWeek % 7], monthOfYear[(systime.wMonth - 1) % 12],
+ systime.wDay, systime.wHour, systime.wMinute, systime.wSecond, systime.wYear);
+ return buf;
+}
+
int gettimeofday(struct timeval *restrict tp, void *restrict tzp)
{
FILETIME fileTime;
int fildes, off_t off)
{
DWORD vaProt = 0;
+ DWORD mapAccess = 0;
+ DWORD lenlow;
+ DWORD lenhigh;
+ HANDLE hMap;
void* allocAddr = NULL;
if (prot & PROT_NONE)
vaProt |= PAGE_NOACCESS;
- if ((prot & PROT_READ) && !(prot & PROT_WRITE))
+ if ((prot & PROT_READ) && !(prot & PROT_WRITE)) {
vaProt |= PAGE_READONLY;
+ mapAccess = FILE_MAP_READ;
+ }
- if (prot & PROT_WRITE)
+ if (prot & PROT_WRITE) {
vaProt |= PAGE_READWRITE;
+ mapAccess |= FILE_MAP_WRITE;
+ }
+
+ lenlow = len & 0xFFFF;
+ lenhigh = len >> 16;
+ /* If the low DWORD is zero and the high DWORD is non-zero, `CreateFileMapping`
+ will return ERROR_INVALID_PARAMETER. To avoid this, set both to zero. */
+ if (lenlow == 0) {
+ lenhigh = 0;
+ }
- if ((flags & MAP_ANON) | (flags & MAP_ANONYMOUS))
+ if (flags & MAP_ANON || flags & MAP_ANONYMOUS)
{
allocAddr = VirtualAlloc(addr, len, MEM_COMMIT, vaProt);
if (allocAddr == NULL)
errno = win_to_posix_error(GetLastError());
}
+ else
+ {
+ hMap = CreateFileMapping((HANDLE)_get_osfhandle(fildes), NULL, vaProt, lenhigh, lenlow, NULL);
+
+ if (hMap != NULL)
+ {
+ allocAddr = MapViewOfFile(hMap, mapAccess, off >> 16, off & 0xFFFF, len);
+ }
+
+ if (hMap == NULL || allocAddr == NULL)
+ errno = win_to_posix_error(GetLastError());
+
+ }
return allocAddr;
}
int munmap(void *addr, size_t len)
{
- if (!VirtualFree(addr, 0, MEM_RELEASE)) {
- errno = win_to_posix_error(GetLastError());
- return -1;
+ BOOL success;
+
+ /* We may have allocated the memory with either MapViewOfFile or
+ VirtualAlloc. Therefore, try calling UnmapViewOfFile first, and if that
+ fails, call VirtualFree. */
+ success = UnmapViewOfFile(addr);
+
+ if (!success)
+ {
+ success = VirtualFree(addr, 0, MEM_RELEASE);
}
- return 0;
+ return !success;
+}
+
+int msync(void *addr, size_t len, int flags)
+{
+ return !FlushViewOfFile(addr, len);
}
int fork(void)
{
static LARGE_INTEGER freq = {{0,0}};
LARGE_INTEGER counts;
+ uint64_t t;
QueryPerformanceCounter(&counts);
if (freq.QuadPart == 0)
tp->tv_sec = counts.QuadPart / freq.QuadPart;
/* Get the difference between the number of ns stored
* in 'tv_sec' and that stored in 'counts' */
- uint64_t t = tp->tv_sec * freq.QuadPart;
+ t = tp->tv_sec * freq.QuadPart;
t = counts.QuadPart - t;
/* 't' now contains the number of cycles since the last second.
* We want the number of nanoseconds, so multiply out by 1,000,000,000
while (path[i] != '\\' && path[i] != '/' && i >= 0)
i--;
- strncpy(name, path + i + 1, MAX_PATH);
+ name[MAX_PATH - 1] = '\0';
+ strncpy(name, path + i + 1, MAX_PATH - 1);
return name;
}
int nice(int incr)
{
- if (incr != 0) {
- errno = EINVAL;
- return -1;
- }
+ DWORD prioclass = NORMAL_PRIORITY_CLASS;
+
+ if (incr < -15)
+ prioclass = HIGH_PRIORITY_CLASS;
+ else if (incr < 0)
+ prioclass = ABOVE_NORMAL_PRIORITY_CLASS;
+ else if (incr > 15)
+ prioclass = IDLE_PRIORITY_CLASS;
+ else if (incr > 0)
+ prioclass = BELOW_NORMAL_PRIORITY_CLASS;
+
+ if (!SetPriorityClass(GetCurrentProcess(), prioclass))
+ log_err("fio: SetPriorityClass failed\n");
return 0;
}
return 0;
}
-int posix_fadvise(int fd, off_t offset, off_t len, int advice)
-{
- return 0;
-}
-
int posix_madvise(void *addr, size_t len, int advice)
{
- log_err("%s is not implemented\n", __func__);
return ENOSYS;
}
-/* Windows doesn't support advice for memory pages. Just ignore it. */
-int msync(void *addr, size_t len, int flags)
-{
- errno = ENOSYS;
- return -1;
-}
-
int fdatasync(int fildes)
{
return fsync(fildes);
ssize_t writev(int fildes, const struct iovec *iov, int iovcnt)
{
- log_err("%s is not implemented\n", __func__);
- errno = ENOSYS;
- return -1;
+ int i;
+ DWORD bytes_written = 0;
+ for (i = 0; i < iovcnt; i++)
+ {
+ int len = send((SOCKET)fildes, iov[i].iov_base, iov[i].iov_len, 0);
+ if (len == SOCKET_ERROR)
+ {
+ DWORD err = GetLastError();
+ errno = win_to_posix_error(err);
+ bytes_written = -1;
+ break;
+ }
+ bytes_written += len;
+ }
+
+ return bytes_written;
}
long long strtoll(const char *restrict str, char **restrict endptr,
FD_SET(fds[i].fd, &exceptfds);
}
-
rc = select(nfds, &readfds, &writefds, &exceptfds, to);
if (rc != SOCKET_ERROR) {
fds[i].revents |= POLLHUP;
}
}
-
return rc;
}
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
{
- struct timeval tv;
+ struct timespec tv;
DWORD ms_remaining;
DWORD ms_total = (rqtp->tv_sec * 1000) + (rqtp->tv_nsec / 1000000.0);
if (dirp->find_handle == INVALID_HANDLE_VALUE) {
char search_pattern[MAX_PATH];
- StringCchPrintfA(search_pattern, MAX_PATH, "%s\\*", dirp->dirname);
+ StringCchPrintfA(search_pattern, MAX_PATH-1, "%s\\*", dirp->dirname);
dirp->find_handle = FindFirstFileA(search_pattern, &find_data);
if (dirp->find_handle == INVALID_HANDLE_VALUE)
return NULL;
return -1;
}
+in_addr_t inet_network(const char *cp)
+{
+ in_addr_t hbo;
+ in_addr_t nbo = inet_addr(cp);
+ hbo = ((nbo & 0xFF) << 24) + ((nbo & 0xFF00) << 8) + ((nbo & 0xFF0000) >> 8) + ((nbo & 0xFF000000) >> 24);
+ return hbo;
+}
+
const char* inet_ntop(int af, const void *restrict src,
char *restrict dst, socklen_t size)
{