OLD | NEW |
1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 | 5 |
6 #include "base/process_util.h" | 6 #include "base/process_util.h" |
7 | 7 |
8 #import <Cocoa/Cocoa.h> | 8 #import <Cocoa/Cocoa.h> |
9 #include <crt_externs.h> | 9 #include <crt_externs.h> |
10 #include <mach/mach.h> | 10 #include <mach/mach.h> |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
175 // Don't need to check the name, we did that w/in CheckForNextProcess. | 175 // Don't need to check the name, we did that w/in CheckForNextProcess. |
176 if (!filter_) | 176 if (!filter_) |
177 return true; | 177 return true; |
178 return filter_->Includes(entry_.pid, entry_.ppid); | 178 return filter_->Includes(entry_.pid, entry_.ppid); |
179 } | 179 } |
180 | 180 |
181 | 181 |
182 // ------------------------------------------------------------------------ | 182 // ------------------------------------------------------------------------ |
183 // NOTE: about ProcessMetrics | 183 // NOTE: about ProcessMetrics |
184 // | 184 // |
185 // Mac doesn't have /proc, and getting a mach task from a pid for another | 185 // Getting a mach task from a pid for another process requires permissions in |
186 // process requires permissions, so there doesn't really seem to be a way | 186 // general, so there doesn't really seem to be a way to do these (and spinning |
187 // to do these (and spinning up ps to fetch each stats seems dangerous to | 187 // up ps to fetch each stats seems dangerous to put in a base api for anyone to |
188 // put in a base api for anyone to call. | 188 // call). Child processes ipc their port, so return something if available, |
| 189 // otherwise return 0. |
189 // | 190 // |
190 bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const { | 191 bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const { |
191 return false; | 192 return false; |
192 } | 193 } |
| 194 |
| 195 static bool GetTaskInfo(mach_port_t task, task_basic_info_64* task_info_data) { |
| 196 if (!task) |
| 197 return false; |
| 198 mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT; |
| 199 kern_return_t kr = task_info(task, |
| 200 TASK_BASIC_INFO_64, |
| 201 reinterpret_cast<task_info_t>(task_info_data), |
| 202 &count); |
| 203 // Most likely cause for failure: |task| is a zombie. |
| 204 return kr == KERN_SUCCESS; |
| 205 } |
| 206 |
193 size_t ProcessMetrics::GetPagefileUsage() const { | 207 size_t ProcessMetrics::GetPagefileUsage() const { |
194 return 0; | 208 task_basic_info_64 task_info_data; |
| 209 if (!GetTaskInfo(TaskForPid(process_), &task_info_data)) |
| 210 return 0; |
| 211 return task_info_data.virtual_size; |
195 } | 212 } |
| 213 |
196 size_t ProcessMetrics::GetPeakPagefileUsage() const { | 214 size_t ProcessMetrics::GetPeakPagefileUsage() const { |
197 return 0; | 215 return 0; |
198 } | 216 } |
| 217 |
199 size_t ProcessMetrics::GetWorkingSetSize() const { | 218 size_t ProcessMetrics::GetWorkingSetSize() const { |
200 return 0; | 219 task_basic_info_64 task_info_data; |
| 220 if (!GetTaskInfo(TaskForPid(process_), &task_info_data)) |
| 221 return 0; |
| 222 return task_info_data.resident_size; |
201 } | 223 } |
| 224 |
202 size_t ProcessMetrics::GetPeakWorkingSetSize() const { | 225 size_t ProcessMetrics::GetPeakWorkingSetSize() const { |
203 return 0; | 226 return 0; |
204 } | 227 } |
205 | 228 |
206 size_t ProcessMetrics::GetPrivateBytes() const { | 229 size_t ProcessMetrics::GetPrivateBytes() const { |
207 return 0; | 230 return 0; |
208 } | 231 } |
209 | 232 |
210 void ProcessMetrics::GetCommittedKBytes(CommittedKBytes* usage) const { | 233 void ProcessMetrics::GetCommittedKBytes(CommittedKBytes* usage) const { |
211 } | 234 } |
212 | 235 |
213 bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const { | 236 bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const { |
214 return false; | 237 size_t priv = GetWorkingSetSize(); |
| 238 if (!priv) |
| 239 return false; |
| 240 ws_usage->priv = priv / 1024; |
| 241 ws_usage->shareable = 0; |
| 242 ws_usage->shared = 0; |
| 243 return true; |
| 244 } |
| 245 |
| 246 #define TIME_VALUE_TO_TIMEVAL(a, r) do { \ |
| 247 (r)->tv_sec = (a)->seconds; \ |
| 248 (r)->tv_usec = (a)->microseconds; \ |
| 249 } while (0) |
| 250 |
| 251 int ProcessMetrics::GetCPUUsage() { |
| 252 mach_port_t task = TaskForPid(process_); |
| 253 if (!task) |
| 254 return 0; |
| 255 |
| 256 kern_return_t kr; |
| 257 |
| 258 // TODO(thakis): Libtop doesn't use thread info. How can they get away |
| 259 // without it? |
| 260 task_thread_times_info thread_info_data; |
| 261 mach_msg_type_number_t thread_info_count = TASK_THREAD_TIMES_INFO_COUNT; |
| 262 kr = task_info(task, |
| 263 TASK_THREAD_TIMES_INFO, |
| 264 reinterpret_cast<task_info_t>(&thread_info_data), |
| 265 &thread_info_count); |
| 266 if (kr != KERN_SUCCESS) { |
| 267 // Most likely cause: |task| is a zombie. |
| 268 return 0; |
| 269 } |
| 270 |
| 271 task_basic_info_64 task_info_data; |
| 272 if (!GetTaskInfo(task, &task_info_data)) |
| 273 return 0; |
| 274 |
| 275 /* Set total_time. */ |
| 276 // thread info contains live time... |
| 277 struct timeval user_timeval, system_timeval, task_timeval; |
| 278 TIME_VALUE_TO_TIMEVAL(&thread_info_data.user_time, &user_timeval); |
| 279 TIME_VALUE_TO_TIMEVAL(&thread_info_data.system_time, &system_timeval); |
| 280 timeradd(&user_timeval, &system_timeval, &task_timeval); |
| 281 |
| 282 // ... task info contains terminated time. |
| 283 TIME_VALUE_TO_TIMEVAL(&task_info_data.user_time, &user_timeval); |
| 284 TIME_VALUE_TO_TIMEVAL(&task_info_data.system_time, &system_timeval); |
| 285 timeradd(&user_timeval, &task_timeval, &task_timeval); |
| 286 timeradd(&system_timeval, &task_timeval, &task_timeval); |
| 287 |
| 288 struct timeval now; |
| 289 int retval = gettimeofday(&now, NULL); |
| 290 if (retval) |
| 291 return 0; |
| 292 |
| 293 int64 time = TimeValToMicroseconds(now); |
| 294 int64 task_time = TimeValToMicroseconds(task_timeval); |
| 295 |
| 296 if ((last_system_time_ == 0) || (last_time_ == 0)) { |
| 297 // First call, just set the last values. |
| 298 last_system_time_ = task_time; |
| 299 last_time_ = time; |
| 300 return 0; |
| 301 } |
| 302 |
| 303 int64 system_time_delta = task_time - last_system_time_; |
| 304 int64 time_delta = time - last_time_; |
| 305 DCHECK(time_delta != 0); |
| 306 if (time_delta == 0) |
| 307 return 0; |
| 308 |
| 309 // We add time_delta / 2 so the result is rounded. |
| 310 int cpu = static_cast<int>((system_time_delta * 100 + time_delta / 2) / |
| 311 (time_delta)); |
| 312 |
| 313 last_system_time_ = task_time; |
| 314 last_time_ = time; |
| 315 |
| 316 return cpu; |
| 317 } |
| 318 |
| 319 mach_port_t ProcessMetrics::TaskForPid(ProcessHandle process) const { |
| 320 mach_port_t task = 0; |
| 321 if (port_provider_) |
| 322 task = port_provider_->TaskForPid(process_); |
| 323 if (!task && process_ == getpid()) |
| 324 task = mach_task_self(); |
| 325 return task; |
215 } | 326 } |
216 | 327 |
217 // ------------------------------------------------------------------------ | 328 // ------------------------------------------------------------------------ |
218 | 329 |
219 // Bytes committed by the system. | 330 // Bytes committed by the system. |
220 size_t GetSystemCommitCharge() { | 331 size_t GetSystemCommitCharge() { |
221 host_name_port_t host = mach_host_self(); | 332 host_name_port_t host = mach_host_self(); |
222 mach_msg_type_number_t count = HOST_VM_INFO_COUNT; | 333 mach_msg_type_number_t count = HOST_VM_INFO_COUNT; |
223 vm_statistics_data_t data; | 334 vm_statistics_data_t data; |
224 kern_return_t kr = host_statistics(host, HOST_VM_INFO, | 335 kern_return_t kr = host_statistics(host, HOST_VM_INFO, |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 CHECK(g_old_malloc && g_old_calloc && g_old_valloc && g_old_realloc) | 432 CHECK(g_old_malloc && g_old_calloc && g_old_valloc && g_old_realloc) |
322 << "Failed to get system allocation functions."; | 433 << "Failed to get system allocation functions."; |
323 | 434 |
324 default_zone->malloc = oom_killer_malloc; | 435 default_zone->malloc = oom_killer_malloc; |
325 default_zone->calloc = oom_killer_calloc; | 436 default_zone->calloc = oom_killer_calloc; |
326 default_zone->valloc = oom_killer_valloc; | 437 default_zone->valloc = oom_killer_valloc; |
327 default_zone->realloc = oom_killer_realloc; | 438 default_zone->realloc = oom_killer_realloc; |
328 } | 439 } |
329 | 440 |
330 } // namespace base | 441 } // namespace base |
OLD | NEW |