blob: c2a11e1b6d29c212a50f2951a5850016e22a2798 [file] [log] [blame]
niklase@google.comf0779a22011-05-30 11:39:38 +00001/*
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
19namespace webrtc {
20CpuWrapperMac::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
54CpuWrapperMac::~CpuWrapperMac()
55{
56 delete _cpuUsage;
57 delete _lastTickCount;
58}
59
60WebRtc_Word32 CpuWrapperMac::CpuUsage()
61{
62 WebRtc_UWord32 numCores;
63 WebRtc_UWord32* array = NULL;
64 return CpuUsageMultiCore(numCores, array);
65}
66
67WebRtc_Word32
68CpuWrapperMac::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