chromium 11.0.969.72
[chromium.git] / patches / patch-base_process__util__netbsd.cc
1 $NetBSD$
2
3 --- base/process_util_netbsd.cc.orig    2011-04-26 05:17:12.000000000 +0000
4 +++ base/process_util_netbsd.cc
5 @@ -0,0 +1,358 @@
6 +// Copyright (c) 2009 The Chromium Authors. All rights reserved.
7 +// Use of this source code is governed by a BSD-style license that can be
8 +// found in the LICENSE file.
9 +
10 +#include "base/process_util.h"
11 +
12 +#include <ctype.h>
13 +#include <dirent.h>
14 +#include <dlfcn.h>
15 +#include <errno.h>
16 +#include <fcntl.h>
17 +#include <sys/time.h>
18 +#include <sys/types.h>
19 +#include <sys/wait.h>
20 +#include <sys/param.h>
21 +#include <sys/sysctl.h>
22 +#include <sys/user.h>
23 +#include <time.h>
24 +#include <unistd.h>
25 +
26 +#include "base/file_util.h"
27 +#include "base/logging.h"
28 +#include "base/string_number_conversions.h"
29 +#include "base/string_split.h"
30 +#include "base/string_tokenizer.h"
31 +#include "base/string_util.h"
32 +#include "base/sys_info.h"
33 +#include "base/threading/thread_restrictions.h"
34 +
35 +namespace base {
36 +
37 +ProcessId GetParentProcessId(ProcessHandle process) {
38 +  struct kinfo_proc2 info;
39 +  int mib[6];
40 +  size_t info_size = sizeof(info);
41 +
42 +  mib[0] = CTL_KERN;
43 +  mib[1] = KERN_PROC;
44 +  mib[2] = KERN_PROC_PID;
45 +  mib[3] = process;
46 +  mib[4] = info_size;
47 +  mib[5] = 400; /* XXX */
48 +
49 +  if (sysctl(mib, 6, &info, &info_size, NULL, 0) < 0)
50 +    return -1;
51 +
52 +  return info.p_ppid;
53 +}
54 +
55 +FilePath GetProcessExecutablePath(ProcessHandle process) {
56 +  printf("%s\n", __PRETTY_FUNCTION__);
57 +
58 +  FilePath stat_file("/proc");
59 +  stat_file = stat_file.Append(base::IntToString(process));
60 +  stat_file = stat_file.Append("exe");
61 +  FilePath exe_name;
62 +  if (!file_util::ReadSymbolicLink(stat_file, &exe_name)) {
63 +    // No such process.  Happens frequently in e.g. TerminateAllChromeProcesses
64 +    return FilePath();
65 +  }
66 +  return exe_name;
67 +}
68 +
69 +ProcessIterator::ProcessIterator(const ProcessFilter* filter)
70 +  : index_of_kinfo_proc_(),
71 +  filter_(filter) {
72 +
73 +  int mib[6];
74 +
75 +  printf("%s\n", __PRETTY_FUNCTION__);
76 +
77 +  mib[0] = CTL_KERN;
78 +  mib[1] = KERN_PROC;
79 +  mib[2] = KERN_PROC_UID;
80 +  mib[3] = getuid();
81 +  mib[4] = sizeof(struct kinfo_proc2);
82 +  mib[5] = 0;
83 +
84 +  bool done = false;
85 +  int try_num = 1;
86 +  const int max_tries = 10;
87 +
88 +  do {
89 +    size_t len = 0;
90 +    if (sysctl(mib, 6, NULL, &len, NULL, 0) <0 ){
91 +      LOG(ERROR) << "failed to get the size needed for the process list";
92 +      kinfo_procs_.resize(0);
93 +      done = true;
94 +    } else {
95 +      size_t num_of_kinfo_proc = len / sizeof(struct kinfo_proc2);
96 +      // Leave some spare room for process table growth (more could show up
97 +      // between when we check and now)
98 +      num_of_kinfo_proc += 16;
99 +      kinfo_procs_.resize(num_of_kinfo_proc);
100 +      len = num_of_kinfo_proc * sizeof(struct kinfo_proc2);
101 +      if (sysctl(mib, 6, &kinfo_procs_[0], &len, NULL, 0) <0) {
102 +        // If we get a mem error, it just means we need a bigger buffer, so
103 +        // loop around again.  Anything else is a real error and give up.
104 +        if (errno != ENOMEM) {
105 +          LOG(ERROR) << "failed to get the process list";
106 +          kinfo_procs_.resize(0);
107 +          done = true;
108 +        }
109 +      } else {
110 +        // Got the list, just make sure we're sized exactly right
111 +        size_t num_of_kinfo_proc = len / sizeof(struct kinfo_proc2);
112 +        kinfo_procs_.resize(num_of_kinfo_proc);
113 +        done = true;
114 +      }
115 +    }
116 +  } while (!done && (try_num++ < max_tries));
117 +
118 +  if (!done) {
119 +    LOG(ERROR) << "failed to collect the process list in a few tries";
120 +    kinfo_procs_.resize(0);
121 +  }
122 +}
123 +
124 +ProcessIterator::~ProcessIterator() {
125 +}
126 +
127 +bool ProcessIterator::CheckForNextProcess() {
128 +  std::string data;
129 +
130 +  printf("%s\n", __PRETTY_FUNCTION__);
131 +
132 +  for (; index_of_kinfo_proc_ < kinfo_procs_.size(); ++ index_of_kinfo_proc_) {
133 +    int mib[3];
134 +    size_t len;
135 +    struct kinfo_proc2 kinfo = kinfo_procs_[index_of_kinfo_proc_];
136 +
137 +    if ((kinfo.p_pid > 0) && (kinfo.p_stat == SZOMB))
138 +      continue;
139 +
140 +    mib[0] = CTL_KERN;
141 +    mib[1] = KERN_PROC_ARGS;
142 +    mib[2] = kinfo.p_pid;
143 +
144 +    len = 0;
145 +    if (sysctl(mib, 3, NULL, &len, NULL, 0) < 0) {
146 +      LOG(ERROR) << "failed to figure out the buffer size for a command line";
147 +      continue;
148 +    }
149 +
150 +    data.resize(len);
151 +
152 +    if (sysctl(mib, 3, &data[0], &len, NULL, 0) < 0) {
153 +      LOG(ERROR) << "failed to fetch a commandline";
154 +      continue;
155 +    }
156 +
157 +    std::string delimiters;
158 +    delimiters.push_back('\0');
159 +    Tokenize(data, delimiters, &entry_.cmd_line_args_);
160 +
161 +    size_t exec_name_end = data.find('\0');
162 +    if (exec_name_end == std::string::npos) {
163 +      LOG(ERROR) << "command line data didn't match expected format";
164 +      continue;
165 +    }
166 +
167 +    entry_.pid_ = kinfo.p_pid;
168 +    entry_.ppid_ = kinfo.p_ppid;
169 +    entry_.gid_ = kinfo.p__pgid;
170 +
171 +    size_t last_slash = data.rfind('/', exec_name_end);
172 +    if (last_slash == std::string::npos)
173 +      entry_.exe_file_.assign(data, 0, exec_name_end);
174 +    else
175 +      entry_.exe_file_.assign(data, last_slash + 1,
176 +                              exec_name_end - last_slash - 1);
177 +
178 +    // Start w/ the next entry next time through
179 +    ++index_of_kinfo_proc_;
180 +
181 +    return true;
182 +  }
183 +  return false;
184 +}
185 +
186 +bool NamedProcessIterator::IncludeEntry() {
187 +  return (executable_name_ == entry().exe_file() &&
188 +                           ProcessIterator::IncludeEntry());
189 +}
190 +
191 +
192 +ProcessMetrics::ProcessMetrics(ProcessHandle process)
193 +    : process_(process),
194 +      last_time_(0),
195 +      last_system_time_(0),
196 +      last_cpu_(0) {
197 +
198 +  processor_count_ = base::SysInfo::NumberOfProcessors();
199 +}
200 +
201 +// static
202 +ProcessMetrics* ProcessMetrics::CreateProcessMetrics(ProcessHandle process) {
203 +  return new ProcessMetrics(process);
204 +}
205 +
206 +size_t ProcessMetrics::GetPagefileUsage() const {
207 +  struct kinfo_proc2 info;
208 +  int mib[6];
209 +  size_t info_size = sizeof(info);
210 +
211 +  mib[0] = CTL_KERN;
212 +  mib[1] = KERN_PROC;
213 +  mib[2] = KERN_PROC_PID;
214 +  mib[3] = process_;
215 +  mib[4] = info_size;
216 +  mib[5] = 400; /* XXX */
217 +
218 +  if (sysctl(mib, 6, &info, &info_size, NULL, 0) < 0)
219 +    return 0;
220 +
221 +  return (info.p_vm_tsize + info.p_vm_dsize + info.p_vm_ssize);
222 +}
223 +
224 +size_t ProcessMetrics::GetPeakPagefileUsage() const {
225 +       printf("%s\n", __PRETTY_FUNCTION__);
226 +
227 +  return 0;
228 +}
229 +
230 +size_t ProcessMetrics::GetWorkingSetSize() const {
231 +  struct kinfo_proc2 info;
232 +  int mib[6];
233 +  size_t info_size = sizeof(info);
234 +
235 +  mib[0] = CTL_KERN;
236 +  mib[1] = KERN_PROC;
237 +  mib[2] = KERN_PROC_PID;
238 +  mib[3] = process_;
239 +  mib[4] = info_size;
240 +  mib[5] = 400; /* XXX */
241 +
242 +  if (sysctl(mib, 6, &info, &info_size, NULL, 0) < 0)
243 +    return 0;
244 +
245 +  return info.p_vm_rssize * getpagesize();
246 +}
247 +
248 +size_t ProcessMetrics::GetPeakWorkingSetSize() const {
249 +       printf("%s\n", __PRETTY_FUNCTION__);
250 +
251 +  return 0;
252 +}
253 +
254 +bool ProcessMetrics::GetMemoryBytes(size_t* private_bytes,
255 +                                    size_t* shared_bytes) {
256 +  WorkingSetKBytes ws_usage;
257 +
258 +  if (!GetWorkingSetKBytes(&ws_usage))
259 +    return false;
260 +
261 +  if (private_bytes)
262 +    *private_bytes = ws_usage.priv << 10;
263 +
264 +  if (shared_bytes)
265 +    *shared_bytes = ws_usage.shared * 1024;
266 +
267 +  return true;
268 +}
269 +
270 +bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const {
271 +// TODO(bapt) be sure we can't be precise
272 +  size_t priv = GetWorkingSetSize();
273 +  if (!priv)
274 +    return false;
275 +  ws_usage->priv = priv / 1024;
276 +  ws_usage->shareable = 0;
277 +  ws_usage->shared = 0;
278 +
279 +  return true;
280 +}
281 +
282 +bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const {
283 +  return false;
284 +}
285 +
286 +static int GetProcessCPU(pid_t pid) {
287 +  struct kinfo_proc2 info;
288 +  int mib[6];
289 +  size_t info_size = sizeof(info);
290 +
291 +  mib[0] = CTL_KERN;
292 +  mib[1] = KERN_PROC;
293 +  mib[2] = KERN_PROC_PID;
294 +  mib[3] = pid;
295 +  mib[4] = info_size;
296 +  mib[5] = 400; /* XXX */
297 +
298 +  if (sysctl(mib, 6, &info, &info_size, NULL, 0) < 0)
299 +    return 0;
300 +
301 +  return info.p_pctcpu;
302 +}
303 +
304 +double ProcessMetrics::GetCPUUsage() {
305 +  struct timeval now;
306 +
307 +  int retval = gettimeofday(&now, NULL);
308 +  if (retval)
309 +    return 0;
310 +
311 +  int64 time = TimeValToMicroseconds(now);
312 +
313 +  if (last_time_ == 0) {
314 +    // First call, just set the last values.
315 +    last_time_ = time;
316 +    last_cpu_ = GetProcessCPU(process_);
317 +    return 0;
318 +  }
319 +
320 +  int64 time_delta = time - last_time_;
321 +  DCHECK_NE(time_delta, 0);
322 +
323 +  if (time_delta == 0)
324 +    return 0;
325 +
326 +  int cpu = GetProcessCPU(process_);
327 +
328 +  last_time_ = time;
329 +  last_cpu_ = cpu;
330 +
331 +  double percentage = static_cast<double>((cpu * 100.0) / FSCALE);
332 +
333 +  return percentage;
334 +}
335 +
336 +size_t GetSystemCommitCharge() {
337 +  int mib[2], pagesize;
338 +  struct vmtotal vmtotal;
339 +  unsigned long mem_total, mem_free, mem_inactive;
340 +  size_t len = sizeof(vmtotal);
341 +
342 +  printf("%s\n", __PRETTY_FUNCTION__);
343 +
344 +  mib[0] = CTL_VM;
345 +  mib[1] = VM_METER;
346 +
347 +  if (sysctl(mib, 2, &vmtotal, &len, NULL, 0) < 0)
348 +    return 0;
349 +
350 +  mem_total = vmtotal.t_vm;
351 +  mem_free = vmtotal.t_free;
352 +  mem_inactive = vmtotal.t_vm - vmtotal.t_avm;
353 +
354 +  pagesize = getpagesize();
355 +
356 +  return mem_total - (mem_free*pagesize) - (mem_inactive*pagesize);
357 +}
358 +
359 +void EnableTerminationOnOutOfMemory() {
360 +  NOTIMPLEMENTED();
361 +  return;
362 +}
363 +}