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 {
CpuWrapperMac()20 CpuWrapperMac::CpuWrapperMac()
21 : _cpuCount(0),
22 _cpuUsage(NULL),
23 _totalCpuUsage(0),
24 _lastTickCount(NULL),
25 _lastTime(0)
26 {
27 natural_t cpuCount;
28 processor_info_array_t infoArray;
29 mach_msg_type_number_t infoCount;
30
31 kern_return_t error = host_processor_info(mach_host_self(),
32 PROCESSOR_CPU_LOAD_INFO,
33 &cpuCount,
34 &infoArray,
35 &infoCount);
36 if (error)
37 {
38 return;
39 }
40
41 _cpuCount = cpuCount;
42 _cpuUsage = new WebRtc_UWord32[cpuCount];
43 _lastTickCount = new WebRtc_Word64[cpuCount];
44 _lastTime = TickTime::MillisecondTimestamp();
45
46 processor_cpu_load_info_data_t* cpuLoadInfo =
47 (processor_cpu_load_info_data_t*) infoArray;
48 for (unsigned int cpu= 0; cpu < cpuCount; cpu++)
49 {
50 WebRtc_Word64 ticks = 0;
51 for (int state = 0; state < 2; state++)
52 {
53 ticks += cpuLoadInfo[cpu].cpu_ticks[state];
54 }
55 _lastTickCount[cpu] = ticks;
56 _cpuUsage[cpu] = 0;
57 }
58 vm_deallocate(mach_task_self(), (vm_address_t)infoArray, infoCount);
59 }
60
~CpuWrapperMac()61 CpuWrapperMac::~CpuWrapperMac()
62 {
63 delete[] _cpuUsage;
64 delete[] _lastTickCount;
65 }
66
CpuUsage()67 WebRtc_Word32 CpuWrapperMac::CpuUsage()
68 {
69 WebRtc_UWord32 numCores;
70 WebRtc_UWord32* array = NULL;
71 return CpuUsageMultiCore(numCores, array);
72 }
73
74 WebRtc_Word32
CpuUsageMultiCore(WebRtc_UWord32 & numCores,WebRtc_UWord32 * & array)75 CpuWrapperMac::CpuUsageMultiCore(WebRtc_UWord32& numCores,
76 WebRtc_UWord32*& array)
77 {
78 // sanity check
79 if(_cpuUsage == NULL)
80 {
81 return -1;
82 }
83
84 WebRtc_Word64 now = TickTime::MillisecondTimestamp();
85 WebRtc_Word64 timeDiffMS = now - _lastTime;
86 if(timeDiffMS >= 500)
87 {
88 if(Update(timeDiffMS) != 0)
89 {
90 return -1;
91 }
92 _lastTime = now;
93 }
94
95 numCores = _cpuCount;
96 array = _cpuUsage;
97 return _totalCpuUsage / _cpuCount;
98 }
99
Update(WebRtc_Word64 timeDiffMS)100 WebRtc_Word32 CpuWrapperMac::Update(WebRtc_Word64 timeDiffMS)
101 {
102 natural_t cpuCount;
103 processor_info_array_t infoArray;
104 mach_msg_type_number_t infoCount;
105
106 kern_return_t error = host_processor_info(mach_host_self(),
107 PROCESSOR_CPU_LOAD_INFO,
108 &cpuCount,
109 &infoArray,
110 &infoCount);
111 if (error)
112 {
113 return -1;
114 }
115
116 processor_cpu_load_info_data_t* cpuLoadInfo =
117 (processor_cpu_load_info_data_t*) infoArray;
118
119 _totalCpuUsage = 0;
120 for (unsigned int cpu = 0; cpu < cpuCount; cpu++)
121 {
122 WebRtc_Word64 ticks = 0;
123 for (int state = 0; state < 2; state++)
124 {
125 ticks += cpuLoadInfo[cpu].cpu_ticks[state];
126 }
127 if(timeDiffMS <= 0)
128 {
129 _cpuUsage[cpu] = 0;
130 }else {
131 _cpuUsage[cpu] = (WebRtc_UWord32)((1000 *
132 (ticks - _lastTickCount[cpu])) /
133 timeDiffMS);
134 }
135 _lastTickCount[cpu] = ticks;
136 _totalCpuUsage += _cpuUsage[cpu];
137 }
138
139 vm_deallocate(mach_task_self(), (vm_address_t)infoArray, infoCount);
140
141 return 0;
142 }
143 } // namespace webrtc
144