1// Copyright 2018 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "util/sys_info.h" 6 7#include "base/logging.h" 8#include "util/build_config.h" 9 10#if defined(OS_POSIX) 11#include <sys/utsname.h> 12#include <unistd.h> 13#endif 14 15#if defined(OS_WIN) 16#include <windows.h> 17#include "base/win/registry.h" 18#endif 19 20bool IsLongPathsSupportEnabled() { 21#if defined(OS_WIN) 22 struct LongPathSupport { 23 LongPathSupport() { 24 // Probe ntdll.dll for RtlAreLongPathsEnabled, and call it if it exists. 25 HINSTANCE ntdll_lib = GetModuleHandleW(L"ntdll"); 26 if (ntdll_lib) { 27 using FunctionType = BOOLEAN(WINAPI*)(); 28 auto func_ptr = reinterpret_cast<FunctionType>( 29 GetProcAddress(ntdll_lib, "RtlAreLongPathsEnabled")); 30 if (func_ptr) { 31 supported = func_ptr(); 32 return; 33 } 34 } 35 36 // If the ntdll approach failed, the registry approach is still reliable, 37 // because the manifest should've always be linked with gn.exe in Windows. 38 const char16_t key_name[] = uR"(SYSTEM\CurrentControlSet\Control\FileSystem)"; 39 const char16_t value_name[] = u"LongPathsEnabled"; 40 41 base::win::RegKey key(HKEY_LOCAL_MACHINE, key_name, KEY_READ); 42 DWORD value; 43 if (key.ReadValueDW(value_name, &value) == ERROR_SUCCESS) { 44 supported = value == 1; 45 } 46 } 47 48 bool supported = false; 49 }; 50 51 static LongPathSupport s_long_paths; // constructed lazily 52 return s_long_paths.supported; 53#else 54 return true; 55#endif 56} 57 58std::string OperatingSystemArchitecture() { 59#if defined(OS_POSIX) 60 struct utsname info; 61 if (uname(&info) < 0) { 62 NOTREACHED(); 63 return std::string(); 64 } 65 std::string arch(info.machine); 66 std::string os(info.sysname); 67 if (arch == "i386" || arch == "i486" || arch == "i586" || arch == "i686") { 68 arch = "x86"; 69 } else if (arch == "i86pc") { 70 // Solaris and illumos systems report 'i86pc' (an Intel x86 PC) as their 71 // machine for both 32-bit and 64-bit x86 systems. Considering the rarity 72 // of 32-bit systems at this point, it is safe to assume 64-bit. 73 arch = "x86_64"; 74 } else if (arch == "amd64") { 75 arch = "x86_64"; 76 } else if (os == "AIX" || os == "OS400") { 77 arch = "ppc64"; 78 } else if (std::string(info.sysname) == "OS/390") { 79 arch = "s390x"; 80 } 81 return arch; 82#elif defined(OS_WIN) 83 SYSTEM_INFO system_info = {}; 84 ::GetNativeSystemInfo(&system_info); 85 switch (system_info.wProcessorArchitecture) { 86 case PROCESSOR_ARCHITECTURE_INTEL: 87 return "x86"; 88 case PROCESSOR_ARCHITECTURE_AMD64: 89 return "x86_64"; 90 case PROCESSOR_ARCHITECTURE_IA64: 91 return "ia64"; 92 } 93 return std::string(); 94#else 95#error 96#endif 97} 98 99int NumberOfProcessors() { 100#if defined(OS_ZOS) 101 return __get_num_online_cpus(); 102 103#elif defined(OS_POSIX) 104 // sysconf returns the number of "logical" (not "physical") processors on both 105 // Mac and Linux. So we get the number of max available "logical" processors. 106 // 107 // Note that the number of "currently online" processors may be fewer than the 108 // returned value of NumberOfProcessors(). On some platforms, the kernel may 109 // make some processors offline intermittently, to save power when system 110 // loading is low. 111 // 112 // One common use case that needs to know the processor count is to create 113 // optimal number of threads for optimization. It should make plan according 114 // to the number of "max available" processors instead of "currently online" 115 // ones. The kernel should be smart enough to make all processors online when 116 // it has sufficient number of threads waiting to run. 117 long res = sysconf(_SC_NPROCESSORS_CONF); 118 if (res == -1) { 119 NOTREACHED(); 120 return 1; 121 } 122 123 return static_cast<int>(res); 124#elif defined(OS_WIN) 125 // On machines with more than 64 logical processors this will not return the 126 // full number of processors. Instead it will return the number of processors 127 // in one processor group - something smaller than 65. However this is okay 128 // because gn doesn't parallelize well beyond 10-20 threads - it starts to run 129 // slower. 130 SYSTEM_INFO system_info = {}; 131 ::GetNativeSystemInfo(&system_info); 132 return system_info.dwNumberOfProcessors; 133#else 134#error 135#endif 136} 137