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