mirror of
https://github.com/idris-lang/Idris2.git
synced 2024-12-22 11:13:36 +03:00
206 lines
5.7 KiB
C
206 lines
5.7 KiB
C
#include <io.h>
|
|
#include <process.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <windows.h>
|
|
|
|
// 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); }
|