Chromium Code Reviews| Index: base/process_util_mac.mm |
| diff --git a/base/process_util_mac.mm b/base/process_util_mac.mm |
| index 91944e81ab5bccca9b0a3f3e375c7b99a387c83e..d6768ff7b8a406291af42d99b83b32a254c7e9ef 100644 |
| --- a/base/process_util_mac.mm |
| +++ b/base/process_util_mac.mm |
| @@ -182,23 +182,50 @@ bool NamedProcessIterator::IncludeEntry() { |
| // ------------------------------------------------------------------------ |
| // NOTE: about ProcessMetrics |
| // |
| -// Mac doesn't have /proc, and getting a mach task from a pid for another |
| -// process requires permissions, so there doesn't really seem to be a way |
| -// to do these (and spinning up ps to fetch each stats seems dangerous to |
| -// put in a base api for anyone to call. |
| +// Getting a mach task from a pid for another process requires permissions in |
| +// general, so there doesn't really seem to be a way to do these (and spinning |
|
Mark Mentovai
2009/12/18 22:18:24
Revise this. The parenthetical never ends.
Nico
2009/12/18 22:46:52
Done.
|
| +// up ps to fetch each stats seems dangerous to put in a base api for anyone to |
| +// call. Child processes ipc their port, so return something if available, else |
|
Mark Mentovai
2009/12/18 22:18:24
When speaking English, "otherwise" is friendlier t
Nico
2009/12/18 22:46:52
Done.
kexinli365
2016/05/08 01:09:31
Acknowledged.
|
| +// return 0. |
| // |
| bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const { |
| return false; |
| } |
| + |
| size_t ProcessMetrics::GetPagefileUsage() const { |
| - return 0; |
| + mach_port_t task = TaskForPid(process_); |
|
Mark Mentovai
2009/12/18 22:18:24
D'ya need to check if task exists? You do that ch
Nico
2009/12/18 22:46:52
Done.
|
| + task_basic_info_64 task_info_data; |
| + mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT; |
| + kern_return_t kr = task_info(task, |
| + TASK_BASIC_INFO_64, |
| + (task_info_t)&task_info_data, |
|
Mark Mentovai
2009/12/18 22:18:24
Prefer C++<style>(casts) unless you need to chain
Nico
2009/12/18 22:46:52
Done.
|
| + &count); |
| + if (kr != KERN_SUCCESS) { |
| + // Most likely cause: |task| is a zombie. |
| + return 0; |
| + } |
| + return task_info_data.virtual_size; |
| } |
| + |
| size_t ProcessMetrics::GetPeakPagefileUsage() const { |
| return 0; |
| } |
| + |
| size_t ProcessMetrics::GetWorkingSetSize() const { |
| - return 0; |
| + mach_port_t task = TaskForPid(process_); |
| + task_basic_info_64 task_info_data; |
| + mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT; |
| + kern_return_t kr = task_info(task, |
|
Mark Mentovai
2009/12/18 22:18:24
Refactor into a common function to populate a task
Nico
2009/12/18 22:46:52
Done.
kexinli365
2016/05/08 01:09:31
Done.
|
| + TASK_BASIC_INFO_64, |
| + (task_info_t)&task_info_data, |
| + &count); |
| + if (kr != KERN_SUCCESS) { |
| + // Most likely cause: |task| is a zombie. |
| + return 0; |
| + } |
| + return task_info_data.resident_size; |
| } |
| + |
| size_t ProcessMetrics::GetPeakWorkingSetSize() const { |
| return 0; |
| } |
| @@ -211,7 +238,104 @@ void ProcessMetrics::GetCommittedKBytes(CommittedKBytes* usage) const { |
| } |
| bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const { |
| - return false; |
| + size_t priv = GetWorkingSetSize(); |
| + if (!priv) |
| + return false; |
| + ws_usage->priv = priv / 1024; |
| + ws_usage->shareable = 0; |
| + ws_usage->shared = 0; |
| + return true; |
| +} |
| + |
| +#define TIME_VALUE_TO_TIMEVAL(a, r) do { \ |
| + (r)->tv_sec = (a)->seconds; \ |
| + (r)->tv_usec = (a)->microseconds; \ |
| +} while (0) |
| + |
| +int ProcessMetrics::GetCPUUsage() { |
| + mach_port_t task = TaskForPid(process_); |
| + if (!task) { |
| + // Most likely cause: |task| is a zombie. |
| + return 0; |
| + } |
| + |
| + kern_return_t kr; |
| + |
| + // TODO(thakis): Libtop doesn't use thread info. How can they get away |
| + // without it? |
| + task_thread_times_info thread_info_data; |
| + mach_msg_type_number_t thread_info_count = TASK_THREAD_TIMES_INFO_COUNT; |
| + kr = task_info(task, |
| + TASK_THREAD_TIMES_INFO, |
| + (task_info_t)&thread_info_data, |
|
Mark Mentovai
2009/12/18 22:18:24
C++-style cast again.
Nico
2009/12/18 22:46:52
Done.
|
| + &thread_info_count); |
| + if (kr != KERN_SUCCESS) { |
| + LOG(ERROR) << "Failed to get thread info for task" << task; |
|
Mark Mentovai
2009/12/18 22:18:24
You need a space at the end of your string literal
Nico
2009/12/18 22:46:52
Done.
|
| + return 0; |
| + } |
| + |
| + task_basic_info_64 task_info_data; |
| + mach_msg_type_number_t task_basic_info_count = TASK_BASIC_INFO_64_COUNT; |
| + kr = task_info(task, |
| + TASK_BASIC_INFO_64, |
| + (task_info_t)&task_info_data, |
| + &task_basic_info_count); |
| + if (kr != KERN_SUCCESS) { |
| + LOG(ERROR) << "Failed to get task info for task" << task; |
| + return 0; |
| + } |
| + |
| + /* Set total_time. */ |
| + // thread info contains live time... |
| + struct timeval user_timeval, system_timeval, task_timeval; |
| + TIME_VALUE_TO_TIMEVAL(&thread_info_data.user_time, &user_timeval); |
| + TIME_VALUE_TO_TIMEVAL(&thread_info_data.system_time, &system_timeval); |
| + timeradd(&user_timeval, &system_timeval, &task_timeval); |
| + |
| + // ... task info contains terminated time. |
| + TIME_VALUE_TO_TIMEVAL(&task_info_data.user_time, &user_timeval); |
| + TIME_VALUE_TO_TIMEVAL(&task_info_data.system_time, &system_timeval); |
| + timeradd(&user_timeval, &task_timeval, &task_timeval); |
| + timeradd(&system_timeval, &task_timeval, &task_timeval); |
| + |
| + struct timeval now; |
| + int retval = gettimeofday(&now, NULL); |
| + if (retval) |
| + return 0; |
| + |
| + int64 time = TimeValToMicroseconds(now); |
| + int64 task_time = TimeValToMicroseconds(task_timeval); |
| + |
| + if ((last_system_time_ == 0) || (last_time_ == 0)) { |
| + // First call, just set the last values. |
| + last_system_time_ = task_time; |
| + last_time_ = time; |
| + return 0; |
| + } |
| + |
| + int64 system_time_delta = task_time - last_system_time_; |
| + int64 time_delta = time - last_time_; |
| + DCHECK(time_delta != 0); |
| + if (time_delta == 0) |
| + return 0; |
| + |
| + // We add time_delta / 2 so the result is rounded. |
| + int cpu = static_cast<int>((system_time_delta * 100 + time_delta / 2) / |
| + (time_delta)); |
| + |
| + last_system_time_ = task_time; |
| + last_time_ = time; |
| + |
| + return cpu; |
| +} |
| + |
| +mach_port_t ProcessMetrics::TaskForPid(ProcessHandle process) const { |
| + mach_port_t task = 0; |
| + if (port_provider_) |
| + task = port_provider_->TaskForPid(process_); |
| + if (!task && process_ == getpid()) |
| + task = mach_task_self(); |
| + return task; |
| } |
| // ------------------------------------------------------------------------ |