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