1 // Copyright (c) 2013 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/process/process_metrics.h"
6 
7 #include <limits.h>
8 #include <stddef.h>
9 #include <stdint.h>
10 #include <sys/time.h>
11 #include <unistd.h>
12 
13 #include "base/logging.h"
14 #include "build/build_config.h"
15 
16 #if !defined(OS_FUCHSIA)
17 #include <sys/resource.h>
18 #endif
19 
20 #if defined(OS_MACOSX)
21 #include <malloc/malloc.h>
22 #else
23 #include <malloc.h>
24 #endif
25 
26 namespace base {
27 
TimeValToMicroseconds(const struct timeval & tv)28 int64_t TimeValToMicroseconds(const struct timeval& tv) {
29   int64_t ret = tv.tv_sec;  // Avoid (int * int) integer overflow.
30   ret *= Time::kMicrosecondsPerSecond;
31   ret += tv.tv_usec;
32   return ret;
33 }
34 
35 ProcessMetrics::~ProcessMetrics() = default;
36 
37 #if !defined(OS_FUCHSIA)
38 
39 #if defined(OS_LINUX)
40 static const rlim_t kSystemDefaultMaxFds = 8192;
41 #elif defined(OS_MACOSX)
42 static const rlim_t kSystemDefaultMaxFds = 256;
43 #elif defined(OS_SOLARIS)
44 static const rlim_t kSystemDefaultMaxFds = 8192;
45 #elif defined(OS_FREEBSD)
46 static const rlim_t kSystemDefaultMaxFds = 8192;
47 #elif defined(OS_NETBSD)
48 static const rlim_t kSystemDefaultMaxFds = 1024;
49 #elif defined(OS_OPENBSD)
50 static const rlim_t kSystemDefaultMaxFds = 256;
51 #elif defined(OS_ANDROID)
52 static const rlim_t kSystemDefaultMaxFds = 1024;
53 #elif defined(OS_AIX)
54 static const rlim_t kSystemDefaultMaxFds = 8192;
55 #endif
56 
GetMaxFds()57 size_t GetMaxFds() {
58   rlim_t max_fds;
59   struct rlimit nofile;
60   if (getrlimit(RLIMIT_NOFILE, &nofile)) {
61     // getrlimit failed. Take a best guess.
62     max_fds = kSystemDefaultMaxFds;
63     RAW_LOG(ERROR, "getrlimit(RLIMIT_NOFILE) failed");
64   } else {
65     max_fds = nofile.rlim_cur;
66   }
67 
68   if (max_fds > INT_MAX)
69     max_fds = INT_MAX;
70 
71   return static_cast<size_t>(max_fds);
72 }
73 
IncreaseFdLimitTo(unsigned int max_descriptors)74 void IncreaseFdLimitTo(unsigned int max_descriptors) {
75   struct rlimit limits;
76   if (getrlimit(RLIMIT_NOFILE, &limits) == 0) {
77     unsigned int new_limit = max_descriptors;
78     if (max_descriptors <= limits.rlim_cur)
79       return;
80     if (limits.rlim_max > 0 && limits.rlim_max < max_descriptors) {
81       new_limit = limits.rlim_max;
82     }
83     limits.rlim_cur = new_limit;
84     if (setrlimit(RLIMIT_NOFILE, &limits) != 0) {
85       PLOG(INFO) << "Failed to set file descriptor limit";
86     }
87   } else {
88     PLOG(INFO) << "Failed to get file descriptor limit";
89   }
90 }
91 
92 #endif  // !defined(OS_FUCHSIA)
93 
GetPageSize()94 size_t GetPageSize() {
95   return getpagesize();
96 }
97 
GetMallocUsage()98 size_t ProcessMetrics::GetMallocUsage() {
99 #if defined(OS_MACOSX) || defined(OS_IOS)
100   malloc_statistics_t stats = {0};
101   malloc_zone_statistics(nullptr, &stats);
102   return stats.size_in_use;
103 #elif defined(OS_LINUX) || defined(OS_ANDROID)
104   struct mallinfo minfo = mallinfo();
105 #if defined(USE_TCMALLOC)
106   return minfo.uordblks;
107 #else
108   return minfo.hblkhd + minfo.arena;
109 #endif
110 #elif defined(OS_FUCHSIA)
111   // TODO(fuchsia): Not currently exposed. https://crbug.com/735087.
112   return 0;
113 #endif
114 }
115 
116 }  // namespace base
117