/* * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "cpu_mac.h" #include <iostream> #include <mach/mach.h> #include <mach/mach_error.h> #include "tick_util.h" namespace webrtc { CpuWrapperMac::CpuWrapperMac() : _cpuUsage(NULL) { natural_t cpuCount; processor_info_array_t infoArray; mach_msg_type_number_t infoCount; kern_return_t error = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &cpuCount, &infoArray, &infoCount); if (error) { return; } _cpuUsage = new WebRtc_UWord32[cpuCount]; _lastTickCount = new WebRtc_Word64[cpuCount]; _lastTime = TickTime::MillisecondTimestamp(); processor_cpu_load_info_data_t* cpuLoadInfo = (processor_cpu_load_info_data_t*) infoArray; for (unsigned int cpu= 0; cpu < cpuCount; cpu++) { WebRtc_Word64 ticks = 0; for (int state = 0; state < 2; state++) { ticks += cpuLoadInfo[cpu].cpu_ticks[state]; } _lastTickCount[cpu] = ticks; } vm_deallocate(mach_task_self(), (vm_address_t)infoArray, infoCount); } CpuWrapperMac::~CpuWrapperMac() { delete _cpuUsage; delete _lastTickCount; } WebRtc_Word32 CpuWrapperMac::CpuUsage() { WebRtc_UWord32 numCores; WebRtc_UWord32* array = NULL; return CpuUsageMultiCore(numCores, array); } WebRtc_Word32 CpuWrapperMac::CpuUsageMultiCore(WebRtc_UWord32& numCores, WebRtc_UWord32*& array) { natural_t cpuCount; processor_info_array_t infoArray; mach_msg_type_number_t infoCount; // sanity check if(_cpuUsage == NULL) { return -1; } WebRtc_Word64 now = TickTime::MillisecondTimestamp(); WebRtc_Word64 timeDiffMS = now - _lastTime; // TODO(hellner) why block here? Why not just return the old // value? Is this behavior consistent across all // platforms? // Make sure that at least 500 ms pass between calls. if(timeDiffMS < 500) { usleep((500-timeDiffMS)*1000); return CpuUsageMultiCore(numCores, array); } _lastTime = now; kern_return_t error = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO, &cpuCount, &infoArray, &infoCount); if (error) { return -1; } processor_cpu_load_info_data_t* cpuLoadInfo = (processor_cpu_load_info_data_t*) infoArray; WebRtc_Word32 totalCpuUsage = 0; for (unsigned int cpu = 0; cpu < cpuCount; cpu++) { WebRtc_Word64 ticks = 0; for (int state = 0; state < 2; state++) { ticks += cpuLoadInfo[cpu].cpu_ticks[state]; } if(timeDiffMS <= 0) { _cpuUsage[cpu] = 0; }else { _cpuUsage[cpu] = (WebRtc_UWord32)((1000 * (ticks - _lastTickCount[cpu])) / timeDiffMS); } _lastTickCount[cpu] = ticks; totalCpuUsage += _cpuUsage[cpu]; } vm_deallocate(mach_task_self(), (vm_address_t)infoArray, infoCount); numCores = cpuCount; array = _cpuUsage; return totalCpuUsage/cpuCount; } } // namespace webrtc