1 /* 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "cpu_mac.h" 12 13 #include <iostream> 14 #include <mach/mach.h> 15 #include <mach/mach_error.h> 16 17 #include "tick_util.h" 18 19 namespace webrtc { 20 CpuWrapperMac::CpuWrapperMac() : _cpuUsage(NULL) 21 { 22 natural_t cpuCount; 23 processor_info_array_t infoArray; 24 mach_msg_type_number_t infoCount; 25 26 kern_return_t error = host_processor_info(mach_host_self(), 27 PROCESSOR_CPU_LOAD_INFO, 28 &cpuCount, 29 &infoArray, 30 &infoCount); 31 if (error) 32 { 33 return; 34 } 35 36 _cpuUsage = new WebRtc_UWord32[cpuCount]; 37 _lastTickCount = new WebRtc_Word64[cpuCount]; 38 _lastTime = TickTime::MillisecondTimestamp(); 39 40 processor_cpu_load_info_data_t* cpuLoadInfo = 41 (processor_cpu_load_info_data_t*) infoArray; 42 for (unsigned int cpu= 0; cpu < cpuCount; cpu++) 43 { 44 WebRtc_Word64 ticks = 0; 45 for (int state = 0; state < 2; state++) 46 { 47 ticks += cpuLoadInfo[cpu].cpu_ticks[state]; 48 } 49 _lastTickCount[cpu] = ticks; 50 } 51 vm_deallocate(mach_task_self(), (vm_address_t)infoArray, infoCount); 52 } 53 54 CpuWrapperMac::~CpuWrapperMac() 55 { 56 delete _cpuUsage; 57 delete _lastTickCount; 58 } 59 60 WebRtc_Word32 CpuWrapperMac::CpuUsage() 61 { 62 WebRtc_UWord32 numCores; 63 WebRtc_UWord32* array = NULL; 64 return CpuUsageMultiCore(numCores, array); 65 } 66 67 WebRtc_Word32 68 CpuWrapperMac::CpuUsageMultiCore(WebRtc_UWord32& numCores, 69 WebRtc_UWord32*& array) 70 { 71 natural_t cpuCount; 72 processor_info_array_t infoArray; 73 mach_msg_type_number_t infoCount; 74 75 // sanity check 76 if(_cpuUsage == NULL) 77 { 78 return -1; 79 } 80 WebRtc_Word64 now = TickTime::MillisecondTimestamp(); 81 WebRtc_Word64 timeDiffMS = now - _lastTime; 82 // TODO(hellner) why block here? Why not just return the old 83 // value? Is this behavior consistent across all 84 // platforms? 85 // Make sure that at least 500 ms pass between calls. 86 if(timeDiffMS < 500) 87 { 88 usleep((500-timeDiffMS)*1000); 89 return CpuUsageMultiCore(numCores, array); 90 } 91 _lastTime = now; 92 93 kern_return_t error = host_processor_info(mach_host_self(), 94 PROCESSOR_CPU_LOAD_INFO, 95 &cpuCount, 96 &infoArray, 97 &infoCount); 98 if (error) 99 { 100 return -1; 101 } 102 103 processor_cpu_load_info_data_t* cpuLoadInfo = 104 (processor_cpu_load_info_data_t*) infoArray; 105 106 WebRtc_Word32 totalCpuUsage = 0; 107 for (unsigned int cpu = 0; cpu < cpuCount; cpu++) 108 { 109 WebRtc_Word64 ticks = 0; 110 for (int state = 0; state < 2; state++) 111 { 112 ticks += cpuLoadInfo[cpu].cpu_ticks[state]; 113 } 114 if(timeDiffMS <= 0) 115 { 116 _cpuUsage[cpu] = 0; 117 }else { 118 _cpuUsage[cpu] = (WebRtc_UWord32)((1000 * 119 (ticks - _lastTickCount[cpu])) / 120 timeDiffMS); 121 } 122 _lastTickCount[cpu] = ticks; 123 totalCpuUsage += _cpuUsage[cpu]; 124 } 125 126 vm_deallocate(mach_task_self(), (vm_address_t)infoArray, infoCount); 127 128 numCores = cpuCount; 129 array = _cpuUsage; 130 return totalCpuUsage/cpuCount; 131 } 132 } // namespace webrtc 133