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
IsLongPathsSupportEnabled()20 bool 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
OperatingSystemArchitecture()58 std::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
NumberOfProcessors()99 int 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