#include #include #include #include #include #include // THis file exists to avoid clashes between windows.h and idris_rts.h // int win_fpoll(FILE *f) { HANDLE wh = (HANDLE)_get_osfhandle(_fileno(f)); if (wh == INVALID_HANDLE_VALUE) { return -1; } DWORD ret = WaitForSingleObject(wh, 1000); // Imitate the return values of select() if (ret == WAIT_OBJECT_0) return 1; if (ret == WAIT_TIMEOUT) return 0; return -1; } int widen_utf8(const char *filename_utf8, LPWSTR *filename_w) { int num_chars = MultiByteToWideChar(CP_UTF8, 0, filename_utf8, -1, 0, 0); int size = sizeof(WCHAR); *filename_w = (LPWSTR)malloc(size * num_chars); MultiByteToWideChar(CP_UTF8, 0, filename_utf8, -1, *filename_w, num_chars); return num_chars; } FILE *win32_u8fopen(const char *path, const char *mode) { LPWSTR wpath, wmode; widen_utf8(path, &wpath); widen_utf8(mode, &wmode); FILE *f = _wfopen(wpath, wmode); free(wpath); free(wmode); return f; } FILE *win32_u8popen(const char *path, const char *mode) { LPWSTR wpath, wmode; widen_utf8(path, &wpath); widen_utf8(mode, &wmode); FILE *f = _wpopen(wpath, wmode); free(wpath); free(wmode); return f; } void win32_gettime(int64_t *sec, int64_t *nsec) { FILETIME ft; #ifdef _OLD_WIN GetSystemTimeAsFileTime(&ft); #else // For Windows NT 6.2 or higher GetSystemTimePreciseAsFileTime(&ft); #endif ULARGE_INTEGER t; t.HighPart = ft.dwHighDateTime; t.LowPart = ft.dwLowDateTime; *nsec = (t.QuadPart % 10000000) * 100; *sec = t.QuadPart / 10000000; *sec -= 11644473600; // LDAP epoch to Unix epoch } void win32_sleep(int ms) { Sleep(ms); } int win32_modenv(const char *name, const char *value, int overwrite) { if (!overwrite && getenv(name)) return 0; return _putenv_s(name, value); } int win32_getErrno() { return GetLastError(); } int win32_getPID() { return _getpid(); } typedef BOOL(WINAPI *LPFN_GLPI)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD); long win32_getNProcessors() { // largely taken from // https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getlogicalprocessorinformation BOOL done = FALSE; long nPhysicalProcessors = 0; long nSMTProcessors = 0; // length of array for storing the information structs DWORD returnLength = 0; // structs for storing the information PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL; PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL; // shortcut to a function (?) LPFN_GLPI glpi; glpi = (LPFN_GLPI)GetProcAddress(GetModuleHandle(TEXT("kernel32")), "GetLogicalProcessorInformation"); // to keep track of whether we're at the end of the array DWORD byteOffset = 0; // repeatedly try to malloc and retrieve the information until we have a // large enough array of information structs, or we fail to malloc while (!done) { DWORD rc = glpi(buffer, &returnLength); if (rc == FALSE) { if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { // this will happen initially since buffer = NULL and we need to // somehow retrieve the required size if (buffer) { free(buffer); } buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(returnLength); if (NULL == buffer) { // memory allocation error return -1; } } else { // something else went wrong return -1; } } else { done = TRUE; } } ptr = buffer; while ((byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION)) <= returnLength) { // if we have a processor core, count the processors if (ptr->Relationship == RelationProcessorCore) { nPhysicalProcessors++; // if we have an SMT-enabled CPU, we need to count the virtual // cores as well DWORD lshift = sizeof(ULONG_PTR) * 8 - 1; ULONG_PTR bitTest = (ULONG_PTR)1 << lshift; DWORD i; for (i = 0; i <= lshift; ++i) { // count the bit if it is set nSMTProcessors += ((ptr->ProcessorMask & bitTest) ? 1 : 0); // move the test to the next bit bitTest /= 2; } } // move to next info element byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); ptr++; } // return the larger number of physical vs SMT cores // (if this bothers you, overhaul this implementation with a solution that // distinguishes between types of cores on _both_ *NIX and Windows!) return nPhysicalProcessors == nSMTProcessors ? nPhysicalProcessors : nSMTProcessors; } int win32_getFileNo(FILE *f) { return _fileno(f); } int win32_getFileTime(FILE *f, int *atime_sec, int *atime_nsec, int *mtime_sec, int *mtime_nsec, int *ctime_sec, int *ctime_nsec) { HANDLE wh = (HANDLE)_get_osfhandle(_fileno(f)); if (wh == INVALID_HANDLE_VALUE) { return -1; } FILETIME atime, mtime, ctime; if (GetFileTime(wh, &ctime, &atime, &mtime)) { ULARGE_INTEGER at, mt, ct; at.HighPart = atime.dwHighDateTime; at.LowPart = atime.dwLowDateTime; mt.HighPart = mtime.dwHighDateTime; mt.LowPart = mtime.dwLowDateTime; ct.HighPart = ctime.dwHighDateTime; ct.LowPart = ctime.dwLowDateTime; *atime_sec = at.QuadPart / 10000000; *atime_sec -= 11644473600; *atime_nsec = (at.QuadPart % 10000000) * 100; *mtime_sec = mt.QuadPart / 10000000; *mtime_sec -= 11644473600; *mtime_nsec = (mt.QuadPart % 10000000) * 100; *ctime_sec = ct.QuadPart / 10000000; *ctime_sec -= 11644473600; *ctime_nsec = (ct.QuadPart % 10000000) * 100; return 0; } else { return -1; } } int win32_isTTY(int fd) { return _isatty(fd); }