xref: /third_party/gn/src/util/sys_info.cc (revision 6d528ed9)
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