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 <sys/sysctl.h>
8#include <sys/user.h>
9#include <unistd.h>
10
11#include "base/sys_info.h"
12
13namespace base {
14
15ProcessMetrics::ProcessMetrics(ProcessHandle process)
16    : process_(process),
17      last_system_time_(0),
18      last_cpu_(0) {
19  processor_count_ = base::SysInfo::NumberOfProcessors();
20}
21
22// static
23ProcessMetrics* ProcessMetrics::CreateProcessMetrics(ProcessHandle process) {
24  return new ProcessMetrics(process);
25}
26
27size_t ProcessMetrics::GetPagefileUsage() const {
28  struct kinfo_proc info;
29  int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process_ };
30  size_t length = sizeof(info);
31
32  if (sysctl(mib, arraysize(mib), &info, &length, NULL, 0) < 0)
33    return 0;
34
35  return info.ki_size;
36}
37
38size_t ProcessMetrics::GetPeakPagefileUsage() const {
39  return 0;
40}
41
42size_t ProcessMetrics::GetWorkingSetSize() const {
43  struct kinfo_proc info;
44  int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process_ };
45  size_t length = sizeof(info);
46
47  if (sysctl(mib, arraysize(mib), &info, &length, NULL, 0) < 0)
48    return 0;
49
50  return info.ki_rssize * getpagesize();
51}
52
53size_t ProcessMetrics::GetPeakWorkingSetSize() const {
54  return 0;
55}
56
57bool ProcessMetrics::GetMemoryBytes(size_t* private_bytes,
58                                    size_t* shared_bytes) {
59  WorkingSetKBytes ws_usage;
60  if (!GetWorkingSetKBytes(&ws_usage))
61    return false;
62
63  if (private_bytes)
64    *private_bytes = ws_usage.priv << 10;
65
66  if (shared_bytes)
67    *shared_bytes = ws_usage.shared * 1024;
68
69  return true;
70}
71
72bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
73// TODO(bapt) be sure we can't be precise
74  size_t priv = GetWorkingSetSize();
75  if (!priv)
76    return false;
77  ws_usage->priv = priv / 1024;
78  ws_usage->shareable = 0;
79  ws_usage->shared = 0;
80
81  return true;
82}
83
84double ProcessMetrics::GetCPUUsage() {
85  struct kinfo_proc info;
86  int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process_ };
87  size_t length = sizeof(info);
88
89  if (sysctl(mib, arraysize(mib), &info, &length, NULL, 0) < 0)
90    return 0;
91
92  return (info.ki_pctcpu / FSCALE) * 100.0;
93}
94
95bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
96  return false;
97}
98
99size_t GetSystemCommitCharge() {
100  int mib[2], pagesize;
101  unsigned long mem_total, mem_free, mem_inactive;
102  size_t length = sizeof(mem_total);
103
104  if (sysctl(mib, arraysize(mib), &mem_total, &length, NULL, 0) < 0)
105    return 0;
106
107  length = sizeof(mem_free);
108  if (sysctlbyname("vm.stats.vm.v_free_count", &mem_free, &length, NULL, 0) < 0)
109    return 0;
110
111  length = sizeof(mem_inactive);
112  if (sysctlbyname("vm.stats.vm.v_inactive_count", &mem_inactive, &length,
113      NULL, 0) < 0) {
114    return 0;
115  }
116
117  pagesize = getpagesize();
118
119  return mem_total - (mem_free*pagesize) - (mem_inactive*pagesize);
120}
121
122}  // namespace base
123