1 // Copyright (c) 2011 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 "base/sys_info.h"
6 
7 #include <errno.h>
8 #include <stddef.h>
9 #include <stdint.h>
10 #include <string.h>
11 #include <sys/param.h>
12 #include <sys/resource.h>
13 #include <sys/utsname.h>
14 #include <unistd.h>
15 
16 #include "base/files/file_util.h"
17 #include "base/lazy_instance.h"
18 #include "base/logging.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/sys_info_internal.h"
21 #include "base/threading/thread_restrictions.h"
22 #include "build/build_config.h"
23 
24 #if defined(OS_ANDROID)
25 #include <sys/vfs.h>
26 #define statvfs statfs  // Android uses a statvfs-like statfs struct and call.
27 #else
28 #include <sys/statvfs.h>
29 #endif
30 
31 namespace {
32 
33 #if !defined(OS_OPENBSD)
NumberOfProcessors()34 int NumberOfProcessors() {
35   // sysconf returns the number of "logical" (not "physical") processors on both
36   // Mac and Linux.  So we get the number of max available "logical" processors.
37   //
38   // Note that the number of "currently online" processors may be fewer than the
39   // returned value of NumberOfProcessors(). On some platforms, the kernel may
40   // make some processors offline intermittently, to save power when system
41   // loading is low.
42   //
43   // One common use case that needs to know the processor count is to create
44   // optimal number of threads for optimization. It should make plan according
45   // to the number of "max available" processors instead of "currently online"
46   // ones. The kernel should be smart enough to make all processors online when
47   // it has sufficient number of threads waiting to run.
48   long res = sysconf(_SC_NPROCESSORS_CONF);
49   if (res == -1) {
50     NOTREACHED();
51     return 1;
52   }
53 
54   return static_cast<int>(res);
55 }
56 
57 base::LazyInstance<
58     base::internal::LazySysInfoValue<int, NumberOfProcessors> >::Leaky
59     g_lazy_number_of_processors = LAZY_INSTANCE_INITIALIZER;
60 #endif
61 
AmountOfVirtualMemory()62 int64_t AmountOfVirtualMemory() {
63   struct rlimit limit;
64   int result = getrlimit(RLIMIT_DATA, &limit);
65   if (result != 0) {
66     NOTREACHED();
67     return 0;
68   }
69   return limit.rlim_cur == RLIM_INFINITY ? 0 : limit.rlim_cur;
70 }
71 
72 base::LazyInstance<
73     base::internal::LazySysInfoValue<int64_t, AmountOfVirtualMemory>>::Leaky
74     g_lazy_virtual_memory = LAZY_INSTANCE_INITIALIZER;
75 
76 }  // namespace
77 
78 namespace base {
79 
80 #if !defined(OS_OPENBSD)
NumberOfProcessors()81 int SysInfo::NumberOfProcessors() {
82   return g_lazy_number_of_processors.Get().value();
83 }
84 #endif
85 
86 // static
AmountOfVirtualMemory()87 int64_t SysInfo::AmountOfVirtualMemory() {
88   return g_lazy_virtual_memory.Get().value();
89 }
90 
91 // static
AmountOfFreeDiskSpace(const FilePath & path)92 int64_t SysInfo::AmountOfFreeDiskSpace(const FilePath& path) {
93   base::ThreadRestrictions::AssertIOAllowed();
94 
95   struct statvfs stats;
96   if (HANDLE_EINTR(statvfs(path.value().c_str(), &stats)) != 0)
97     return -1;
98   return static_cast<int64_t>(stats.f_bavail) * stats.f_frsize;
99 }
100 
101 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
102 // static
OperatingSystemName()103 std::string SysInfo::OperatingSystemName() {
104   struct utsname info;
105   if (uname(&info) < 0) {
106     NOTREACHED();
107     return std::string();
108   }
109   return std::string(info.sysname);
110 }
111 #endif
112 
113 #if !defined(OS_MACOSX) && !defined(OS_ANDROID)
114 // static
OperatingSystemVersion()115 std::string SysInfo::OperatingSystemVersion() {
116   struct utsname info;
117   if (uname(&info) < 0) {
118     NOTREACHED();
119     return std::string();
120   }
121   return std::string(info.release);
122 }
123 #endif
124 
125 // static
OperatingSystemArchitecture()126 std::string SysInfo::OperatingSystemArchitecture() {
127   struct utsname info;
128   if (uname(&info) < 0) {
129     NOTREACHED();
130     return std::string();
131   }
132   std::string arch(info.machine);
133   if (arch == "i386" || arch == "i486" || arch == "i586" || arch == "i686") {
134     arch = "x86";
135   } else if (arch == "amd64") {
136     arch = "x86_64";
137   }
138   return arch;
139 }
140 
141 // static
VMAllocationGranularity()142 size_t SysInfo::VMAllocationGranularity() {
143   return getpagesize();
144 }
145 
146 }  // namespace base
147