diff options
Diffstat (limited to '3rdparty/bx/src/os.cpp')
-rw-r--r-- | 3rdparty/bx/src/os.cpp | 454 |
1 files changed, 454 insertions, 0 deletions
diff --git a/3rdparty/bx/src/os.cpp b/3rdparty/bx/src/os.cpp new file mode 100644 index 00000000000..5f1d45945b7 --- /dev/null +++ b/3rdparty/bx/src/os.cpp @@ -0,0 +1,454 @@ +/* + * Copyright 2010-2017 Branimir Karadzic. All rights reserved. + * License: https://github.com/bkaradzic/bx#license-bsd-2-clause + */ + +#include <bx/os.h> +#include <bx/uint32_t.h> +#include <bx/string.h> + +#include <stdio.h> + +#if BX_PLATFORM_WINDOWS || BX_PLATFORM_WINRT +# include <windows.h> +# include <psapi.h> +#elif BX_PLATFORM_ANDROID \ + || BX_PLATFORM_EMSCRIPTEN \ + || BX_PLATFORM_BSD \ + || BX_PLATFORM_HURD \ + || BX_PLATFORM_IOS \ + || BX_PLATFORM_LINUX \ + || BX_PLATFORM_NACL \ + || BX_PLATFORM_OSX \ + || BX_PLATFORM_PS4 \ + || BX_PLATFORM_RPI \ + || BX_PLATFORM_STEAMLINK +# include <sched.h> // sched_yield +# if BX_PLATFORM_BSD \ + || BX_PLATFORM_IOS \ + || BX_PLATFORM_NACL \ + || BX_PLATFORM_OSX \ + || BX_PLATFORM_PS4 \ + || BX_PLATFORM_STEAMLINK +# include <pthread.h> // mach_port_t +# endif // BX_PLATFORM_* + +# include <time.h> // nanosleep +# if !BX_PLATFORM_PS4 && !BX_PLATFORM_NACL +# include <dlfcn.h> // dlopen, dlclose, dlsym +# endif // !BX_PLATFORM_PS4 && !BX_PLATFORM_NACL + +# if BX_PLATFORM_ANDROID +# include <malloc.h> // mallinfo +# elif BX_PLATFORM_LINUX \ + || BX_PLATFORM_RPI \ + || BX_PLATFORM_STEAMLINK +# include <unistd.h> // syscall +# include <sys/syscall.h> +# elif BX_PLATFORM_OSX +# include <mach/mach.h> // mach_task_basic_info +# elif BX_PLATFORM_HURD +# include <pthread/pthread.h> // pthread_self +# elif BX_PLATFORM_ANDROID +# include "debug.h" // getTid is not implemented... +# endif // BX_PLATFORM_ANDROID +#endif // BX_PLATFORM_ + +#if BX_CRT_MSVC +# include <direct.h> // _getcwd +#else +# include <unistd.h> // getcwd +#endif // BX_CRT_MSVC + +namespace bx +{ + + void sleep(uint32_t _ms) + { +#if BX_PLATFORM_WINDOWS || BX_PLATFORM_XBOX360 + ::Sleep(_ms); +#elif BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT + BX_UNUSED(_ms); + debugOutput("sleep is not implemented"); debugBreak(); +#else + timespec req = {(time_t)_ms/1000, (long)((_ms%1000)*1000000)}; + timespec rem = {0, 0}; + ::nanosleep(&req, &rem); +#endif // BX_PLATFORM_ + } + + void yield() + { +#if BX_PLATFORM_WINDOWS + ::SwitchToThread(); +#elif BX_PLATFORM_XBOX360 + ::Sleep(0); +#elif BX_PLATFORM_XBOXONE || BX_PLATFORM_WINRT + debugOutput("yield is not implemented"); debugBreak(); +#else + ::sched_yield(); +#endif // BX_PLATFORM_ + } + + uint32_t getTid() + { +#if BX_PLATFORM_WINDOWS + return ::GetCurrentThreadId(); +#elif BX_PLATFORM_LINUX || BX_PLATFORM_RPI || BX_PLATFORM_STEAMLINK + return (pid_t)::syscall(SYS_gettid); +#elif BX_PLATFORM_IOS || BX_PLATFORM_OSX + return (mach_port_t)::pthread_mach_thread_np(pthread_self() ); +#elif BX_PLATFORM_BSD || BX_PLATFORM_NACL + // Casting __nc_basic_thread_data*... need better way to do this. + return *(uint32_t*)::pthread_self(); +#elif BX_PLATFORM_HURD + return (pthread_t)::pthread_self(); +#else +//# pragma message "not implemented." + debugOutput("getTid is not implemented"); debugBreak(); + return 0; +#endif // + } + + size_t getProcessMemoryUsed() + { +#if BX_PLATFORM_ANDROID + struct mallinfo mi = mallinfo(); + return mi.uordblks; +#elif BX_PLATFORM_LINUX || BX_PLATFORM_HURD + FILE* file = fopen("/proc/self/statm", "r"); + if (NULL == file) + { + return 0; + } + + long pages = 0; + int items = fscanf(file, "%*s%ld", &pages); + fclose(file); + return 1 == items + ? pages * sysconf(_SC_PAGESIZE) + : 0 + ; +#elif BX_PLATFORM_OSX +# if defined(MACH_TASK_BASIC_INFO) + mach_task_basic_info info; + mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT; + + int const result = task_info(mach_task_self() + , MACH_TASK_BASIC_INFO + , (task_info_t)&info + , &infoCount + ); +# else // MACH_TASK_BASIC_INFO + task_basic_info info; + mach_msg_type_number_t infoCount = TASK_BASIC_INFO_COUNT; + + int const result = task_info(mach_task_self() + , TASK_BASIC_INFO + , (task_info_t)&info + , &infoCount + ); +# endif // MACH_TASK_BASIC_INFO + if (KERN_SUCCESS != result) + { + return 0; + } + + return info.resident_size; +#elif BX_PLATFORM_WINDOWS + PROCESS_MEMORY_COUNTERS pmc; + GetProcessMemoryInfo(GetCurrentProcess() + , &pmc + , sizeof(pmc) + ); + return pmc.WorkingSetSize; +#else + return 0; +#endif // BX_PLATFORM_* + } + + void* dlopen(const char* _filePath) + { +#if BX_PLATFORM_WINDOWS + return (void*)::LoadLibraryA(_filePath); +#elif BX_PLATFORM_EMSCRIPTEN \ + || BX_PLATFORM_NACL \ + || BX_PLATFORM_PS4 \ + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT + BX_UNUSED(_filePath); + return NULL; +#else + return ::dlopen(_filePath, RTLD_LOCAL|RTLD_LAZY); +#endif // BX_PLATFORM_ + } + + void dlclose(void* _handle) + { +#if BX_PLATFORM_WINDOWS + ::FreeLibrary( (HMODULE)_handle); +#elif BX_PLATFORM_EMSCRIPTEN \ + || BX_PLATFORM_NACL \ + || BX_PLATFORM_PS4 \ + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT + BX_UNUSED(_handle); +#else + ::dlclose(_handle); +#endif // BX_PLATFORM_ + } + + void* dlsym(void* _handle, const char* _symbol) + { +#if BX_PLATFORM_WINDOWS + return (void*)::GetProcAddress( (HMODULE)_handle, _symbol); +#elif BX_PLATFORM_EMSCRIPTEN \ + || BX_PLATFORM_NACL \ + || BX_PLATFORM_PS4 \ + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT + BX_UNUSED(_handle, _symbol); + return NULL; +#else + return ::dlsym(_handle, _symbol); +#endif // BX_PLATFORM_ + } + + bool getenv(const char* _name, char* _out, uint32_t* _inOutSize) + { +#if BX_PLATFORM_WINDOWS + DWORD len = ::GetEnvironmentVariableA(_name, _out, *_inOutSize); + bool result = len != 0 && len < *_inOutSize; + *_inOutSize = len; + return result; +#elif BX_PLATFORM_PS4 \ + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT + BX_UNUSED(_name, _out, _inOutSize); + return false; +#else + const char* ptr = ::getenv(_name); + uint32_t len = 0; + bool result = false; + if (NULL != ptr) + { + len = (uint32_t)strnlen(ptr); + + result = len != 0 && len < *_inOutSize; + if (len < *_inOutSize) + { + strcpy(_out, ptr); + } + } + + *_inOutSize = len; + return result; +#endif // BX_PLATFORM_ + } + + void setenv(const char* _name, const char* _value) + { +#if BX_PLATFORM_WINDOWS + ::SetEnvironmentVariableA(_name, _value); +#elif BX_PLATFORM_PS4 \ + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT + BX_UNUSED(_name, _value); +#else + ::setenv(_name, _value, 1); +#endif // BX_PLATFORM_ + } + + void unsetenv(const char* _name) + { +#if BX_PLATFORM_WINDOWS + ::SetEnvironmentVariableA(_name, NULL); +#elif BX_PLATFORM_PS4 \ + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT + BX_UNUSED(_name); +#else + ::unsetenv(_name); +#endif // BX_PLATFORM_ + } + + int chdir(const char* _path) + { +#if BX_PLATFORM_PS4 \ + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT + BX_UNUSED(_path); + return -1; +#elif BX_CRT_MSVC + return ::_chdir(_path); +#else + return ::chdir(_path); +#endif // BX_COMPILER_ + } + + char* pwd(char* _buffer, uint32_t _size) + { +#if BX_PLATFORM_PS4 \ + || BX_PLATFORM_XBOXONE \ + || BX_PLATFORM_WINRT + BX_UNUSED(_buffer, _size); + return NULL; +#elif BX_CRT_MSVC + return ::_getcwd(_buffer, (int)_size); +#else + return ::getcwd(_buffer, _size); +#endif // BX_COMPILER_ + } + + bool getTempPath(char* _out, uint32_t* _inOutSize) + { +#if BX_PLATFORM_WINDOWS + uint32_t len = ::GetTempPathA(*_inOutSize, _out); + bool result = len != 0 && len < *_inOutSize; + *_inOutSize = len; + return result; +#else + static const char* s_tmp[] = + { + "TMPDIR", + "TMP", + "TEMP", + "TEMPDIR", + + NULL + }; + + for (const char** tmp = s_tmp; *tmp != NULL; ++tmp) + { + uint32_t len = *_inOutSize; + *_out = '\0'; + bool result = getenv(*tmp, _out, &len); + + if (result + && len != 0 + && len < *_inOutSize) + { + *_inOutSize = len; + return result; + } + } + + FileInfo fi; + if (stat("/tmp", fi) + && FileInfo::Directory == fi.m_type) + { + strlncpy(_out, *_inOutSize, "/tmp"); + *_inOutSize = 4; + return true; + } + + return false; +#endif // BX_PLATFORM_* + } + + bool stat(const char* _filePath, FileInfo& _fileInfo) + { + _fileInfo.m_size = 0; + _fileInfo.m_type = FileInfo::Count; + +#if BX_COMPILER_MSVC + struct ::_stat64 st; + int32_t result = ::_stat64(_filePath, &st); + + if (0 != result) + { + return false; + } + + if (0 != (st.st_mode & _S_IFREG) ) + { + _fileInfo.m_type = FileInfo::Regular; + } + else if (0 != (st.st_mode & _S_IFDIR) ) + { + _fileInfo.m_type = FileInfo::Directory; + } +#else + struct ::stat st; + int32_t result = ::stat(_filePath, &st); + if (0 != result) + { + return false; + } + + if (0 != (st.st_mode & S_IFREG) ) + { + _fileInfo.m_type = FileInfo::Regular; + } + else if (0 != (st.st_mode & S_IFDIR) ) + { + _fileInfo.m_type = FileInfo::Directory; + } +#endif // BX_COMPILER_MSVC + + _fileInfo.m_size = st.st_size; + + return true; + } + + void* exec(const char* const* _argv) + { +#if BX_PLATFORM_LINUX || BX_PLATFORM_HURD + pid_t pid = fork(); + + if (0 == pid) + { + int result = execvp(_argv[0], const_cast<char *const*>(&_argv[1]) ); + BX_UNUSED(result); + return NULL; + } + + return (void*)uintptr_t(pid); +#elif BX_PLATFORM_WINDOWS + STARTUPINFO si; + memset(&si, 0, sizeof(STARTUPINFO) ); + si.cb = sizeof(STARTUPINFO); + + PROCESS_INFORMATION pi; + memset(&pi, 0, sizeof(PROCESS_INFORMATION) ); + + int32_t total = 0; + for (uint32_t ii = 0; NULL != _argv[ii]; ++ii) + { + total += (int32_t)strnlen(_argv[ii]) + 1; + } + + char* temp = (char*)alloca(total); + int32_t len = 0; + for(uint32_t ii = 0; NULL != _argv[ii]; ++ii) + { + len += snprintf(&temp[len], bx::uint32_imax(0, total-len) + , "%s " + , _argv[ii] + ); + } + + bool ok = !!CreateProcessA(_argv[0] + , temp + , NULL + , NULL + , false + , 0 + , NULL + , NULL + , &si + , &pi + ); + if (ok) + { + return pi.hProcess; + } + + return NULL; +#else + BX_UNUSED(_argv); + return NULL; +#endif // BX_PLATFORM_LINUX || BX_PLATFORM_HURD + } + +} // namespace bx |