mariadb/windows/windows.c

377 lines
9.6 KiB
C
Raw Normal View History

#define _CRT_SECURE_NO_DEPRECATE
//rand_s requires _CRT_RAND_S be defined before including stdlib
#define _CRT_RAND_S
#include <stdlib.h>
#include <toku_portability.h>
#include <windows.h>
#include <dirent.h>
#include <toku_assert.h>
#include <direct.h>
#include <errno.h>
#include <io.h>
#include <malloc.h>
#include <process.h>
#include <share.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <Crtdbg.h>
#include <string.h>
static int
toku_malloc_init(void) {
int r = 0;
#if TOKU_WINDOWS_32
//Set the heap (malloc/free/realloc) to use the low fragmentation mode.
ULONG HeapFragValue = 2;
int success;
success = HeapSetInformation(GetProcessHeap(),
HeapCompatibilityInformation,
&HeapFragValue,
sizeof(HeapFragValue));
//if (success==0) //Do some error output if necessary.
if (!success)
r = GetLastError();
#endif
return r;
}
int
toku_portability_init(void) {
int r = 0;
if (r==0)
r = toku_malloc_init();
if (r==0)
r = toku_pthread_win32_init();
if (r==0)
r = toku_fsync_init();
if (r==0)
r = toku_mkstemp_init();
if (r==0)
_fmode = _O_BINARY; //Default open file is BINARY
return r;
}
int
toku_portability_destroy(void) {
int r = 0;
if (r==0)
r = toku_mkstemp_destroy();
if (r==0)
r = toku_fsync_destroy();
if (r==0)
r = toku_pthread_win32_destroy();
return r;
}
int
toku_os_get_file_size(int fildes, int64_t *sizep) {
int r;
int64_t size = _filelengthi64(fildes);
if (size<0) r = errno;
else {
r = 0;
*sizep = size;
}
return r;
}
uint64_t
toku_os_get_phys_memory_size(void) {
MEMORYSTATUS memory_status;
GlobalMemoryStatus(&memory_status);
return memory_status.dwTotalPhys;
}
int
toku_os_get_number_processors(void) {
SYSTEM_INFO system_info;
GetSystemInfo(&system_info);
return system_info.dwNumberOfProcessors;
}
int
toku_os_get_number_active_processors(void) {
SYSTEM_INFO system_info;
DWORD mask, n;
GetSystemInfo(&system_info);
mask = system_info.dwActiveProcessorMask;
for (n=0; mask; mask >>= 1)
n += mask & 1;
return n;
}
int
toku_os_get_pagesize(void) {
SYSTEM_INFO system_info;
GetSystemInfo(&system_info);
return system_info.dwPageSize;
}
int
toku_os_get_unique_file_id(int fildes, struct fileid *id) {
int r;
BY_HANDLE_FILE_INFORMATION info;
HANDLE filehandle;
memset(id, 0, sizeof(*id));
memset(&info, 0, sizeof(info));
filehandle = (HANDLE)_get_osfhandle(fildes);
if (filehandle==INVALID_HANDLE_VALUE) {
r = errno; assert(r!=0);
goto cleanup;
}
r = GetFileInformationByHandle(filehandle, &info);
if (r==0) { //0 is error here.
r = GetLastError(); assert(r!=0);
if (r==ERROR_INVALID_FUNCTION && info.dwVolumeSerialNumber == 0 &&
info.nFileIndexHigh == 0 && info.nFileIndexLow == 0) {
//"NUL" will return this.
//TODO: Remove this hack somehow
r = 0;
goto continue_dev_null;
}
goto cleanup;
}
//Make sure only "NUL" returns all zeros.
assert(info.dwVolumeSerialNumber!=0 || info.nFileIndexHigh!=0 || info.nFileIndexLow!=0);
continue_dev_null: //Skip zeros check (its allowed here).
id->st_dev = info.dwVolumeSerialNumber;
id->st_ino = info.nFileIndexHigh;
id->st_ino <<= 32;
id->st_ino |= info.nFileIndexLow;
r = 0;
cleanup:
if (r!=0) {
errno = r;
r = -1;
}
return r;
}
static void
convert_filetime_timeval(FILETIME ft, struct timeval *tv) {
ULARGE_INTEGER t;
t.u.HighPart = ft.dwHighDateTime;
t.u.LowPart = ft.dwLowDateTime;
t.QuadPart /= 10;
if (tv) {
tv->tv_sec = t.QuadPart / 1000000;
tv->tv_usec = t.QuadPart % 1000000;
}
}
int
toku_os_get_process_times(struct timeval *usertime, struct timeval *kerneltime) {
FILETIME w_createtime, w_exittime, w_usertime, w_kerneltime;
if (GetProcessTimes(GetCurrentProcess(), &w_createtime, &w_exittime, &w_kerneltime, &w_usertime)) {
convert_filetime_timeval(w_usertime, usertime);
convert_filetime_timeval(w_kerneltime, kerneltime);
return 0;
}
return GetLastError();
}
int
toku_os_getpid(void) {
#if 0
return _getpid();
#else
return GetCurrentProcessId();
#endif
}
int
toku_os_gettid(void) {
return GetCurrentThreadId();
}
int
toku_os_get_max_process_data_size(uint64_t *maxdata) {
#if TOKU_WINDOWS_32
// the process gets 1/2 of the 32 bit address space.
// we are ignoring the 3GB feature for now.
*maxdata = 1ULL << 31;
return 0;
#elif TOKU_WINDOWS_64
*maxdata = ~0ULL;
return 0;
#else
#error
return EINVAL;
#endif
}
int
toku_os_lock_file(char *name) {
int fd = _sopen(name, O_CREAT, _SH_DENYRW, S_IREAD|S_IWRITE);
return fd;
}
int
toku_os_unlock_file(int fildes) {
int r = close(fildes);
return r;
}
int
toku_os_mkdir(const char *pathname, mode_t mode) {
int r = mkdir(pathname);
UNUSED_WARNING(mode);
if (r!=0) r = errno;
return r;
}
static void printfParameterHandler(const wchar_t* expression,
const wchar_t* function, const wchar_t* file,
unsigned int line, uintptr_t pReserved) {
fwprintf(stderr, L"Invalid parameter detected in function %s."
L" File: %s Line: %d\n"
L"Expression: %s\n", function, file, line, expression);
}
static void ignoreParameterHandler(const wchar_t* expression,
const wchar_t* function, const wchar_t* file,
unsigned int line, uintptr_t pReserved) {
UNUSED_WARNING(expression);
UNUSED_WARNING(function);
UNUSED_WARNING(file);
UNUSED_WARNING(line);
UNUSED_WARNING(pReserved);
}
int
toku_os_initialize_settings(int verbosity) {
int r;
static int initialized = 0;
assert(initialized==0);
initialized=1;
if (verbosity>0)
_set_invalid_parameter_handler(printfParameterHandler);
else
_set_invalid_parameter_handler(ignoreParameterHandler);
#if defined(_DEBUG)
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
#endif
r = 0;
return r;
}
int
toku_os_is_absolute_name(const char* path) {
return (path[0] == '\\' ||
path[0] == '/' ||
(isalpha(path[0]) && path[1]==':' && path[2]=='\\') ||
(isalpha(path[0]) && path[1]==':' && path[2]=='/'));
}
int
vsnprintf(char *str, size_t size, const char *format, va_list ap) {
int r = _vsnprintf(str, size, format, ap);
if (str && size>0) {
str[size-1] = '\0'; //Always null terminate.
if (r<0 && errno==ERANGE) {
r = strlen(str)+1; //Mimic linux return value.
//May be too small, but it does
//at least indicate overflow
}
}
return r;
}
int
snprintf(char *str, size_t size, const char *format, ...) {
va_list ap;
va_start(ap, format);
int r = vsnprintf(str, size, format, ap);
va_end(ap);
return r;
}
#include <PowrProf.h>
#define TOKU_MICROSOFT_DID_NOT_DEFINE_PROCESSOR_POWER_INFORMATION 1
#if TOKU_MICROSOFT_DID_NOT_DEFINE_PROCESSOR_POWER_INFORMATION
//From MSDN: (As of Windows 2000)
// Note that this structure definition was accidentally omitted from WinNT.h.
// This error will be corrected in the future. In the meantime, to compile your
// application, include the structure definition contained in this topic in your
// source code.
typedef struct _PROCESSOR_POWER_INFORMATION {
ULONG Number;
ULONG MaxMhz;
ULONG CurrentMhz;
ULONG MhzLimit;
ULONG MaxIdleState;
ULONG CurrentIdleState;
}PROCESSOR_POWER_INFORMATION, *PPROCESSOR_POWER_INFORMATION;
#endif
int
toku_os_get_processor_frequency(uint64_t *hzret) {
SYSTEM_INFO sys_info;
// find out how many processors we have in the system
GetSystemInfo(&sys_info);
PROCESSOR_POWER_INFORMATION infos[sys_info.dwNumberOfProcessors];
memset(infos, 0, sizeof(infos));
NTSTATUS r = CallNtPowerInformation(ProcessorInformation, NULL, 0, &infos[0], sizeof(infos));
assert(r==ERROR_SUCCESS);
uint64_t mhz = infos[0].MaxMhz;
*hzret = mhz * 1000000ULL;
return 0;
}
int
toku_dup2(int fd, int fd2) {
int r;
r = _dup2(fd, fd2);
if (r==0) //success
r = fd2;
return r;
}
// for now, just return zeros
int
toku_get_filesystem_sizes(const char *path, uint64_t *avail_size, uint64_t *free_size, uint64_t *total_size) {
int r;
ULARGE_INTEGER free_bytes_for_user;
ULARGE_INTEGER free_bytes_total;
ULARGE_INTEGER total_bytes;
BOOL success = GetDiskFreeSpaceEx(path,
&free_bytes_for_user,
&total_bytes,
&free_bytes_total);
if (success) {
r = 0;
if (avail_size) *avail_size = free_bytes_for_user.QuadPart;
if (free_size) *free_size = free_bytes_total.QuadPart;
if (total_size) *total_size = total_bytes.QuadPart;
}
else {
r = GetLastError();
}
return r;
}
int strerror_r(int errnum, char *buf, size_t buflen) {
int r = strerror_s(buf, buflen, errnum);
return r;
}