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/webrtc@3737 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/system_wrappers/interface/cpu_wrapper.h b/system_wrappers/interface/cpu_wrapper.h
new file mode 100644
index 0000000..0911213
--- /dev/null
+++ b/system_wrappers/interface/cpu_wrapper.h
@@ -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_
diff --git a/system_wrappers/source/Android.mk b/system_wrappers/source/Android.mk
index ac64c3a..f59d880 100644
--- a/system_wrappers/source/Android.mk
+++ b/system_wrappers/source/Android.mk
@@ -24,6 +24,7 @@
     aligned_malloc.cc \
     atomic32_posix.cc \
     condition_variable.cc \
+    cpu_no_op.cc \
     cpu_features.cc \
     cpu_info.cc \
     critical_section.cc \
diff --git a/system_wrappers/source/cpu.cc b/system_wrappers/source/cpu.cc
new file mode 100644
index 0000000..d81f015
--- /dev/null
+++ b/system_wrappers/source/cpu.cc
@@ -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
diff --git a/system_wrappers/source/cpu_info.cc b/system_wrappers/source/cpu_info.cc
index 514f41f..9bed35c 100644
--- a/system_wrappers/source/cpu_info.cc
+++ b/system_wrappers/source/cpu_info.cc
@@ -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 {
 
diff --git a/system_wrappers/source/cpu_linux.cc b/system_wrappers/source/cpu_linux.cc
new file mode 100644
index 0000000..74783b9
--- /dev/null
+++ b/system_wrappers/source/cpu_linux.cc
@@ -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
diff --git a/system_wrappers/source/cpu_linux.h b/system_wrappers/source/cpu_linux.h
new file mode 100644
index 0000000..804b53e
--- /dev/null
+++ b/system_wrappers/source/cpu_linux.h
@@ -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_
diff --git a/system_wrappers/source/cpu_mac.cc b/system_wrappers/source/cpu_mac.cc
new file mode 100644
index 0000000..0342802
--- /dev/null
+++ b/system_wrappers/source/cpu_mac.cc
@@ -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
diff --git a/system_wrappers/source/cpu_mac.h b/system_wrappers/source/cpu_mac.h
new file mode 100644
index 0000000..7e58003
--- /dev/null
+++ b/system_wrappers/source/cpu_mac.h
@@ -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_
diff --git a/system_wrappers/source/cpu_measurement_harness.cc b/system_wrappers/source/cpu_measurement_harness.cc
new file mode 100644
index 0000000..237e776
--- /dev/null
+++ b/system_wrappers/source/cpu_measurement_harness.cc
@@ -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
diff --git a/system_wrappers/source/cpu_measurement_harness.h b/system_wrappers/source/cpu_measurement_harness.h
new file mode 100644
index 0000000..3b87f27
--- /dev/null
+++ b/system_wrappers/source/cpu_measurement_harness.h
@@ -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_
diff --git a/system_wrappers/source/cpu_no_op.cc b/system_wrappers/source/cpu_no_op.cc
new file mode 100644
index 0000000..f666961
--- /dev/null
+++ b/system_wrappers/source/cpu_no_op.cc
@@ -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
diff --git a/system_wrappers/source/cpu_win.cc b/system_wrappers/source/cpu_win.cc
new file mode 100644
index 0000000..7231d4d
--- /dev/null
+++ b/system_wrappers/source/cpu_win.cc
@@ -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",
+                                                 &timestamp_sys_100_ns_type,
+                                                 &timestamp_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_,
+                                             &timestamp_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
diff --git a/system_wrappers/source/cpu_win.h b/system_wrappers/source/cpu_win.h
new file mode 100644
index 0000000..d15073c
--- /dev/null
+++ b/system_wrappers/source/cpu_win.h
@@ -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_
diff --git a/system_wrappers/source/cpu_wrapper_unittest.cc b/system_wrappers/source/cpu_wrapper_unittest.cc
new file mode 100644
index 0000000..c849689
--- /dev/null
+++ b/system_wrappers/source/cpu_wrapper_unittest.cc
@@ -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();
+};
diff --git a/system_wrappers/source/system_wrappers.gyp b/system_wrappers/source/system_wrappers.gyp
index 8bc947b..36aa7d6 100644
--- a/system_wrappers/source/system_wrappers.gyp
+++ b/system_wrappers/source/system_wrappers.gyp
@@ -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',
diff --git a/system_wrappers/source/system_wrappers_tests.gyp b/system_wrappers/source/system_wrappers_tests.gyp
index fd1db25..66939e9 100644
--- a/system_wrappers/source/system_wrappers_tests.gyp
+++ b/system_wrappers/source/system_wrappers_tests.gyp
@@ -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': [
diff --git a/system_wrappers/source/trace_unittest.cc b/system_wrappers/source/trace_unittest.cc
new file mode 100644
index 0000000..62422ad
--- /dev/null
+++ b/system_wrappers/source/trace_unittest.cc
@@ -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);
+}
diff --git a/voice_engine/include/voe_hardware.h b/voice_engine/include/voe_hardware.h
index 1537aab..e973c11 100644
--- a/voice_engine/include/voe_hardware.h
+++ b/voice_engine/include/voe_hardware.h
@@ -93,6 +93,13 @@
     // 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;
 
diff --git a/voice_engine/test/auto_test/standard/hardware_before_streaming_test.cc b/voice_engine/test/auto_test/standard/hardware_before_streaming_test.cc
index 6136543..edb7f56 100644
--- a/voice_engine/test/auto_test/standard/hardware_before_streaming_test.cc
+++ b/voice_engine/test/auto_test/standard/hardware_before_streaming_test.cc
@@ -51,6 +51,17 @@
 // 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));
diff --git a/voice_engine/test/auto_test/standard/hardware_test.cc b/voice_engine/test/auto_test/standard/hardware_test.cc
index d026f51..7310e52 100644
--- a/voice_engine/test/auto_test/standard/hardware_test.cc
+++ b/voice_engine/test/auto_test/standard/hardware_test.cc
@@ -69,6 +69,20 @@
 }
 #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.
diff --git a/voice_engine/voe_hardware_impl.cc b/voice_engine/voe_hardware_impl.cc
index a374bc9..db7e18f 100644
--- a/voice_engine/voe_hardware_impl.cc
+++ b/voice_engine/voe_hardware_impl.cc
@@ -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 @@
 
 #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 @@
     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),
diff --git a/voice_engine/voe_hardware_impl.h b/voice_engine/voe_hardware_impl.h
index 1b2f343..9477567 100644
--- a/voice_engine/voe_hardware_impl.h
+++ b/voice_engine/voe_hardware_impl.h
@@ -17,6 +17,7 @@
 
 namespace webrtc
 {
+class CpuWrapper;
 
 class VoEHardwareImpl: public VoEHardware
 {
@@ -49,6 +50,8 @@
 
     virtual int GetCPULoad(int& loadPercent);
 
+    virtual int GetSystemCPULoad(int& loadPercent);
+
     virtual int ResetAudioDevice();
 
     virtual int AudioDeviceControl(unsigned int par1,
@@ -72,6 +75,7 @@
     virtual ~VoEHardwareImpl();
 
 private:
+    CpuWrapper* _cpu;
     voe::SharedData* _shared;
 };