system.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto 2 // Copyright (c) 2009-present The Bitcoin Core developers 3 // Distributed under the MIT software license, see the accompanying 4 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 5 6 #include <bitcoin-build-config.h> // IWYU pragma: keep 7 8 #include <common/system.h> 9 10 #include <logging.h> 11 #include <util/string.h> 12 #include <util/time.h> 13 14 #ifdef WIN32 15 #include <cassert> 16 #include <codecvt> 17 #include <compat/compat.h> 18 #include <windows.h> 19 #else 20 #include <sys/stat.h> 21 #include <unistd.h> 22 #endif 23 24 #ifdef HAVE_MALLOPT_ARENA_MAX 25 #include <malloc.h> 26 #endif 27 28 #include <algorithm> 29 #include <cstddef> 30 #include <cstdint> 31 #include <cstdlib> 32 #include <locale> 33 #include <optional> 34 #include <stdexcept> 35 #include <string> 36 #include <thread> 37 38 using util::ReplaceAll; 39 40 #ifndef WIN32 41 std::string ShellEscape(const std::string& arg) 42 { 43 std::string escaped = arg; 44 ReplaceAll(escaped, "'", "'\"'\"'"); 45 return "'" + escaped + "'"; 46 } 47 #endif 48 49 #if HAVE_SYSTEM 50 void runCommand(const std::string& strCommand) 51 { 52 if (strCommand.empty()) return; 53 #ifndef WIN32 54 int nErr = ::system(strCommand.c_str()); 55 #else 56 int nErr = ::_wsystem(std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t>().from_bytes(strCommand).c_str()); 57 #endif 58 if (nErr) { 59 LogWarning("runCommand error: system(%s) returned %d", strCommand, nErr); 60 } 61 } 62 #endif 63 64 void SetupEnvironment() 65 { 66 #ifdef HAVE_MALLOPT_ARENA_MAX 67 // glibc-specific: On 32-bit systems set the number of arenas to 1. 68 // By default, since glibc 2.10, the C library will create up to two heap 69 // arenas per core. This is known to cause excessive virtual address space 70 // usage in our usage. Work around it by setting the maximum number of 71 // arenas to 1. 72 if (sizeof(void*) == 4) { 73 mallopt(M_ARENA_MAX, 1); 74 } 75 #endif 76 // On most POSIX systems (e.g. Linux, but not BSD) the environment's locale 77 // may be invalid, in which case the "C.UTF-8" locale is used as fallback. 78 #if !defined(WIN32) && !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) 79 try { 80 std::locale(""); // Raises a runtime error if current locale is invalid 81 } catch (const std::runtime_error&) { 82 setenv("LC_ALL", "C.UTF-8", 1); 83 } 84 #elif defined(WIN32) 85 assert(GetACP() == CP_UTF8); 86 // Set the default input/output charset is utf-8 87 SetConsoleCP(CP_UTF8); 88 SetConsoleOutputCP(CP_UTF8); 89 #endif 90 91 #ifndef WIN32 92 constexpr mode_t private_umask = 0077; 93 umask(private_umask); 94 #endif 95 } 96 97 bool SetupNetworking() 98 { 99 #ifdef WIN32 100 // Initialize Windows Sockets 101 WSADATA wsadata; 102 int ret = WSAStartup(MAKEWORD(2,2), &wsadata); 103 if (ret != NO_ERROR || LOBYTE(wsadata.wVersion ) != 2 || HIBYTE(wsadata.wVersion) != 2) 104 return false; 105 #endif 106 return true; 107 } 108 109 int GetNumCores() 110 { 111 return std::thread::hardware_concurrency(); 112 } 113 114 std::optional<size_t> GetTotalRAM() 115 { 116 [[maybe_unused]] auto clamp{[](uint64_t v) { return size_t(std::min(v, uint64_t{std::numeric_limits<size_t>::max()})); }}; 117 #ifdef WIN32 118 if (MEMORYSTATUSEX m{}; (m.dwLength = sizeof(m), GlobalMemoryStatusEx(&m))) return clamp(m.ullTotalPhys); 119 #elif defined(__APPLE__) || \ 120 defined(__FreeBSD__) || \ 121 defined(__NetBSD__) || \ 122 defined(__OpenBSD__) || \ 123 defined(__illumos__) || \ 124 defined(__linux__) 125 if (long p{sysconf(_SC_PHYS_PAGES)}, s{sysconf(_SC_PAGESIZE)}; p > 0 && s > 0) return clamp(1ULL * p * s); 126 #endif 127 return std::nullopt; 128 } 129 130 namespace { 131 const auto g_startup_time{SteadyClock::now()}; 132 } // namespace 133 134 SteadyClock::duration GetUptime() { return SteadyClock::now() - g_startup_time; }