X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=os%2Fwindows%2Fposix.c;h=67e71c8eabe57a0f2041c78a10cab9ac7c133ec0;hp=27793cbd85fa7b1193d39d4312e0e3ba0776395a;hb=36744c7511b71defe1c60666ae175ec8a5ed22c8;hpb=9277ec144b7a2a852a72e2c4d3f0ff806ccd97aa diff --git a/os/windows/posix.c b/os/windows/posix.c index 27793cbd..67e71c8e 100755 --- a/os/windows/posix.c +++ b/os/windows/posix.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -19,21 +20,75 @@ #include #include "../os-windows.h" +#include "../../lib/hweight.h" + +extern unsigned long mtime_since_now(struct timeval *); +extern void fio_gettime(struct timeval *, void *); + +/* These aren't defined in the MinGW headers */ +HRESULT WINAPI StringCchCopyA( + char *pszDest, + size_t cchDest, + const char *pszSrc); + +HRESULT WINAPI StringCchPrintfA( + char *pszDest, + size_t cchDest, + const char *pszFormat, + ...); + +int vsprintf_s( + char *buffer, + size_t numberOfElements, + const char *format, + va_list argptr); + +int GetNumLogicalProcessors(void) +{ + SYSTEM_LOGICAL_PROCESSOR_INFORMATION *processor_info = NULL; + DWORD len = 0; + DWORD num_processors = 0; + DWORD error = 0; + DWORD i; + + while (!GetLogicalProcessorInformation(processor_info, &len)) { + error = GetLastError(); + if (error == ERROR_INSUFFICIENT_BUFFER) + processor_info = malloc(len); + else { + log_err("Error: GetLogicalProcessorInformation failed: %d\n", error); + return -1; + } + + if (processor_info == NULL) { + log_err("Error: failed to allocate memory for GetLogicalProcessorInformation"); + return -1; + } + } + + for (i = 0; i < len / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); i++) + { + if (processor_info[i].Relationship == RelationProcessorCore) + num_processors += hweight64(processor_info[i].ProcessorMask); + } + + free(processor_info); + return num_processors; +} long sysconf(int name) { - long long val = -1; - DWORD len; - SYSTEM_LOGICAL_PROCESSOR_INFORMATION processorInfo; + long val = -1; SYSTEM_INFO sysInfo; MEMORYSTATUSEX status; switch (name) { case _SC_NPROCESSORS_ONLN: - len = sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); - GetLogicalProcessorInformation(&processorInfo, &len); - val = len / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); + val = GetNumLogicalProcessors(); + if (val == -1) + log_err("_SC_NPROCESSORS_ONLN failed\n"); + break; case _SC_PAGESIZE: @@ -95,10 +150,10 @@ char *dlerror(void) int gettimeofday(struct timeval *restrict tp, void *restrict tzp) { FILETIME fileTime; - unsigned long long unix_time, windows_time; - const time_t MILLISECONDS_BETWEEN_1601_AND_1970 = 11644473600000; + uint64_t unix_time, windows_time; + const uint64_t MILLISECONDS_BETWEEN_1601_AND_1970 = 11644473600000; - // Ignore the timezone parameter + /* Ignore the timezone parameter */ (void)tzp; /* @@ -107,7 +162,7 @@ int gettimeofday(struct timeval *restrict tp, void *restrict tzp) * Its precision is 100 ns but accuracy is only one clock tick, or normally around 15 ms. */ GetSystemTimeAsFileTime(&fileTime); - windows_time = ((unsigned long long)fileTime.dwHighDateTime << 32) + fileTime.dwLowDateTime; + windows_time = ((uint64_t)fileTime.dwHighDateTime << 32) + fileTime.dwLowDateTime; /* Divide by 10,000 to convert to ms and subtract the time between 1601 and 1970 */ unix_time = (((windows_time)/10000) - MILLISECONDS_BETWEEN_1601_AND_1970); /* unix_time is now the number of milliseconds since 1970 (the Unix epoch) */ @@ -116,16 +171,20 @@ int gettimeofday(struct timeval *restrict tp, void *restrict tzp) return 0; } -void syslog(int priority, const char *message, ... /* argument */) -{ - log_err("%s is not implemented\n", __func__); -} - int sigaction(int sig, const struct sigaction *act, struct sigaction *oact) { - errno = ENOSYS; - return (-1); + int rc = 0; + void (*prev_handler)(int); + + prev_handler = signal(sig, act->sa_handler); + if (oact != NULL) + oact->sa_handler = prev_handler; + + if (prev_handler == SIG_ERR) + rc = -1; + + return rc; } int lstat(const char * path, struct stat * buf) @@ -175,14 +234,43 @@ pid_t setsid(void) return (-1); } +static HANDLE log_file = INVALID_HANDLE_VALUE; + void openlog(const char *ident, int logopt, int facility) { - log_err("%s is not implemented\n", __func__); + if (log_file == INVALID_HANDLE_VALUE) + log_file = CreateFileA("syslog.txt", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL); } void closelog(void) { - log_err("%s is not implemented\n", __func__); + CloseHandle(log_file); + log_file = INVALID_HANDLE_VALUE; +} + +void syslog(int priority, const char *message, ... /* argument */) +{ + va_list v; + int len; + char *output; + DWORD bytes_written; + + if (log_file == INVALID_HANDLE_VALUE) { + log_file = CreateFileA("syslog.txt", GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL); + } + + if (log_file == INVALID_HANDLE_VALUE) { + log_err("syslog: failed to open log file\n"); + return; + } + + va_start(v, message); + len = _vscprintf(message, v); + output = malloc(len + sizeof(char)); + vsprintf(output, message, v); + WriteFile(log_file, output, len, &bytes_written, NULL); + va_end(v); + free(output); } int kill(pid_t pid, int sig) @@ -191,12 +279,16 @@ int kill(pid_t pid, int sig) return (-1); } -// This is assumed to be used only by the network code, -// and so doesn't try and handle any of the other cases +/* + * This is assumed to be used only by the network code, + * and so doesn't try and handle any of the other cases + */ int fcntl(int fildes, int cmd, ...) { - // non-blocking mode doesn't work the same as in BSD sockets, - // so ignore it. + /* + * non-blocking mode doesn't work the same as in BSD sockets, + * so ignore it. + */ #if 0 va_list ap; int val, opt, status; @@ -251,7 +343,7 @@ int clock_gettime(clockid_t clock_id, struct timespec *tp) tp->tv_sec = counts.QuadPart / freq.QuadPart; /* Get the difference between the number of ns stored * in 'tv_sec' and that stored in 'counts' */ - unsigned long long t = tp->tv_sec * freq.QuadPart; + uint64_t 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 @@ -308,29 +400,69 @@ char *basename(char *path) i = strlen(path) - 1; - while (name[i] != '\\' && name[i] != '/' && i >= 0) + while (path[i] != '\\' && path[i] != '/' && i >= 0) i--; - strcpy(name, path + i); + strncpy(name, path + i + 1, MAX_PATH); return name; } int posix_fallocate(int fd, off_t offset, off_t len) { - log_err("%s is not implemented\n", __func__); - errno = ENOSYS; - return (-1); + const int BUFFER_SIZE = 256 * 1024; + int rc = 0; + char *buf; + unsigned int write_len; + unsigned int bytes_written; + off_t bytes_remaining = len; + + if (len == 0 || offset < 0) + return EINVAL; + + buf = malloc(BUFFER_SIZE); + + if (buf == NULL) + return ENOMEM; + + memset(buf, 0, BUFFER_SIZE); + + int64_t prev_pos = _telli64(fd); + + if (_lseeki64(fd, offset, SEEK_SET) == -1) + return errno; + + while (bytes_remaining > 0) { + if (bytes_remaining < BUFFER_SIZE) + write_len = (unsigned int)bytes_remaining; + else + write_len = BUFFER_SIZE; + + bytes_written = _write(fd, buf, write_len); + if (bytes_written == -1) { + rc = errno; + break; + } + + /* Don't allow Windows to cache the write: flush it to disk */ + _commit(fd); + + bytes_remaining -= bytes_written; + } + + free(buf); + _lseeki64(fd, prev_pos, SEEK_SET); + return rc; } int ftruncate(int fildes, off_t length) { BOOL bSuccess; - int old_pos = tell(fildes); - lseek(fildes, length, SEEK_SET); + int64_t prev_pos = _telli64(fildes); + _lseeki64(fildes, length, SEEK_SET); HANDLE hFile = (HANDLE)_get_osfhandle(fildes); bSuccess = SetEndOfFile(hFile); - lseek(fildes, old_pos, SEEK_SET); + _lseeki64(fildes, prev_pos, SEEK_SET); return !bSuccess; } @@ -346,7 +478,9 @@ HANDLE fileMappings[1024]; int shmget(key_t key, size_t size, int shmflg) { int mapid = -1; - HANDLE hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, (PAGE_EXECUTE_READWRITE | SEC_RESERVE), size >> 32, size & 0xFFFFFFFF, NULL); + uint32_t size_low = size & 0xFFFFFFFF; + uint32_t size_high = ((uint64_t)size) >> 32; + HANDLE hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, (PAGE_EXECUTE_READWRITE | SEC_RESERVE), size_high, size_low, NULL); if (hMapping != NULL) { fileMappings[nFileMappings] = hMapping; mapid = nFileMappings; @@ -410,7 +544,7 @@ int nice(int incr) int getrusage(int who, struct rusage *r_usage) { - const time_t SECONDS_BETWEEN_1601_AND_1970 = 11644473600; + const uint64_t SECONDS_BETWEEN_1601_AND_1970 = 11644473600; FILETIME cTime, eTime, kTime, uTime; time_t time; @@ -418,14 +552,14 @@ int getrusage(int who, struct rusage *r_usage) HANDLE hProcess = GetCurrentProcess(); GetProcessTimes(hProcess, &cTime, &eTime, &kTime, &uTime); - time = ((unsigned long long)uTime.dwHighDateTime << 32) + uTime.dwLowDateTime; + time = ((uint64_t)uTime.dwHighDateTime << 32) + uTime.dwLowDateTime; /* Divide by 10,000,000 to get the number of seconds and move the epoch from * 1601 to 1970 */ time = (time_t)(((time)/10000000) - SECONDS_BETWEEN_1601_AND_1970); r_usage->ru_utime.tv_sec = time; /* getrusage() doesn't care about anything other than seconds, so set tv_usec to 0 */ r_usage->ru_utime.tv_usec = 0; - time = ((unsigned long long)kTime.dwHighDateTime << 32) + kTime.dwLowDateTime; + time = ((uint64_t)kTime.dwHighDateTime << 32) + kTime.dwLowDateTime; /* Divide by 10,000,000 to get the number of seconds and move the epoch from * 1601 to 1970 */ time = (time_t)(((time)/10000000) - SECONDS_BETWEEN_1601_AND_1970); @@ -434,16 +568,20 @@ int getrusage(int who, struct rusage *r_usage) 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. +/* Windows doesn't support advice for memory pages. Just ignore it. */ int msync(void *addr, size_t len, int flags) { - log_err("%s is not implemented\n", __func__); errno = ENOSYS; return -1; } @@ -456,17 +594,17 @@ int fdatasync(int fildes) ssize_t pwrite(int fildes, const void *buf, size_t nbyte, off_t offset) { - long pos = tell(fildes); - ssize_t len = write(fildes, buf, nbyte); - lseek(fildes, pos, SEEK_SET); + int64_t pos = _telli64(fildes); + ssize_t len = _write(fildes, buf, nbyte); + _lseeki64(fildes, pos, SEEK_SET); return len; } ssize_t pread(int fildes, void *buf, size_t nbyte, off_t offset) { - long pos = tell(fildes); + int64_t pos = _telli64(fildes); ssize_t len = read(fildes, buf, nbyte); - lseek(fildes, pos, SEEK_SET); + _lseeki64(fildes, pos, SEEK_SET); return len; } @@ -490,39 +628,6 @@ long long strtoll(const char *restrict str, char **restrict endptr, return _strtoi64(str, endptr, base); } -char *strsep(char **stringp, const char *delim) -{ - char *orig = *stringp; - BOOL gotMatch = FALSE; - int i = 0; - int j = 0; - - if (*stringp == NULL) - return NULL; - - while ((*stringp)[i] != '\0') { - j = 0; - while (delim[j] != '\0') { - if ((*stringp)[i] == delim[j]) { - gotMatch = TRUE; - (*stringp)[i] = '\0'; - *stringp = *stringp + i + 1; - break; - } - j++; - } - if (gotMatch) - break; - - i++; - } - - if (!gotMatch) - *stringp = NULL; - - return orig; -} - int poll(struct pollfd fds[], nfds_t nfds, int timeout) { struct timeval tv; @@ -531,11 +636,11 @@ int poll(struct pollfd fds[], nfds_t nfds, int timeout) int i; int rc; - if (timeout != -1) - to = &tv; - - to->tv_sec = timeout / 1000; - to->tv_usec = (timeout % 1000) * 1000; + if (timeout != -1) { + to = &tv; + to->tv_sec = timeout / 1000; + to->tv_usec = (timeout % 1000) * 1000; + } FD_ZERO(&readfds); FD_ZERO(&writefds); @@ -554,7 +659,7 @@ int poll(struct pollfd fds[], nfds_t nfds, int timeout) if (fds[i].events & POLLOUT) FD_SET(fds[i].fd, &writefds); - FD_SET(fds[i].fd, &exceptfds); + FD_SET(fds[i].fd, &exceptfds); } rc = select(nfds, &readfds, &writefds, &exceptfds, to); @@ -582,30 +687,93 @@ int poll(struct pollfd fds[], nfds_t nfds, int timeout) int nanosleep(const struct timespec *rqtp, struct timespec *rmtp) { - log_err("%s is not implemented\n", __func__); - errno = ENOSYS; - return -1; + struct timeval tv; + DWORD ms_remaining; + DWORD ms_total = (rqtp->tv_sec * 1000) + (rqtp->tv_nsec / 1000000.0); + + if (ms_total == 0) + ms_total = 1; + + ms_remaining = ms_total; + + /* Since Sleep() can sleep for less than the requested time, add a loop to + ensure we only return after the requested length of time has elapsed */ + do { + fio_gettime(&tv, NULL); + Sleep(ms_remaining); + ms_remaining = ms_total - mtime_since_now(&tv); + } while (ms_remaining > 0 && ms_remaining < ms_total); + + /* this implementation will never sleep for less than the requested time */ + if (rmtp != NULL) { + rmtp->tv_sec = 0; + rmtp->tv_nsec = 0; + } + + return 0; } DIR *opendir(const char *dirname) { - log_err("%s is not implemented\n", __func__); - errno = ENOSYS; - return NULL; + struct dirent_ctx *dc = NULL; + + /* See if we can open it. If not, we'll return an error here */ + HANDLE file = CreateFileA(dirname, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (file != INVALID_HANDLE_VALUE) { + CloseHandle(file); + dc = (struct dirent_ctx*)malloc(sizeof(struct dirent_ctx)); + StringCchCopyA(dc->dirname, MAX_PATH, dirname); + dc->find_handle = INVALID_HANDLE_VALUE; + } else { + DWORD error = GetLastError(); + if (error == ERROR_FILE_NOT_FOUND) + errno = ENOENT; + + else if (error == ERROR_PATH_NOT_FOUND) + errno = ENOTDIR; + else if (error == ERROR_TOO_MANY_OPEN_FILES) + errno = ENFILE; + else if (error == ERROR_ACCESS_DENIED) + errno = EACCES; + else + errno = error; + } + + return dc; } int closedir(DIR *dirp) { - log_err("%s is not implemented\n", __func__); - errno = ENOSYS; - return -1; + if (dirp != NULL && dirp->find_handle != INVALID_HANDLE_VALUE) + FindClose(dirp->find_handle); + + free(dirp); + return 0; } struct dirent *readdir(DIR *dirp) { - log_err("%s is not implemented\n", __func__); - errno = ENOSYS; - return NULL; + static struct dirent de; + WIN32_FIND_DATA find_data; + + if (dirp == NULL) + return NULL; + + if (dirp->find_handle == INVALID_HANDLE_VALUE) { + char search_pattern[MAX_PATH]; + StringCchPrintfA(search_pattern, MAX_PATH, "%s\\*", dirp->dirname); + dirp->find_handle = FindFirstFileA(search_pattern, &find_data); + if (dirp->find_handle == INVALID_HANDLE_VALUE) + return NULL; + } else { + if (!FindNextFile(dirp->find_handle, &find_data)) + return NULL; + } + + StringCchCopyA(de.d_name, MAX_PATH, find_data.cFileName); + de.d_ino = 0; + + return &de; } uid_t geteuid(void) @@ -615,13 +783,6 @@ uid_t geteuid(void) return -1; } -int inet_aton(char *addr) -{ - log_err("%s is not implemented\n", __func__); - errno = ENOSYS; - return 0; -} - const char* inet_ntop(int af, const void *restrict src, char *restrict dst, socklen_t size) { @@ -658,6 +819,7 @@ const char* inet_ntop(int af, const void *restrict src, errno = ENOSPC; WSACleanup(); + return ret; }