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