Revert 3736 "Removed CPU APIs from VoEHardware. Code is now only..."
> Removed CPU APIs from VoEHardware. Code is now only used by test applications. > > BUG=8404677 > > Review URL: https://webrtc-codereview.appspot.com/1238004 TBR=henrike@webrtc.org Review URL: https://webrtc-codereview.appspot.com/1267004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3737 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
4c138e8fca
commit
80fccc29de
55
webrtc/system_wrappers/interface/cpu_wrapper.h
Normal file
55
webrtc/system_wrappers/interface/cpu_wrapper.h
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CPU_WRAPPER_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CPU_WRAPPER_H_
|
||||
|
||||
#include "typedefs.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CpuWrapper {
|
||||
public:
|
||||
static CpuWrapper* CreateCpu();
|
||||
virtual ~CpuWrapper() {}
|
||||
|
||||
// Returns the average CPU usage for all processors. The CPU usage can be
|
||||
// between and including 0 to 100 (%)
|
||||
virtual WebRtc_Word32 CpuUsage() = 0;
|
||||
virtual WebRtc_Word32 CpuUsage(WebRtc_Word8* process_name,
|
||||
WebRtc_UWord32 length) = 0;
|
||||
virtual WebRtc_Word32 CpuUsage(WebRtc_UWord32 process_id) = 0;
|
||||
|
||||
// The CPU usage per core is returned in cpu_usage. The CPU can be between
|
||||
// and including 0 to 100 (%)
|
||||
// Note that the pointer passed as cpu_usage is redirected to a local member
|
||||
// of the CPU wrapper.
|
||||
// num_cores is the number of cores in the cpu_usage array.
|
||||
// The return value is -1 for failure or 0-100, indicating the average
|
||||
// CPU usage across all cores.
|
||||
// Note: on some OSs this class is initialized lazy. This means that it
|
||||
// might not yet be possible to retrieve any CPU metrics. When this happens
|
||||
// the return value will be zero (indicating that there is not a failure),
|
||||
// num_cores will be 0 and cpu_usage will be set to NULL (indicating that
|
||||
// no metrics are available yet). Once the initialization is completed,
|
||||
// which can take in the order of seconds, CPU metrics can be retrieved.
|
||||
virtual WebRtc_Word32 CpuUsageMultiCore(WebRtc_UWord32& num_cores,
|
||||
WebRtc_UWord32*& cpu_usage) = 0;
|
||||
|
||||
virtual void Reset() = 0;
|
||||
virtual void Stop() = 0;
|
||||
|
||||
protected:
|
||||
CpuWrapper() {}
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_CPU_WRAPPER_H_
|
@ -24,6 +24,7 @@ LOCAL_SRC_FILES := \
|
||||
aligned_malloc.cc \
|
||||
atomic32_posix.cc \
|
||||
condition_variable.cc \
|
||||
cpu_no_op.cc \
|
||||
cpu_features.cc \
|
||||
cpu_info.cc \
|
||||
critical_section.cc \
|
||||
|
36
webrtc/system_wrappers/source/cpu.cc
Normal file
36
webrtc/system_wrappers/source/cpu.cc
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 "system_wrappers/interface/cpu_wrapper.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include "cpu_win.h"
|
||||
#elif defined(WEBRTC_MAC)
|
||||
#include "cpu_mac.h"
|
||||
#elif defined(WEBRTC_ANDROID)
|
||||
// Not implemented yet, might be possible to use Linux implementation
|
||||
#else // defined(WEBRTC_LINUX)
|
||||
#include "cpu_linux.h"
|
||||
#endif
|
||||
|
||||
namespace webrtc {
|
||||
CpuWrapper* CpuWrapper::CreateCpu() {
|
||||
#if defined(_WIN32)
|
||||
return new CpuWindows();
|
||||
#elif defined(WEBRTC_MAC)
|
||||
return new CpuWrapperMac();
|
||||
#elif defined(WEBRTC_ANDROID)
|
||||
return 0;
|
||||
#else
|
||||
return new CpuLinux();
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
@ -8,7 +8,7 @@
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "webrtc/system_wrappers/interface/cpu_info.h"
|
||||
#include "system_wrappers/interface/cpu_info.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
#include <Windows.h>
|
||||
@ -22,7 +22,7 @@
|
||||
#include <sys/sysinfo.h>
|
||||
#endif
|
||||
|
||||
#include "system_wrappers/interface/trace.h"
|
||||
#include "trace.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
|
184
webrtc/system_wrappers/source/cpu_linux.cc
Normal file
184
webrtc/system_wrappers/source/cpu_linux.cc
Normal file
@ -0,0 +1,184 @@
|
||||
/*
|
||||
* 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 "system_wrappers/source/cpu_linux.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
CpuLinux::CpuLinux()
|
||||
: old_busy_time_(0),
|
||||
old_idle_time_(0),
|
||||
old_busy_time_multi_(NULL),
|
||||
old_idle_time_multi_(NULL),
|
||||
idle_array_(NULL),
|
||||
busy_array_(NULL),
|
||||
result_array_(NULL),
|
||||
num_cores_(0) {
|
||||
const int result = GetNumCores();
|
||||
if (result != -1) {
|
||||
num_cores_ = result;
|
||||
old_busy_time_multi_ = new long long[num_cores_];
|
||||
memset(old_busy_time_multi_, 0, sizeof(long long) * num_cores_);
|
||||
old_idle_time_multi_ = new long long[num_cores_];
|
||||
memset(old_idle_time_multi_, 0, sizeof(long long) * num_cores_);
|
||||
idle_array_ = new long long[num_cores_];
|
||||
memset(idle_array_, 0, sizeof(long long) * num_cores_);
|
||||
busy_array_ = new long long[num_cores_];
|
||||
memset(busy_array_, 0, sizeof(long long) * num_cores_);
|
||||
result_array_ = new WebRtc_UWord32[num_cores_];
|
||||
|
||||
GetData(old_busy_time_, old_idle_time_, busy_array_, idle_array_);
|
||||
}
|
||||
}
|
||||
|
||||
CpuLinux::~CpuLinux() {
|
||||
delete [] old_busy_time_multi_;
|
||||
delete [] old_idle_time_multi_;
|
||||
delete [] idle_array_;
|
||||
delete [] busy_array_;
|
||||
delete [] result_array_;
|
||||
}
|
||||
|
||||
WebRtc_Word32 CpuLinux::CpuUsage() {
|
||||
WebRtc_UWord32 dummy = 0;
|
||||
WebRtc_UWord32* dummy_array = NULL;
|
||||
return CpuUsageMultiCore(dummy, dummy_array);
|
||||
}
|
||||
|
||||
WebRtc_Word32 CpuLinux::CpuUsageMultiCore(WebRtc_UWord32& num_cores,
|
||||
WebRtc_UWord32*& core_array) {
|
||||
core_array = result_array_;
|
||||
num_cores = num_cores_;
|
||||
long long busy = 0;
|
||||
long long idle = 0;
|
||||
if (GetData(busy, idle, busy_array_, idle_array_) != 0)
|
||||
return -1;
|
||||
|
||||
long long delta_busy = busy - old_busy_time_;
|
||||
long long delta_idle = idle - old_idle_time_;
|
||||
old_busy_time_ = busy;
|
||||
old_idle_time_ = idle;
|
||||
|
||||
int ret_val = -1;
|
||||
if (delta_busy + delta_idle == 0) {
|
||||
ret_val = 0;
|
||||
} else {
|
||||
ret_val = (int)(100 * (delta_busy) / (delta_busy + delta_idle));
|
||||
}
|
||||
|
||||
if (core_array == NULL) {
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
for (WebRtc_UWord32 i = 0; i < num_cores_; ++i) {
|
||||
delta_busy = busy_array_[i] - old_busy_time_multi_[i];
|
||||
delta_idle = idle_array_[i] - old_idle_time_multi_[i];
|
||||
old_busy_time_multi_[i] = busy_array_[i];
|
||||
old_idle_time_multi_[i] = idle_array_[i];
|
||||
if (delta_busy + delta_idle == 0) {
|
||||
core_array[i] = 0;
|
||||
} else {
|
||||
core_array[i] = (int)(100 * (delta_busy) / (delta_busy + delta_idle));
|
||||
}
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
int CpuLinux::GetData(long long& busy, long long& idle, long long*& busy_array,
|
||||
long long*& idle_array) {
|
||||
FILE* fp = fopen("/proc/stat", "r");
|
||||
if (!fp) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char line[100];
|
||||
if (fgets(line, 100, fp) == NULL) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
char first_word[100];
|
||||
if (sscanf(line, "%s ", first_word) != 1) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
if (strncmp(first_word, "cpu", 3) != 0) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
char s_user[100];
|
||||
char s_nice[100];
|
||||
char s_system[100];
|
||||
char s_idle[100];
|
||||
if (sscanf(line, "%s %s %s %s %s ",
|
||||
first_word, s_user, s_nice, s_system, s_idle) != 5) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
long long luser = atoll(s_user);
|
||||
long long lnice = atoll(s_nice);
|
||||
long long lsystem = atoll(s_system);
|
||||
long long lidle = atoll(s_idle);
|
||||
|
||||
busy = luser + lnice + lsystem;
|
||||
idle = lidle;
|
||||
for (WebRtc_UWord32 i = 0; i < num_cores_; ++i) {
|
||||
if (fgets(line, 100, fp) == NULL) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
if (sscanf(line, "%s %s %s %s %s ", first_word, s_user, s_nice, s_system,
|
||||
s_idle) != 5) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
luser = atoll(s_user);
|
||||
lnice = atoll(s_nice);
|
||||
lsystem = atoll(s_system);
|
||||
lidle = atoll(s_idle);
|
||||
busy_array[i] = luser + lnice + lsystem;
|
||||
idle_array[i] = lidle;
|
||||
}
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CpuLinux::GetNumCores() {
|
||||
FILE* fp = fopen("/proc/stat", "r");
|
||||
if (!fp) {
|
||||
return -1;
|
||||
}
|
||||
// Skip first line
|
||||
char line[100];
|
||||
if (!fgets(line, 100, fp)) {
|
||||
fclose(fp);
|
||||
return -1;
|
||||
}
|
||||
int num_cores = -1;
|
||||
char first_word[100];
|
||||
do {
|
||||
num_cores++;
|
||||
if (fgets(line, 100, fp)) {
|
||||
if (sscanf(line, "%s ", first_word) != 1) {
|
||||
first_word[0] = '\0';
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (strncmp(first_word, "cpu", 3) == 0);
|
||||
fclose(fp);
|
||||
return num_cores;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
60
webrtc/system_wrappers/source/cpu_linux.h
Normal file
60
webrtc/system_wrappers/source/cpu_linux.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CPU_LINUX_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CPU_LINUX_H_
|
||||
|
||||
#include "system_wrappers/interface/cpu_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CpuLinux : public CpuWrapper {
|
||||
public:
|
||||
CpuLinux();
|
||||
virtual ~CpuLinux();
|
||||
|
||||
virtual WebRtc_Word32 CpuUsage();
|
||||
virtual WebRtc_Word32 CpuUsage(WebRtc_Word8* process_name,
|
||||
WebRtc_UWord32 length) {
|
||||
return 0;
|
||||
}
|
||||
virtual WebRtc_Word32 CpuUsage(WebRtc_UWord32 process_id) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual WebRtc_Word32 CpuUsageMultiCore(WebRtc_UWord32& num_cores,
|
||||
WebRtc_UWord32*& array);
|
||||
|
||||
virtual void Reset() {
|
||||
return;
|
||||
}
|
||||
virtual void Stop() {
|
||||
return;
|
||||
}
|
||||
private:
|
||||
int GetData(long long& busy, long long& idle, long long*& busy_array,
|
||||
long long*& idle_array);
|
||||
int GetNumCores();
|
||||
|
||||
long long old_busy_time_;
|
||||
long long old_idle_time_;
|
||||
|
||||
long long* old_busy_time_multi_;
|
||||
long long* old_idle_time_multi_;
|
||||
|
||||
long long* idle_array_;
|
||||
long long* busy_array_;
|
||||
WebRtc_UWord32* result_array_;
|
||||
WebRtc_UWord32 num_cores_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CPU_LINUX_H_
|
130
webrtc/system_wrappers/source/cpu_mac.cc
Normal file
130
webrtc/system_wrappers/source/cpu_mac.cc
Normal file
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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 "system_wrappers/source/cpu_mac.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_error.h>
|
||||
|
||||
#include "tick_util.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
CpuWrapperMac::CpuWrapperMac()
|
||||
: cpu_count_(0),
|
||||
cpu_usage_(NULL),
|
||||
total_cpu_usage_(0),
|
||||
last_tick_count_(NULL),
|
||||
last_time_(0) {
|
||||
natural_t cpu_count;
|
||||
processor_info_array_t info_array;
|
||||
mach_msg_type_number_t info_count;
|
||||
|
||||
kern_return_t error = host_processor_info(mach_host_self(),
|
||||
PROCESSOR_CPU_LOAD_INFO,
|
||||
&cpu_count,
|
||||
&info_array,
|
||||
&info_count);
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
cpu_count_ = cpu_count;
|
||||
cpu_usage_ = new WebRtc_UWord32[cpu_count];
|
||||
last_tick_count_ = new WebRtc_Word64[cpu_count];
|
||||
last_time_ = TickTime::MillisecondTimestamp();
|
||||
|
||||
processor_cpu_load_info_data_t* cpu_load_info =
|
||||
(processor_cpu_load_info_data_t*) info_array;
|
||||
for (unsigned int cpu = 0; cpu < cpu_count; ++cpu) {
|
||||
WebRtc_Word64 ticks = 0;
|
||||
for (int state = 0; state < 2; ++state) {
|
||||
ticks += cpu_load_info[cpu].cpu_ticks[state];
|
||||
}
|
||||
last_tick_count_[cpu] = ticks;
|
||||
cpu_usage_[cpu] = 0;
|
||||
}
|
||||
vm_deallocate(mach_task_self(), (vm_address_t)info_array, info_count);
|
||||
}
|
||||
|
||||
CpuWrapperMac::~CpuWrapperMac() {
|
||||
delete[] cpu_usage_;
|
||||
delete[] last_tick_count_;
|
||||
}
|
||||
|
||||
WebRtc_Word32 CpuWrapperMac::CpuUsage() {
|
||||
WebRtc_UWord32 num_cores;
|
||||
WebRtc_UWord32* array = NULL;
|
||||
return CpuUsageMultiCore(num_cores, array);
|
||||
}
|
||||
|
||||
WebRtc_Word32
|
||||
CpuWrapperMac::CpuUsageMultiCore(WebRtc_UWord32& num_cores,
|
||||
WebRtc_UWord32*& array) {
|
||||
// sanity check
|
||||
if (cpu_usage_ == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
WebRtc_Word64 now = TickTime::MillisecondTimestamp();
|
||||
WebRtc_Word64 time_diff_ms = now - last_time_;
|
||||
if (time_diff_ms >= 500) {
|
||||
if (Update(time_diff_ms) != 0) {
|
||||
return -1;
|
||||
}
|
||||
last_time_ = now;
|
||||
}
|
||||
|
||||
num_cores = cpu_count_;
|
||||
array = cpu_usage_;
|
||||
return total_cpu_usage_ / cpu_count_;
|
||||
}
|
||||
|
||||
WebRtc_Word32 CpuWrapperMac::Update(WebRtc_Word64 time_diff_ms) {
|
||||
natural_t cpu_count;
|
||||
processor_info_array_t info_array;
|
||||
mach_msg_type_number_t info_count;
|
||||
|
||||
kern_return_t error = host_processor_info(mach_host_self(),
|
||||
PROCESSOR_CPU_LOAD_INFO,
|
||||
&cpu_count,
|
||||
&info_array,
|
||||
&info_count);
|
||||
if (error) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
processor_cpu_load_info_data_t* cpu_load_info =
|
||||
(processor_cpu_load_info_data_t*) info_array;
|
||||
|
||||
total_cpu_usage_ = 0;
|
||||
for (unsigned int cpu = 0; cpu < cpu_count; ++cpu) {
|
||||
WebRtc_Word64 ticks = 0;
|
||||
for (int state = 0; state < 2; ++state) {
|
||||
ticks += cpu_load_info[cpu].cpu_ticks[state];
|
||||
}
|
||||
if (time_diff_ms <= 0) {
|
||||
cpu_usage_[cpu] = 0;
|
||||
} else {
|
||||
cpu_usage_[cpu] = (WebRtc_UWord32)((1000 *
|
||||
(ticks - last_tick_count_[cpu])) /
|
||||
time_diff_ms);
|
||||
}
|
||||
last_tick_count_[cpu] = ticks;
|
||||
total_cpu_usage_ += cpu_usage_[cpu];
|
||||
}
|
||||
|
||||
vm_deallocate(mach_task_self(), (vm_address_t)info_array, info_count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
53
webrtc/system_wrappers/source/cpu_mac.h
Normal file
53
webrtc/system_wrappers/source/cpu_mac.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CPU_MAC_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CPU_MAC_H_
|
||||
|
||||
#include "system_wrappers/interface/cpu_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CpuWrapperMac : public CpuWrapper {
|
||||
public:
|
||||
CpuWrapperMac();
|
||||
virtual ~CpuWrapperMac();
|
||||
|
||||
virtual WebRtc_Word32 CpuUsage();
|
||||
virtual WebRtc_Word32 CpuUsage(WebRtc_Word8* process_name,
|
||||
WebRtc_UWord32 length) {
|
||||
return -1;
|
||||
}
|
||||
virtual WebRtc_Word32 CpuUsage(WebRtc_UWord32 process_id) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Note: this class will block the call and sleep if called too fast
|
||||
// This function blocks the calling thread if the thread is calling it more
|
||||
// often than every 500 ms.
|
||||
virtual WebRtc_Word32 CpuUsageMultiCore(WebRtc_UWord32& num_cores,
|
||||
WebRtc_UWord32*& array);
|
||||
|
||||
virtual void Reset() {}
|
||||
virtual void Stop() {}
|
||||
|
||||
private:
|
||||
WebRtc_Word32 Update(WebRtc_Word64 time_diffMS);
|
||||
|
||||
WebRtc_UWord32 cpu_count_;
|
||||
WebRtc_UWord32* cpu_usage_;
|
||||
WebRtc_Word32 total_cpu_usage_;
|
||||
WebRtc_Word64* last_tick_count_;
|
||||
WebRtc_Word64 last_time_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CPU_MAC_H_
|
127
webrtc/system_wrappers/source/cpu_measurement_harness.cc
Normal file
127
webrtc/system_wrappers/source/cpu_measurement_harness.cc
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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 "system_wrappers/interface/cpu_wrapper.h"
|
||||
#include "system_wrappers/interface/event_wrapper.h"
|
||||
#include "system_wrappers/interface/scoped_ptr.h"
|
||||
#include "system_wrappers/source/cpu_measurement_harness.h"
|
||||
|
||||
const int kCpuCheckPeriodMs = 100;
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
CpuMeasurementHarness* CpuMeasurementHarness::Create(
|
||||
CpuTarget* target,
|
||||
int work_period_ms,
|
||||
int work_iterations_per_period,
|
||||
int duration_ms) {
|
||||
if (target == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (work_period_ms > duration_ms) {
|
||||
return NULL;
|
||||
}
|
||||
if (work_period_ms < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (duration_ms < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (work_iterations_per_period < 1) {
|
||||
return NULL;
|
||||
}
|
||||
return new CpuMeasurementHarness(target, work_period_ms,
|
||||
work_iterations_per_period, duration_ms);
|
||||
}
|
||||
|
||||
CpuMeasurementHarness::CpuMeasurementHarness(CpuTarget* target,
|
||||
int work_period_ms,
|
||||
int work_iterations_per_period,
|
||||
int duration_ms)
|
||||
: cpu_target_(target),
|
||||
work_period_ms_(work_period_ms),
|
||||
work_iterations_per_period_(work_iterations_per_period),
|
||||
duration_ms_(duration_ms),
|
||||
cpu_sum_(0),
|
||||
cpu_iterations_(0),
|
||||
cpu_(CpuWrapper::CreateCpu()),
|
||||
event_(EventWrapper::Create()) {
|
||||
}
|
||||
|
||||
CpuMeasurementHarness::~CpuMeasurementHarness() {
|
||||
}
|
||||
|
||||
bool CpuMeasurementHarness::Run() {
|
||||
if (!WaitForCpuInit()) {
|
||||
return false;
|
||||
}
|
||||
// No need for precision. Run for approximately the asked for duration.
|
||||
// TODO(hellner): very low prio if at all, the actual duration of the test
|
||||
// will be longer if calling DoWork() is not negligable and/or called many
|
||||
// times. It may make sense to compensate for drift here. This will,
|
||||
// however, only add complexity with minimal gains. Perhaps renaming the
|
||||
// duration_ms_ to something more fuzzy is a better idea. However, the name
|
||||
// would be very convoluted if it is to be self documenting.
|
||||
int elapsed_time_ms = 0;
|
||||
int last_measured_time = 0;
|
||||
while (elapsed_time_ms < duration_ms_) {
|
||||
if (((elapsed_time_ms - last_measured_time) / kCpuCheckPeriodMs) >= 1) {
|
||||
last_measured_time = elapsed_time_ms;
|
||||
Measure();
|
||||
}
|
||||
if (!DoWork()) {
|
||||
return false;
|
||||
}
|
||||
event_->Wait(work_period_ms_);
|
||||
elapsed_time_ms += work_period_ms_;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int CpuMeasurementHarness::AverageCpu() {
|
||||
if (cpu_iterations_ == 0) {
|
||||
return 0;
|
||||
}
|
||||
assert(cpu_sum_ >= 0);
|
||||
assert(cpu_iterations_ >= 0);
|
||||
return cpu_sum_ / cpu_iterations_;
|
||||
}
|
||||
|
||||
bool CpuMeasurementHarness::WaitForCpuInit() {
|
||||
bool cpu_usage_available = false;
|
||||
int num_iterations = 0;
|
||||
// Initializing the CPU measurements may take a couple of seconds on Windows.
|
||||
// Since the initialization is lazy we need to wait until it is completed.
|
||||
// Should not take more than 10000 ms.
|
||||
while (!cpu_usage_available && (++num_iterations < 10000)) {
|
||||
event_->Wait(1);
|
||||
cpu_usage_available = cpu_->CpuUsage() != -1;
|
||||
}
|
||||
return cpu_usage_available;
|
||||
}
|
||||
|
||||
void CpuMeasurementHarness::Measure() {
|
||||
WebRtc_UWord32 num_cores = 0;
|
||||
WebRtc_UWord32* cores = NULL;
|
||||
// Return the average CPU for now.
|
||||
cpu_sum_ = cpu_->CpuUsageMultiCore(num_cores, cores);
|
||||
++cpu_iterations_;
|
||||
}
|
||||
|
||||
bool CpuMeasurementHarness::DoWork() {
|
||||
for (int i = 0; i < work_iterations_per_period_; ++i) {
|
||||
if (!cpu_target_->DoWork()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
66
webrtc/system_wrappers/source/cpu_measurement_harness.h
Normal file
66
webrtc/system_wrappers/source/cpu_measurement_harness.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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.
|
||||
*/
|
||||
|
||||
#ifndef SRC_SYSTEM_WRAPPERS_SOURCE_CPU_MEASUREMENT_HARNESS_H_
|
||||
#define SRC_SYSTEM_WRAPPERS_SOURCE_CPU_MEASUREMENT_HARNESS_H_
|
||||
|
||||
#include "system_wrappers/interface/scoped_ptr.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
class CpuWrapper;
|
||||
class EventWrapper;
|
||||
class ThreadWrapper;
|
||||
|
||||
// This abstract class provides an interface that should be passed to
|
||||
// CpuMeasurementHarness. CpuMeasurementHarness will call it with the
|
||||
// frequency requested and measure the CPU usage for all calls.
|
||||
class CpuTarget {
|
||||
public:
|
||||
// Callback function for which the CPU usage should be calculated.
|
||||
virtual bool DoWork() = 0;
|
||||
|
||||
protected:
|
||||
CpuTarget() {}
|
||||
virtual ~CpuTarget() {}
|
||||
};
|
||||
|
||||
class CpuMeasurementHarness {
|
||||
public:
|
||||
static CpuMeasurementHarness* Create(CpuTarget* target,
|
||||
int work_period_ms,
|
||||
int work_iterations_per_period,
|
||||
int duration_ms);
|
||||
~CpuMeasurementHarness();
|
||||
bool Run();
|
||||
int AverageCpu();
|
||||
|
||||
protected:
|
||||
CpuMeasurementHarness(CpuTarget* target, int work_period_ms,
|
||||
int work_iterations_per_period, int duration_ms);
|
||||
|
||||
private:
|
||||
bool WaitForCpuInit();
|
||||
void Measure();
|
||||
bool DoWork();
|
||||
|
||||
CpuTarget* cpu_target_;
|
||||
const int work_period_ms_;
|
||||
const int work_iterations_per_period_;
|
||||
const int duration_ms_;
|
||||
int cpu_sum_;
|
||||
int cpu_iterations_;
|
||||
scoped_ptr<CpuWrapper> cpu_;
|
||||
scoped_ptr<EventWrapper> event_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // SRC_SYSTEM_WRAPPERS_SOURCE_CPU_MEASUREMENT_HARNESS_H_
|
21
webrtc/system_wrappers/source/cpu_no_op.cc
Normal file
21
webrtc/system_wrappers/source/cpu_no_op.cc
Normal file
@ -0,0 +1,21 @@
|
||||
/*
|
||||
* 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 "system_wrappers/interface/cpu_wrapper.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
CpuWrapper* CpuWrapper::CreateCpu() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
526
webrtc/system_wrappers/source/cpu_win.cc
Normal file
526
webrtc/system_wrappers/source/cpu_win.cc
Normal file
@ -0,0 +1,526 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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_win.h"
|
||||
|
||||
#define _WIN32_DCOM
|
||||
|
||||
#include <assert.h>
|
||||
#include <iostream>
|
||||
#include <Wbemidl.h>
|
||||
|
||||
#pragma comment(lib, "wbemuuid.lib")
|
||||
|
||||
#include "condition_variable_wrapper.h"
|
||||
#include "critical_section_wrapper.h"
|
||||
#include "event_wrapper.h"
|
||||
#include "thread_wrapper.h"
|
||||
|
||||
namespace webrtc {
|
||||
WebRtc_Word32 CpuWindows::CpuUsage()
|
||||
{
|
||||
if (!has_initialized_)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
// Last element is the average
|
||||
return cpu_usage_[number_of_objects_ - 1];
|
||||
}
|
||||
|
||||
WebRtc_Word32 CpuWindows::CpuUsageMultiCore(WebRtc_UWord32& num_cores,
|
||||
WebRtc_UWord32*& cpu_usage)
|
||||
{
|
||||
if (has_terminated_) {
|
||||
num_cores = 0;
|
||||
cpu_usage = NULL;
|
||||
return -1;
|
||||
}
|
||||
if (!has_initialized_)
|
||||
{
|
||||
num_cores = 0;
|
||||
cpu_usage = NULL;
|
||||
return -1;
|
||||
}
|
||||
num_cores = number_of_objects_ - 1;
|
||||
cpu_usage = cpu_usage_;
|
||||
return cpu_usage_[number_of_objects_-1];
|
||||
}
|
||||
|
||||
CpuWindows::CpuWindows()
|
||||
: cpu_polling_thread(NULL),
|
||||
initialize_(true),
|
||||
has_initialized_(false),
|
||||
terminate_(false),
|
||||
has_terminated_(false),
|
||||
cpu_usage_(NULL),
|
||||
wbem_enum_access_(NULL),
|
||||
number_of_objects_(0),
|
||||
cpu_usage_handle_(0),
|
||||
previous_processor_timestamp_(NULL),
|
||||
timestamp_sys_100_ns_handle_(0),
|
||||
previous_100ns_timestamp_(NULL),
|
||||
wbem_service_(NULL),
|
||||
wbem_service_proxy_(NULL),
|
||||
wbem_refresher_(NULL),
|
||||
wbem_enum_(NULL)
|
||||
{
|
||||
// All resources are allocated in PollingCpu().
|
||||
if (AllocateComplexDataTypes())
|
||||
{
|
||||
StartPollingCpu();
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
CpuWindows::~CpuWindows()
|
||||
{
|
||||
// All resources are reclaimed in StopPollingCpu().
|
||||
StopPollingCpu();
|
||||
DeAllocateComplexDataTypes();
|
||||
}
|
||||
|
||||
bool CpuWindows::AllocateComplexDataTypes()
|
||||
{
|
||||
cpu_polling_thread = ThreadWrapper::CreateThread(
|
||||
CpuWindows::Process,
|
||||
reinterpret_cast<void*>(this),
|
||||
kNormalPriority,
|
||||
"CpuWindows");
|
||||
init_crit_ = CriticalSectionWrapper::CreateCriticalSection();
|
||||
init_cond_ = ConditionVariableWrapper::CreateConditionVariable();
|
||||
terminate_crit_ = CriticalSectionWrapper::CreateCriticalSection();
|
||||
terminate_cond_ = ConditionVariableWrapper::CreateConditionVariable();
|
||||
sleep_event = EventWrapper::Create();
|
||||
return (cpu_polling_thread != NULL) && (init_crit_ != NULL) &&
|
||||
(init_cond_ != NULL) && (terminate_crit_ != NULL) &&
|
||||
(terminate_cond_ != NULL) && (sleep_event != NULL);
|
||||
}
|
||||
|
||||
void CpuWindows::DeAllocateComplexDataTypes()
|
||||
{
|
||||
if (sleep_event != NULL)
|
||||
{
|
||||
delete sleep_event;
|
||||
sleep_event = NULL;
|
||||
}
|
||||
if (terminate_cond_ != NULL)
|
||||
{
|
||||
delete terminate_cond_;
|
||||
terminate_cond_ = NULL;
|
||||
}
|
||||
if (terminate_crit_ != NULL)
|
||||
{
|
||||
delete terminate_crit_;
|
||||
terminate_crit_ = NULL;
|
||||
}
|
||||
if (init_cond_ != NULL)
|
||||
{
|
||||
delete init_cond_;
|
||||
init_cond_ = NULL;
|
||||
}
|
||||
if (init_crit_ != NULL)
|
||||
{
|
||||
delete init_crit_;
|
||||
init_crit_ = NULL;
|
||||
}
|
||||
if (cpu_polling_thread != NULL)
|
||||
{
|
||||
delete cpu_polling_thread;
|
||||
cpu_polling_thread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void CpuWindows::StartPollingCpu()
|
||||
{
|
||||
unsigned int dummy_id = 0;
|
||||
if (!cpu_polling_thread->Start(dummy_id))
|
||||
{
|
||||
initialize_ = false;
|
||||
has_terminated_ = true;
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
bool CpuWindows::StopPollingCpu()
|
||||
{
|
||||
{
|
||||
// If StopPollingCpu is called immediately after StartPollingCpu() it is
|
||||
// possible that cpu_polling_thread is in the process of initializing.
|
||||
// Let initialization finish to avoid getting into a bad state.
|
||||
CriticalSectionScoped cs(init_crit_);
|
||||
while(initialize_)
|
||||
{
|
||||
init_cond_->SleepCS(*init_crit_);
|
||||
}
|
||||
}
|
||||
|
||||
CriticalSectionScoped cs(terminate_crit_);
|
||||
terminate_ = true;
|
||||
sleep_event->Set();
|
||||
while (!has_terminated_)
|
||||
{
|
||||
terminate_cond_->SleepCS(*terminate_crit_);
|
||||
}
|
||||
cpu_polling_thread->Stop();
|
||||
delete cpu_polling_thread;
|
||||
cpu_polling_thread = NULL;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CpuWindows::Process(void* thread_object)
|
||||
{
|
||||
return reinterpret_cast<CpuWindows*>(thread_object)->ProcessImpl();
|
||||
}
|
||||
|
||||
bool CpuWindows::ProcessImpl()
|
||||
{
|
||||
{
|
||||
CriticalSectionScoped cs(terminate_crit_);
|
||||
if (terminate_)
|
||||
{
|
||||
Terminate();
|
||||
terminate_cond_->WakeAll();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Initialize on first iteration
|
||||
if (initialize_)
|
||||
{
|
||||
CriticalSectionScoped cs(init_crit_);
|
||||
initialize_ = false;
|
||||
const bool success = Initialize();
|
||||
init_cond_->WakeAll();
|
||||
if (!success || !has_initialized_)
|
||||
{
|
||||
has_initialized_ = false;
|
||||
terminate_ = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Approximately one seconds sleep for each CPU measurement. Precision is
|
||||
// not important. 1 second refresh rate is also used by Performance Monitor
|
||||
// (perfmon).
|
||||
if(kEventTimeout != sleep_event->Wait(1000))
|
||||
{
|
||||
// Terminating. No need to update CPU usage.
|
||||
assert(terminate_);
|
||||
return true;
|
||||
}
|
||||
|
||||
// UpdateCpuUsage() returns false if a single (or more) CPU read(s) failed.
|
||||
// Not a major problem if it happens.
|
||||
UpdateCpuUsage();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CpuWindows::CreateWmiConnection()
|
||||
{
|
||||
IWbemLocator* service_locator = NULL;
|
||||
HRESULT hr = CoCreateInstance(CLSID_WbemLocator, NULL,
|
||||
CLSCTX_INPROC_SERVER, IID_IWbemLocator,
|
||||
reinterpret_cast<void**> (&service_locator));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// To get the WMI service specify the WMI namespace.
|
||||
BSTR wmi_namespace = SysAllocString(L"\\\\.\\root\\cimv2");
|
||||
if (wmi_namespace == NULL)
|
||||
{
|
||||
// This type of failure signifies running out of memory.
|
||||
service_locator->Release();
|
||||
return false;
|
||||
}
|
||||
hr = service_locator->ConnectServer(wmi_namespace, NULL, NULL, NULL, 0L,
|
||||
NULL, NULL, &wbem_service_);
|
||||
SysFreeString(wmi_namespace);
|
||||
service_locator->Release();
|
||||
return !FAILED(hr);
|
||||
}
|
||||
|
||||
// Sets up WMI refresher and enum
|
||||
bool CpuWindows::CreatePerfOsRefresher()
|
||||
{
|
||||
// Create refresher.
|
||||
HRESULT hr = CoCreateInstance(CLSID_WbemRefresher, NULL,
|
||||
CLSCTX_INPROC_SERVER, IID_IWbemRefresher,
|
||||
reinterpret_cast<void**> (&wbem_refresher_));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Create PerfOS_Processor enum.
|
||||
IWbemConfigureRefresher* wbem_refresher_config = NULL;
|
||||
hr = wbem_refresher_->QueryInterface(
|
||||
IID_IWbemConfigureRefresher,
|
||||
reinterpret_cast<void**> (&wbem_refresher_config));
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create a proxy to the IWbemServices so that a local authentication
|
||||
// can be set up (this is needed to be able to successfully call
|
||||
// IWbemConfigureRefresher::AddEnum). Setting authentication with
|
||||
// CoInitializeSecurity is process-wide (which is too intrusive).
|
||||
hr = CoCopyProxy(static_cast<IUnknown*> (wbem_service_),
|
||||
reinterpret_cast<IUnknown**> (&wbem_service_proxy_));
|
||||
if(FAILED(hr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Set local authentication.
|
||||
// RPC_C_AUTHN_WINNT means using NTLM instead of Kerberos which is default.
|
||||
hr = CoSetProxyBlanket(static_cast<IUnknown*> (wbem_service_proxy_),
|
||||
RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL,
|
||||
RPC_C_AUTHN_LEVEL_DEFAULT,
|
||||
RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't care about the particular id for the enum.
|
||||
long enum_id = 0;
|
||||
hr = wbem_refresher_config->AddEnum(wbem_service_proxy_,
|
||||
L"Win32_PerfRawData_PerfOS_Processor",
|
||||
0, NULL, &wbem_enum_, &enum_id);
|
||||
wbem_refresher_config->Release();
|
||||
wbem_refresher_config = NULL;
|
||||
return !FAILED(hr);
|
||||
}
|
||||
|
||||
// Have to pull the first round of data to be able set the handles.
|
||||
bool CpuWindows::CreatePerfOsCpuHandles()
|
||||
{
|
||||
// Update the refresher so that there is data available in wbem_enum_.
|
||||
wbem_refresher_->Refresh(0L);
|
||||
|
||||
// The number of enumerators is the number of processor + 1 (the total).
|
||||
// This is unknown at this point.
|
||||
DWORD number_returned = 0;
|
||||
HRESULT hr = wbem_enum_->GetObjects(0L, number_of_objects_,
|
||||
wbem_enum_access_, &number_returned);
|
||||
// number_returned indicates the number of enumerators that are needed.
|
||||
if (hr == WBEM_E_BUFFER_TOO_SMALL &&
|
||||
number_returned > number_of_objects_)
|
||||
{
|
||||
// Allocate the number IWbemObjectAccess asked for by the
|
||||
// GetObjects(..) function.
|
||||
wbem_enum_access_ = new IWbemObjectAccess*[number_returned];
|
||||
cpu_usage_ = new WebRtc_UWord32[number_returned];
|
||||
previous_processor_timestamp_ = new unsigned __int64[number_returned];
|
||||
previous_100ns_timestamp_ = new unsigned __int64[number_returned];
|
||||
if ((wbem_enum_access_ == NULL) || (cpu_usage_ == NULL) ||
|
||||
(previous_processor_timestamp_ == NULL) ||
|
||||
(previous_100ns_timestamp_ == NULL))
|
||||
{
|
||||
// Out of memory.
|
||||
return false;
|
||||
}
|
||||
|
||||
SecureZeroMemory(wbem_enum_access_, number_returned *
|
||||
sizeof(IWbemObjectAccess*));
|
||||
memset(cpu_usage_, 0, sizeof(int) * number_returned);
|
||||
memset(previous_processor_timestamp_, 0, sizeof(unsigned __int64) *
|
||||
number_returned);
|
||||
memset(previous_100ns_timestamp_, 0, sizeof(unsigned __int64) *
|
||||
number_returned);
|
||||
|
||||
number_of_objects_ = number_returned;
|
||||
// Read should be successfull now that memory has been allocated.
|
||||
hr = wbem_enum_->GetObjects(0L, number_of_objects_, wbem_enum_access_,
|
||||
&number_returned);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 0 enumerators should not be enough. Something has gone wrong here.
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the enumerator handles that are needed for calculating CPU usage.
|
||||
CIMTYPE cpu_usage_type;
|
||||
hr = wbem_enum_access_[0]->GetPropertyHandle(L"PercentProcessorTime",
|
||||
&cpu_usage_type,
|
||||
&cpu_usage_handle_);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
CIMTYPE timestamp_sys_100_ns_type;
|
||||
hr = wbem_enum_access_[0]->GetPropertyHandle(L"TimeStamp_Sys100NS",
|
||||
×tamp_sys_100_ns_type,
|
||||
×tamp_sys_100_ns_handle_);
|
||||
return !FAILED(hr);
|
||||
}
|
||||
|
||||
bool CpuWindows::Initialize()
|
||||
{
|
||||
if (terminate_)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Initialize COM library.
|
||||
HRESULT hr = CoInitializeEx(NULL,COINIT_MULTITHREADED);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CreateWmiConnection())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!CreatePerfOsRefresher())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (!CreatePerfOsCpuHandles())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
has_initialized_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CpuWindows::Terminate()
|
||||
{
|
||||
if (has_terminated_)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// Reverse order of Initialize().
|
||||
// Some compilers complain about deleting NULL though it's well defined
|
||||
if (previous_100ns_timestamp_ != NULL)
|
||||
{
|
||||
delete[] previous_100ns_timestamp_;
|
||||
previous_100ns_timestamp_ = NULL;
|
||||
}
|
||||
if (previous_processor_timestamp_ != NULL)
|
||||
{
|
||||
delete[] previous_processor_timestamp_;
|
||||
previous_processor_timestamp_ = NULL;
|
||||
}
|
||||
if (cpu_usage_ != NULL)
|
||||
{
|
||||
delete[] cpu_usage_;
|
||||
cpu_usage_ = NULL;
|
||||
}
|
||||
if (wbem_enum_access_ != NULL)
|
||||
{
|
||||
for (DWORD i = 0; i < number_of_objects_; i++)
|
||||
{
|
||||
if(wbem_enum_access_[i] != NULL)
|
||||
{
|
||||
wbem_enum_access_[i]->Release();
|
||||
}
|
||||
}
|
||||
delete[] wbem_enum_access_;
|
||||
wbem_enum_access_ = NULL;
|
||||
}
|
||||
if (wbem_enum_ != NULL)
|
||||
{
|
||||
wbem_enum_->Release();
|
||||
wbem_enum_ = NULL;
|
||||
}
|
||||
if (wbem_refresher_ != NULL)
|
||||
{
|
||||
wbem_refresher_->Release();
|
||||
wbem_refresher_ = NULL;
|
||||
}
|
||||
if (wbem_service_proxy_ != NULL)
|
||||
{
|
||||
wbem_service_proxy_->Release();
|
||||
wbem_service_proxy_ = NULL;
|
||||
}
|
||||
if (wbem_service_ != NULL)
|
||||
{
|
||||
wbem_service_->Release();
|
||||
wbem_service_ = NULL;
|
||||
}
|
||||
// CoUninitialized should be called once for every CoInitializeEx.
|
||||
// Regardless if it failed or not.
|
||||
CoUninitialize();
|
||||
has_terminated_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CpuWindows::UpdateCpuUsage()
|
||||
{
|
||||
wbem_refresher_->Refresh(0L);
|
||||
DWORD number_returned = 0;
|
||||
HRESULT hr = wbem_enum_->GetObjects(0L, number_of_objects_,
|
||||
wbem_enum_access_,&number_returned);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// wbem_enum_access_ has already been allocated. Unless the number of
|
||||
// CPUs change runtime this should not happen.
|
||||
return false;
|
||||
}
|
||||
unsigned __int64 cpu_usage = 0;
|
||||
unsigned __int64 timestamp_100ns = 0;
|
||||
bool returnValue = true;
|
||||
for (DWORD i = 0; i < number_returned; i++)
|
||||
{
|
||||
hr = wbem_enum_access_[i]->ReadQWORD(cpu_usage_handle_,&cpu_usage);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
returnValue = false;
|
||||
}
|
||||
hr = wbem_enum_access_[i]->ReadQWORD(timestamp_sys_100_ns_handle_,
|
||||
×tamp_100ns);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
returnValue = false;
|
||||
}
|
||||
wbem_enum_access_[i]->Release();
|
||||
wbem_enum_access_[i] = NULL;
|
||||
|
||||
const bool wrapparound =
|
||||
(previous_processor_timestamp_[i] > cpu_usage) ||
|
||||
(previous_100ns_timestamp_[i] > timestamp_100ns);
|
||||
const bool first_time = (previous_processor_timestamp_[i] == 0) ||
|
||||
(previous_100ns_timestamp_[i] == 0);
|
||||
if (wrapparound || first_time)
|
||||
{
|
||||
previous_processor_timestamp_[i] = cpu_usage;
|
||||
previous_100ns_timestamp_[i] = timestamp_100ns;
|
||||
continue;
|
||||
}
|
||||
const unsigned __int64 processor_timestamp_delta =
|
||||
cpu_usage - previous_processor_timestamp_[i];
|
||||
const unsigned __int64 timestamp_100ns_delta =
|
||||
timestamp_100ns - previous_100ns_timestamp_[i];
|
||||
|
||||
if (processor_timestamp_delta >= timestamp_100ns_delta)
|
||||
{
|
||||
cpu_usage_[i] = 0;
|
||||
} else {
|
||||
// Quotient must be float since the division is guaranteed to yield
|
||||
// a value between 0 and 1 which is 0 in integer division.
|
||||
const float delta_quotient =
|
||||
static_cast<float>(processor_timestamp_delta) /
|
||||
static_cast<float>(timestamp_100ns_delta);
|
||||
cpu_usage_[i] = 100 - static_cast<WebRtc_UWord32>(delta_quotient *
|
||||
100);
|
||||
}
|
||||
previous_processor_timestamp_[i] = cpu_usage;
|
||||
previous_100ns_timestamp_[i] = timestamp_100ns;
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
} // namespace webrtc
|
103
webrtc/system_wrappers/source/cpu_win.h
Normal file
103
webrtc/system_wrappers/source/cpu_win.h
Normal file
@ -0,0 +1,103 @@
|
||||
// This file contains a Windows implementation of CpuWrapper.
|
||||
// Note: Windows XP, Windows Server 2003 are the minimum requirements.
|
||||
// The requirements are due to the implementation being based on
|
||||
// WMI.
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CPU_WINDOWS_NO_CPOL_H_
|
||||
#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CPU_WINDOWS_NO_CPOL_H_
|
||||
|
||||
#include "cpu_wrapper.h"
|
||||
|
||||
#include <Wbemidl.h>
|
||||
|
||||
namespace webrtc {
|
||||
class ConditionVariableWrapper;
|
||||
class CriticalSectionWrapper;
|
||||
class EventWrapper;
|
||||
class ThreadWrapper;
|
||||
|
||||
class CpuWindows : public CpuWrapper
|
||||
{
|
||||
public:
|
||||
virtual WebRtc_Word32 CpuUsage();
|
||||
virtual WebRtc_Word32 CpuUsage(WebRtc_Word8* /*pProcessName*/,
|
||||
WebRtc_UWord32 /*length*/) {return -1;}
|
||||
virtual WebRtc_Word32 CpuUsage(WebRtc_UWord32 /*dwProcessID*/) {return -1;}
|
||||
|
||||
virtual WebRtc_Word32 CpuUsageMultiCore(WebRtc_UWord32& num_cores,
|
||||
WebRtc_UWord32*& cpu_usage);
|
||||
|
||||
virtual void Reset() {}
|
||||
virtual void Stop() {}
|
||||
|
||||
CpuWindows();
|
||||
virtual ~CpuWindows();
|
||||
private:
|
||||
bool AllocateComplexDataTypes();
|
||||
void DeAllocateComplexDataTypes();
|
||||
|
||||
void StartPollingCpu();
|
||||
bool StopPollingCpu();
|
||||
|
||||
static bool Process(void* thread_object);
|
||||
bool ProcessImpl();
|
||||
|
||||
bool CreateWmiConnection();
|
||||
bool CreatePerfOsRefresher();
|
||||
bool CreatePerfOsCpuHandles();
|
||||
bool Initialize();
|
||||
bool Terminate();
|
||||
|
||||
bool UpdateCpuUsage();
|
||||
|
||||
ThreadWrapper* cpu_polling_thread;
|
||||
|
||||
bool initialize_;
|
||||
bool has_initialized_;
|
||||
CriticalSectionWrapper* init_crit_;
|
||||
ConditionVariableWrapper* init_cond_;
|
||||
|
||||
bool terminate_;
|
||||
bool has_terminated_;
|
||||
CriticalSectionWrapper* terminate_crit_;
|
||||
ConditionVariableWrapper* terminate_cond_;
|
||||
|
||||
// For sleep with wake-up functionality.
|
||||
EventWrapper* sleep_event;
|
||||
|
||||
// Will be an array. Just care about CPU 0 for now.
|
||||
WebRtc_UWord32* cpu_usage_;
|
||||
|
||||
// One IWbemObjectAccess for each processor and one for the total.
|
||||
// 0-n-1 is the individual processors.
|
||||
// n is the total.
|
||||
IWbemObjectAccess** wbem_enum_access_;
|
||||
DWORD number_of_objects_;
|
||||
|
||||
// Cpu timestamp
|
||||
long cpu_usage_handle_;
|
||||
unsigned __int64* previous_processor_timestamp_;
|
||||
|
||||
// Timestamp
|
||||
long timestamp_sys_100_ns_handle_;
|
||||
unsigned __int64* previous_100ns_timestamp_;
|
||||
|
||||
IWbemServices* wbem_service_;
|
||||
IWbemServices* wbem_service_proxy_;
|
||||
|
||||
IWbemRefresher* wbem_refresher_;
|
||||
|
||||
IWbemHiPerfEnum* wbem_enum_;
|
||||
|
||||
};
|
||||
} // namespace webrtc
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CPU_WINDOWS_NO_CPOL_H_
|
76
webrtc/system_wrappers/source/cpu_wrapper_unittest.cc
Normal file
76
webrtc/system_wrappers/source/cpu_wrapper_unittest.cc
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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 "gtest/gtest.h"
|
||||
#include "system_wrappers/interface/cpu_info.h"
|
||||
#include "system_wrappers/interface/cpu_wrapper.h"
|
||||
#include "system_wrappers/interface/event_wrapper.h"
|
||||
#include "system_wrappers/interface/scoped_ptr.h"
|
||||
#include "system_wrappers/interface/trace.h"
|
||||
#include "testsupport/fileutils.h"
|
||||
|
||||
using webrtc::CpuInfo;
|
||||
using webrtc::CpuWrapper;
|
||||
using webrtc::EventWrapper;
|
||||
using webrtc::scoped_ptr;
|
||||
using webrtc::Trace;
|
||||
|
||||
// This test is flaky on Windows/Release.
|
||||
// http://code.google.com/p/webrtc/issues/detail?id=290
|
||||
#ifdef _WIN32
|
||||
#define MAYBE_Usage DISABLED_Usage
|
||||
#else
|
||||
#define MAYBE_Usage Usage
|
||||
#endif
|
||||
TEST(CpuWrapperTest, MAYBE_Usage) {
|
||||
Trace::CreateTrace();
|
||||
std::string trace_file = webrtc::test::OutputPath() +
|
||||
"cpu_wrapper_unittest.txt";
|
||||
Trace::SetTraceFile(trace_file.c_str());
|
||||
Trace::SetLevelFilter(webrtc::kTraceAll);
|
||||
printf("Number of cores detected:%u\n", CpuInfo::DetectNumberOfCores());
|
||||
scoped_ptr<CpuWrapper> cpu(CpuWrapper::CreateCpu());
|
||||
ASSERT_TRUE(cpu.get() != NULL);
|
||||
scoped_ptr<EventWrapper> sleep_event(EventWrapper::Create());
|
||||
ASSERT_TRUE(sleep_event.get() != NULL);
|
||||
|
||||
int num_iterations = 0;
|
||||
WebRtc_UWord32 num_cores = 0;
|
||||
WebRtc_UWord32* cores = NULL;
|
||||
bool cpu_usage_available = cpu->CpuUsageMultiCore(num_cores, cores) != -1;
|
||||
// Initializing the CPU measurements may take a couple of seconds on Windows.
|
||||
// Since the initialization is lazy we need to wait until it is completed.
|
||||
// Should not take more than 10000 ms.
|
||||
while (!cpu_usage_available && (++num_iterations < 10000)) {
|
||||
if (cores != NULL) {
|
||||
ASSERT_GT(num_cores, 0u);
|
||||
break;
|
||||
}
|
||||
sleep_event->Wait(1);
|
||||
cpu_usage_available = cpu->CpuUsageMultiCore(num_cores, cores) != -1;
|
||||
}
|
||||
ASSERT_TRUE(cpu_usage_available);
|
||||
|
||||
const WebRtc_Word32 average = cpu->CpuUsageMultiCore(num_cores, cores);
|
||||
ASSERT_TRUE(cores != NULL);
|
||||
EXPECT_GT(num_cores, 0u);
|
||||
EXPECT_GE(average, 0);
|
||||
EXPECT_LE(average, 100);
|
||||
|
||||
printf("\nNumber of cores:%d\n", num_cores);
|
||||
printf("Average cpu:%d\n", average);
|
||||
for (WebRtc_UWord32 i = 0; i < num_cores; i++) {
|
||||
printf("Core:%u CPU:%u \n", i, cores[i]);
|
||||
EXPECT_GE(cores[i], 0u);
|
||||
EXPECT_LE(cores[i], 100u);
|
||||
}
|
||||
|
||||
Trace::ReturnTrace();
|
||||
};
|
@ -28,6 +28,7 @@
|
||||
'../interface/compile_assert.h',
|
||||
'../interface/condition_variable_wrapper.h',
|
||||
'../interface/cpu_info.h',
|
||||
'../interface/cpu_wrapper.h',
|
||||
'../interface/cpu_features_wrapper.h',
|
||||
'../interface/critical_section_wrapper.h',
|
||||
'../interface/data_log.h',
|
||||
@ -64,7 +65,15 @@
|
||||
'condition_variable_event_win.h',
|
||||
'condition_variable_native_win.cc',
|
||||
'condition_variable_native_win.h',
|
||||
'cpu.cc',
|
||||
'cpu_no_op.cc',
|
||||
'cpu_info.cc',
|
||||
'cpu_linux.cc',
|
||||
'cpu_linux.h',
|
||||
'cpu_mac.cc',
|
||||
'cpu_mac.h',
|
||||
'cpu_win.cc',
|
||||
'cpu_win.h',
|
||||
'cpu_features.cc',
|
||||
'critical_section.cc',
|
||||
'critical_section_posix.cc',
|
||||
@ -153,6 +162,18 @@
|
||||
'libraries': [ '-lwinmm.lib', ],
|
||||
},
|
||||
}],
|
||||
['build_with_chromium==1', {
|
||||
'sources!': [
|
||||
'cpu.cc',
|
||||
'cpu_linux.h',
|
||||
'cpu_mac.h',
|
||||
'cpu_win.h',
|
||||
],
|
||||
}, {
|
||||
'sources!': [
|
||||
'cpu_no_op.cc',
|
||||
],
|
||||
}],
|
||||
], # conditions
|
||||
'target_conditions': [
|
||||
# We need to do this in a target_conditions block to override the
|
||||
@ -162,6 +183,7 @@
|
||||
# by file name rules).
|
||||
'sources/': [
|
||||
['include', '^atomic32_mac\\.'],
|
||||
['include', '^cpu_mac\\.'],
|
||||
],
|
||||
'sources!': [
|
||||
'atomic32_posix.cc',
|
||||
|
@ -20,6 +20,9 @@
|
||||
'sources': [
|
||||
'aligned_malloc_unittest.cc',
|
||||
'condition_variable_unittest.cc',
|
||||
'cpu_wrapper_unittest.cc',
|
||||
'cpu_measurement_harness.h',
|
||||
'cpu_measurement_harness.cc',
|
||||
'critical_section_unittest.cc',
|
||||
'event_tracer_unittest.cc',
|
||||
'list_unittest.cc',
|
||||
@ -33,6 +36,7 @@
|
||||
'stringize_macros_unittest.cc',
|
||||
'thread_unittest.cc',
|
||||
'thread_posix_unittest.cc',
|
||||
'trace_unittest.cc',
|
||||
'unittest_utilities_unittest.cc',
|
||||
],
|
||||
'conditions': [
|
||||
|
55
webrtc/system_wrappers/source/trace_unittest.cc
Normal file
55
webrtc/system_wrappers/source/trace_unittest.cc
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2012 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 "gtest/gtest.h"
|
||||
#include "webrtc/system_wrappers/interface/trace.h"
|
||||
#include "webrtc/system_wrappers/source/cpu_measurement_harness.h"
|
||||
#include "webrtc/test/testsupport/fileutils.h"
|
||||
|
||||
using webrtc::CpuMeasurementHarness;
|
||||
using webrtc::Trace;
|
||||
using webrtc::kTraceWarning;
|
||||
using webrtc::kTraceUtility;
|
||||
|
||||
class Logger : public webrtc::CpuTarget {
|
||||
public:
|
||||
Logger() {
|
||||
Trace::CreateTrace();
|
||||
std::string trace_file = webrtc::test::OutputPath() + "trace_unittest.txt";
|
||||
Trace::SetTraceFile(trace_file.c_str());
|
||||
Trace::SetLevelFilter(webrtc::kTraceAll);
|
||||
}
|
||||
virtual ~Logger() {
|
||||
Trace::ReturnTrace();
|
||||
}
|
||||
|
||||
virtual bool DoWork() {
|
||||
// Use input paremeters to WEBRTC_TRACE that are not likely to be removed
|
||||
// in future code. E.g. warnings will likely be kept and this file is in
|
||||
// utility so it should use kTraceUtility.
|
||||
WEBRTC_TRACE(kTraceWarning, kTraceUtility, 0, "Log line");
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// This test is disabled because it measures CPU usage. This is flaky because
|
||||
// the CPU usage for a machine may spike due to OS or other application.
|
||||
TEST(TraceTest, DISABLED_CpuUsage) {
|
||||
Logger logger;
|
||||
const int periodicity_ms = 1;
|
||||
const int iterations_per_period = 10;
|
||||
const int duration_ms = 1000;
|
||||
CpuMeasurementHarness* cpu_harness =
|
||||
CpuMeasurementHarness::Create(&logger, periodicity_ms,
|
||||
iterations_per_period, duration_ms);
|
||||
cpu_harness->Run();
|
||||
const int average_cpu = cpu_harness->AverageCpu();
|
||||
EXPECT_GE(5, average_cpu);
|
||||
}
|
@ -93,6 +93,13 @@ public:
|
||||
// of total CPU availability. [Windows only]
|
||||
virtual int GetCPULoad(int& loadPercent) = 0;
|
||||
|
||||
// Gets the computer's current CPU consumption in terms of the percent
|
||||
// of the total CPU availability. This method may fail a few times on
|
||||
// Windows because it needs a certain warm-up time before reporting the
|
||||
// result. You should check the return value and either try again or
|
||||
// give up when it fails.
|
||||
virtual int GetSystemCPULoad(int& loadPercent) = 0;
|
||||
|
||||
// Not supported
|
||||
virtual int ResetAudioDevice() = 0;
|
||||
|
||||
|
@ -51,6 +51,17 @@ TEST_F(HardwareBeforeStreamingTest, ResetsAudioDeviceOnIphone) {
|
||||
// Tests that only apply to desktop:
|
||||
#if !defined(WEBRTC_IOS) & !defined(WEBRTC_ANDROID)
|
||||
|
||||
TEST_F(HardwareBeforeStreamingTest, GetSystemCpuLoadSucceeds) {
|
||||
#ifdef _WIN32
|
||||
// This method needs some warm-up time on Windows. We sleep a good amount
|
||||
// of time instead of retrying to make the test simpler.
|
||||
Sleep(2000);
|
||||
#endif
|
||||
|
||||
int load_percent;
|
||||
EXPECT_EQ(0, voe_hardware_->GetSystemCPULoad(load_percent));
|
||||
}
|
||||
|
||||
TEST_F(HardwareBeforeStreamingTest, GetPlayoutDeviceStatusReturnsTrue) {
|
||||
bool play_available = false;
|
||||
EXPECT_EQ(0, voe_hardware_->GetPlayoutDeviceStatus(play_available));
|
||||
|
@ -69,6 +69,20 @@ TEST_F(HardwareTest, GetCpuLoadReturnsErrorOnNonWindowsPlatform) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(WEBRTC_MAC) && !defined(WEBRTC_ANDROID)
|
||||
TEST_F(HardwareTest, GetSystemCpuLoadWorksExceptOnMacAndAndroid) {
|
||||
#ifdef _WIN32
|
||||
// This method needs some warm-up time on Windows. We sleep a good amount
|
||||
// of time instead of retrying to make the test simpler.
|
||||
Sleep(2000);
|
||||
#endif
|
||||
int load = -1;
|
||||
EXPECT_EQ(0, voe_hardware_->GetSystemCPULoad(load));
|
||||
EXPECT_GE(load, 0);
|
||||
TEST_LOG("System CPU load = %d%%\n", load);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST_F(HardwareTest, BuiltInWasapiAECWorksForAudioWindowsCoreAudioLayer) {
|
||||
#ifdef WEBRTC_IOS
|
||||
// Ensure the sound device is reset on iPhone.
|
||||
|
@ -12,6 +12,7 @@
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "cpu_wrapper.h"
|
||||
#include "critical_section_wrapper.h"
|
||||
#include "trace.h"
|
||||
#include "voe_errors.h"
|
||||
@ -37,16 +38,29 @@ VoEHardware* VoEHardware::GetInterface(VoiceEngine* voiceEngine)
|
||||
|
||||
#ifdef WEBRTC_VOICE_ENGINE_HARDWARE_API
|
||||
|
||||
VoEHardwareImpl::VoEHardwareImpl(voe::SharedData* shared) : _shared(shared)
|
||||
VoEHardwareImpl::VoEHardwareImpl(voe::SharedData* shared) :
|
||||
_cpu(NULL), _shared(shared)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
|
||||
"VoEHardwareImpl() - ctor");
|
||||
|
||||
_cpu = CpuWrapper::CreateCpu();
|
||||
if (_cpu)
|
||||
{
|
||||
_cpu->CpuUsage(); // init cpu usage
|
||||
}
|
||||
}
|
||||
|
||||
VoEHardwareImpl::~VoEHardwareImpl()
|
||||
{
|
||||
WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_shared->instance_id(), -1),
|
||||
"~VoEHardwareImpl() - dtor");
|
||||
|
||||
if (_cpu)
|
||||
{
|
||||
delete _cpu;
|
||||
_cpu = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int VoEHardwareImpl::SetAudioDeviceLayer(AudioLayers audioLayer)
|
||||
@ -739,6 +753,45 @@ int VoEHardwareImpl::GetCPULoad(int& loadPercent)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VoEHardwareImpl::GetSystemCPULoad(int& loadPercent)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
|
||||
"GetSystemCPULoad(loadPercent=?)");
|
||||
ANDROID_NOT_SUPPORTED(_shared->statistics());
|
||||
IPHONE_NOT_SUPPORTED(_shared->statistics());
|
||||
|
||||
if (!_shared->statistics().Initialized())
|
||||
{
|
||||
_shared->SetLastError(VE_NOT_INITED, kTraceError);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check if implemented for this platform
|
||||
if (!_cpu)
|
||||
{
|
||||
_shared->SetLastError(VE_FUNC_NOT_SUPPORTED, kTraceError,
|
||||
" no support for getting system CPU load");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Get CPU load
|
||||
WebRtc_Word32 load = _cpu->CpuUsage();
|
||||
if (load < 0)
|
||||
{
|
||||
_shared->SetLastError(VE_CPU_INFO_ERROR, kTraceError,
|
||||
" error getting system CPU load");
|
||||
return -1;
|
||||
}
|
||||
|
||||
loadPercent = static_cast<int> (load);
|
||||
|
||||
WEBRTC_TRACE(kTraceStateInfo, kTraceVoice,
|
||||
VoEId(_shared->instance_id(), -1),
|
||||
" Output: loadPercent = %d", loadPercent);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VoEHardwareImpl::EnableBuiltInAEC(bool enable)
|
||||
{
|
||||
WEBRTC_TRACE(kTraceApiCall, kTraceVoice, VoEId(_shared->instance_id(), -1),
|
||||
|
@ -17,6 +17,7 @@
|
||||
|
||||
namespace webrtc
|
||||
{
|
||||
class CpuWrapper;
|
||||
|
||||
class VoEHardwareImpl: public VoEHardware
|
||||
{
|
||||
@ -49,6 +50,8 @@ public:
|
||||
|
||||
virtual int GetCPULoad(int& loadPercent);
|
||||
|
||||
virtual int GetSystemCPULoad(int& loadPercent);
|
||||
|
||||
virtual int ResetAudioDevice();
|
||||
|
||||
virtual int AudioDeviceControl(unsigned int par1,
|
||||
@ -72,6 +75,7 @@ protected:
|
||||
virtual ~VoEHardwareImpl();
|
||||
|
||||
private:
|
||||
CpuWrapper* _cpu;
|
||||
voe::SharedData* _shared;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user