Home | History | Annotate | Download | only in source
      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 {
     20 CpuWrapperMac::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 
     54 CpuWrapperMac::~CpuWrapperMac()
     55 {
     56     delete _cpuUsage;
     57     delete _lastTickCount;
     58 }
     59 
     60 WebRtc_Word32 CpuWrapperMac::CpuUsage()
     61 {
     62     WebRtc_UWord32 numCores;
     63     WebRtc_UWord32* array = NULL;
     64     return CpuUsageMultiCore(numCores, array);
     65 }
     66 
     67 WebRtc_Word32
     68 CpuWrapperMac::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
    133