aboutsummaryrefslogtreecommitdiff
path: root/src/system_wrappers/source/cpu_mac.cc
blob: c2a11e1b6d29c212a50f2951a5850016e22a2798 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "cpu_mac.h"

#include <iostream>
#include <mach/mach.h>
#include <mach/mach_error.h>

#include "tick_util.h"

namespace webrtc {
CpuWrapperMac::CpuWrapperMac() : _cpuUsage(NULL)
{
    natural_t cpuCount;
    processor_info_array_t infoArray;
    mach_msg_type_number_t infoCount;

    kern_return_t error = host_processor_info(mach_host_self(),
                                              PROCESSOR_CPU_LOAD_INFO,
                                              &cpuCount,
                                              &infoArray,
                                              &infoCount);
    if (error)
    {
        return;
    }

    _cpuUsage = new WebRtc_UWord32[cpuCount];
    _lastTickCount = new WebRtc_Word64[cpuCount];
    _lastTime = TickTime::MillisecondTimestamp();

    processor_cpu_load_info_data_t* cpuLoadInfo =
        (processor_cpu_load_info_data_t*) infoArray;
    for (unsigned int cpu= 0; cpu < cpuCount; cpu++)
    {
        WebRtc_Word64 ticks = 0;
        for (int state = 0; state < 2; state++)
        {
            ticks += cpuLoadInfo[cpu].cpu_ticks[state];
        }
        _lastTickCount[cpu] = ticks;
    }
    vm_deallocate(mach_task_self(), (vm_address_t)infoArray, infoCount);
}

CpuWrapperMac::~CpuWrapperMac()
{
    delete _cpuUsage;
    delete _lastTickCount;
}

WebRtc_Word32 CpuWrapperMac::CpuUsage()
{
    WebRtc_UWord32 numCores;
    WebRtc_UWord32* array = NULL;
    return CpuUsageMultiCore(numCores, array);
}

WebRtc_Word32
CpuWrapperMac::CpuUsageMultiCore(WebRtc_UWord32& numCores,
                                 WebRtc_UWord32*& array)
{
    natural_t cpuCount;
    processor_info_array_t infoArray;
    mach_msg_type_number_t infoCount;

    // sanity check
    if(_cpuUsage == NULL)
    {
        return -1;
    }
    WebRtc_Word64 now = TickTime::MillisecondTimestamp();
    WebRtc_Word64 timeDiffMS = now - _lastTime;
    // TODO(hellner) why block here? Why not just return the old
    //                          value? Is this behavior consistent across all
    //                          platforms?
    // Make sure that at least 500 ms pass between calls.
    if(timeDiffMS < 500)
    {
        usleep((500-timeDiffMS)*1000);
        return CpuUsageMultiCore(numCores, array);
    }
    _lastTime = now;

     kern_return_t error = host_processor_info(mach_host_self(),
                                              PROCESSOR_CPU_LOAD_INFO,
                                              &cpuCount,
                                              &infoArray,
                                              &infoCount);
    if (error)
    {
        return -1;
    }

    processor_cpu_load_info_data_t* cpuLoadInfo =
        (processor_cpu_load_info_data_t*) infoArray;

    WebRtc_Word32 totalCpuUsage = 0;
    for (unsigned int cpu = 0; cpu < cpuCount; cpu++)
    {
        WebRtc_Word64 ticks = 0;
        for (int state = 0; state < 2; state++)
        {
            ticks += cpuLoadInfo[cpu].cpu_ticks[state];
        }
        if(timeDiffMS <= 0)
        {
            _cpuUsage[cpu] = 0;
        }else {
            _cpuUsage[cpu] = (WebRtc_UWord32)((1000 *
                                              (ticks - _lastTickCount[cpu])) /
                                              timeDiffMS);
        }
        _lastTickCount[cpu] = ticks;
        totalCpuUsage += _cpuUsage[cpu];
    }

    vm_deallocate(mach_task_self(), (vm_address_t)infoArray, infoCount);

    numCores = cpuCount;
    array = _cpuUsage;
    return totalCpuUsage/cpuCount;
}
} // namespace webrtc