diff options
author | rsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-23 12:59:54 +0000 |
---|---|---|
committer | rsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-23 12:59:54 +0000 |
commit | 32f5e9a0783c3d03ec2351401d8c4100c153a499 (patch) | |
tree | 2a0d58988e8c1429380500961d5f20ce08dc5c60 /base/process_util_mac.mm | |
parent | 2ac90b1f8eff5bf3788f258bd8fbbcaaa023df91 (diff) | |
download | chromium_src-32f5e9a0783c3d03ec2351401d8c4100c153a499.zip chromium_src-32f5e9a0783c3d03ec2351401d8c4100c153a499.tar.gz chromium_src-32f5e9a0783c3d03ec2351401d8c4100c153a499.tar.bz2 |
Split ProcessMetrics out of base/process_util.h and into base/process/process_metrics.h.
BUG=242290
R=brettw@chromium.org
Review URL: https://codereview.chromium.org/15564006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@201775 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base/process_util_mac.mm')
-rw-r--r-- | base/process_util_mac.mm | 307 |
1 files changed, 0 insertions, 307 deletions
diff --git a/base/process_util_mac.mm b/base/process_util_mac.mm index e0174b4..c9f0ef7 100644 --- a/base/process_util_mac.mm +++ b/base/process_util_mac.mm @@ -184,313 +184,6 @@ bool NamedProcessIterator::IncludeEntry() { } -// ------------------------------------------------------------------------ -// NOTE: about ProcessMetrics -// -// 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 -// 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, -// otherwise return 0. -// - -ProcessMetrics::ProcessMetrics(ProcessHandle process, - ProcessMetrics::PortProvider* port_provider) - : process_(process), - last_time_(0), - last_system_time_(0), - port_provider_(port_provider) { - processor_count_ = SysInfo::NumberOfProcessors(); -} - -// static -ProcessMetrics* ProcessMetrics::CreateProcessMetrics( - ProcessHandle process, - ProcessMetrics::PortProvider* port_provider) { - return new ProcessMetrics(process, port_provider); -} - -bool ProcessMetrics::GetIOCounters(IoCounters* io_counters) const { - return false; -} - -static bool GetTaskInfo(mach_port_t task, task_basic_info_64* task_info_data) { - if (task == MACH_PORT_NULL) - return false; - mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT; - kern_return_t kr = task_info(task, - TASK_BASIC_INFO_64, - reinterpret_cast<task_info_t>(task_info_data), - &count); - // Most likely cause for failure: |task| is a zombie. - return kr == KERN_SUCCESS; -} - -size_t ProcessMetrics::GetPagefileUsage() const { - task_basic_info_64 task_info_data; - if (!GetTaskInfo(TaskForPid(process_), &task_info_data)) - return 0; - return task_info_data.virtual_size; -} - -size_t ProcessMetrics::GetPeakPagefileUsage() const { - return 0; -} - -size_t ProcessMetrics::GetWorkingSetSize() const { - task_basic_info_64 task_info_data; - if (!GetTaskInfo(TaskForPid(process_), &task_info_data)) - return 0; - return task_info_data.resident_size; -} - -size_t ProcessMetrics::GetPeakWorkingSetSize() const { - return 0; -} - -static bool GetCPUTypeForProcess(pid_t pid, cpu_type_t* cpu_type) { - size_t len = sizeof(*cpu_type); - int result = sysctlbyname("sysctl.proc_cputype", - cpu_type, - &len, - NULL, - 0); - if (result != 0) { - DPLOG(ERROR) << "sysctlbyname(""sysctl.proc_cputype"")"; - return false; - } - - return true; -} - -static bool IsAddressInSharedRegion(mach_vm_address_t addr, cpu_type_t type) { - if (type == CPU_TYPE_I386) - return addr >= SHARED_REGION_BASE_I386 && - addr < (SHARED_REGION_BASE_I386 + SHARED_REGION_SIZE_I386); - else if (type == CPU_TYPE_X86_64) - return addr >= SHARED_REGION_BASE_X86_64 && - addr < (SHARED_REGION_BASE_X86_64 + SHARED_REGION_SIZE_X86_64); - else - return false; -} - -// This is a rough approximation of the algorithm that libtop uses. -// private_bytes is the size of private resident memory. -// shared_bytes is the size of shared resident memory. -bool ProcessMetrics::GetMemoryBytes(size_t* private_bytes, - size_t* shared_bytes) { - kern_return_t kr; - size_t private_pages_count = 0; - size_t shared_pages_count = 0; - - if (!private_bytes && !shared_bytes) - return true; - - mach_port_t task = TaskForPid(process_); - if (task == MACH_PORT_NULL) { - DLOG(ERROR) << "Invalid process"; - return false; - } - - cpu_type_t cpu_type; - if (!GetCPUTypeForProcess(process_, &cpu_type)) - return false; - - // The same region can be referenced multiple times. To avoid double counting - // we need to keep track of which regions we've already counted. - base::hash_set<int> seen_objects; - - // We iterate through each VM region in the task's address map. For shared - // memory we add up all the pages that are marked as shared. Like libtop we - // try to avoid counting pages that are also referenced by other tasks. Since - // we don't have access to the VM regions of other tasks the only hint we have - // is if the address is in the shared region area. - // - // Private memory is much simpler. We simply count the pages that are marked - // as private or copy on write (COW). - // - // See libtop_update_vm_regions in - // http://www.opensource.apple.com/source/top/top-67/libtop.c - mach_vm_size_t size = 0; - for (mach_vm_address_t address = MACH_VM_MIN_ADDRESS;; address += size) { - vm_region_top_info_data_t info; - mach_msg_type_number_t info_count = VM_REGION_TOP_INFO_COUNT; - mach_port_t object_name; - kr = mach_vm_region(task, - &address, - &size, - VM_REGION_TOP_INFO, - (vm_region_info_t)&info, - &info_count, - &object_name); - if (kr == KERN_INVALID_ADDRESS) { - // We're at the end of the address space. - break; - } else if (kr != KERN_SUCCESS) { - DLOG(ERROR) << "Calling mach_vm_region failed with error: " - << mach_error_string(kr); - return false; - } - - if (IsAddressInSharedRegion(address, cpu_type) && - info.share_mode != SM_PRIVATE) - continue; - - if (info.share_mode == SM_COW && info.ref_count == 1) - info.share_mode = SM_PRIVATE; - - switch (info.share_mode) { - case SM_PRIVATE: - private_pages_count += info.private_pages_resident; - private_pages_count += info.shared_pages_resident; - break; - case SM_COW: - private_pages_count += info.private_pages_resident; - // Fall through - case SM_SHARED: - if (seen_objects.count(info.obj_id) == 0) { - // Only count the first reference to this region. - seen_objects.insert(info.obj_id); - shared_pages_count += info.shared_pages_resident; - } - break; - default: - break; - } - } - - vm_size_t page_size; - kr = host_page_size(task, &page_size); - if (kr != KERN_SUCCESS) { - DLOG(ERROR) << "Failed to fetch host page size, error: " - << mach_error_string(kr); - return false; - } - - if (private_bytes) - *private_bytes = private_pages_count * page_size; - if (shared_bytes) - *shared_bytes = shared_pages_count * page_size; - - return true; -} - -void ProcessMetrics::GetCommittedKBytes(CommittedKBytes* usage) const { -} - -bool ProcessMetrics::GetWorkingSetKBytes(WorkingSetKBytes* ws_usage) const { - 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) - -double ProcessMetrics::GetCPUUsage() { - mach_port_t task = TaskForPid(process_); - if (task == MACH_PORT_NULL) - return 0; - - kern_return_t kr; - - // Libtop explicitly loops over the threads (libtop_pinfo_update_cpu_usage() - // in libtop.c), but this is more concise and gives the same results: - 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, - reinterpret_cast<task_info_t>(&thread_info_data), - &thread_info_count); - if (kr != KERN_SUCCESS) { - // Most likely cause: |task| is a zombie. - return 0; - } - - task_basic_info_64 task_info_data; - if (!GetTaskInfo(task, &task_info_data)) - 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_NE(0U, time_delta); - if (time_delta == 0) - return 0; - - last_system_time_ = task_time; - last_time_ = time; - - return static_cast<double>(system_time_delta * 100.0) / time_delta; -} - -mach_port_t ProcessMetrics::TaskForPid(ProcessHandle process) const { - mach_port_t task = MACH_PORT_NULL; - if (port_provider_) - task = port_provider_->TaskForPid(process_); - if (task == MACH_PORT_NULL && process_ == getpid()) - task = mach_task_self(); - return task; -} - -// ------------------------------------------------------------------------ - -// Bytes committed by the system. -size_t GetSystemCommitCharge() { - base::mac::ScopedMachPort host(mach_host_self()); - mach_msg_type_number_t count = HOST_VM_INFO_COUNT; - vm_statistics_data_t data; - kern_return_t kr = host_statistics(host, HOST_VM_INFO, - reinterpret_cast<host_info_t>(&data), - &count); - if (kr) { - DLOG(WARNING) << "Failed to fetch host statistics."; - return 0; - } - - vm_size_t page_size; - kr = host_page_size(host, &page_size); - if (kr) { - DLOG(ERROR) << "Failed to fetch host page size."; - return 0; - } - - return (data.active_count * page_size) / 1024; -} - // These are helpers for EnableTerminationOnHeapCorruption, which is a no-op // on 64 bit Macs. #if ARCH_CPU_32_BITS |