aboutsummaryrefslogtreecommitdiff
path: root/src/system_wrappers
diff options
context:
space:
mode:
Diffstat (limited to 'src/system_wrappers')
-rw-r--r--src/system_wrappers/interface/atomic32.h65
-rw-r--r--src/system_wrappers/interface/atomic32_wrapper.h55
-rw-r--r--src/system_wrappers/interface/compile_assert.h21
-rw-r--r--src/system_wrappers/interface/fix_interlocked_exchange_pointer_win.h35
-rw-r--r--src/system_wrappers/interface/ref_count.h6
-rw-r--r--src/system_wrappers/interface/sleep.h24
-rw-r--r--src/system_wrappers/interface/static_instance.h8
-rw-r--r--src/system_wrappers/interface/thread_wrapper.h17
-rw-r--r--src/system_wrappers/interface/tick_util.h33
-rw-r--r--src/system_wrappers/interface/trace.h7
-rw-r--r--src/system_wrappers/source/Android.mk9
-rw-r--r--src/system_wrappers/source/android/cpu-features.c396
-rw-r--r--src/system_wrappers/source/android/cpu-features.h56
-rw-r--r--src/system_wrappers/source/atomic32.cc84
-rw-r--r--src/system_wrappers/source/atomic32_linux.h119
-rw-r--r--src/system_wrappers/source/atomic32_mac.cc60
-rw-r--r--src/system_wrappers/source/atomic32_mac.h117
-rw-r--r--src/system_wrappers/source/atomic32_posix.cc64
-rw-r--r--src/system_wrappers/source/atomic32_win.cc72
-rw-r--r--src/system_wrappers/source/condition_variable_unittest.cc208
-rw-r--r--src/system_wrappers/source/condition_variable_win.cc224
-rw-r--r--src/system_wrappers/source/condition_variable_win.h67
-rw-r--r--src/system_wrappers/source/cpu_features_android.c15
-rw-r--r--src/system_wrappers/source/cpu_features_arm.c333
-rw-r--r--src/system_wrappers/source/cpu_linux.cc1
-rw-r--r--src/system_wrappers/source/cpu_measurement_harness.cc127
-rw-r--r--src/system_wrappers/source/cpu_measurement_harness.h66
-rw-r--r--src/system_wrappers/source/cpu_win.cc530
-rw-r--r--src/system_wrappers/source/cpu_win.h103
-rw-r--r--src/system_wrappers/source/cpu_wrapper_unittest.cc13
-rw-r--r--src/system_wrappers/source/critical_section_posix.cc22
-rw-r--r--src/system_wrappers/source/critical_section_unittest.cc167
-rw-r--r--src/system_wrappers/source/critical_section_win.cc35
-rw-r--r--src/system_wrappers/source/critical_section_win.h36
-rw-r--r--src/system_wrappers/source/event_win.cc84
-rw-r--r--src/system_wrappers/source/event_win.h40
-rw-r--r--src/system_wrappers/source/file_impl.cc4
-rw-r--r--src/system_wrappers/source/rw_lock.cc7
-rw-r--r--src/system_wrappers/source/rw_lock_win.cc186
-rw-r--r--src/system_wrappers/source/rw_lock_win.h71
-rw-r--r--src/system_wrappers/source/set_thread_name_win.h43
-rw-r--r--src/system_wrappers/source/sleep.cc36
-rw-r--r--src/system_wrappers/source/sort.cc8
-rw-r--r--src/system_wrappers/source/system_wrappers.gyp54
-rw-r--r--src/system_wrappers/source/thread_posix.cc195
-rw-r--r--src/system_wrappers/source/thread_posix.h12
-rw-r--r--src/system_wrappers/source/thread_unittest.cc96
-rw-r--r--src/system_wrappers/source/thread_win.cc233
-rw-r--r--src/system_wrappers/source/thread_win.h66
-rw-r--r--src/system_wrappers/source/trace_impl.cc68
-rw-r--r--src/system_wrappers/source/trace_impl.h19
-rw-r--r--src/system_wrappers/source/trace_impl_no_op.cc4
-rw-r--r--src/system_wrappers/source/trace_posix.cc104
-rw-r--r--src/system_wrappers/source/trace_posix.h1
-rw-r--r--src/system_wrappers/source/trace_unittest.cc57
-rw-r--r--src/system_wrappers/source/trace_win.cc131
-rw-r--r--src/system_wrappers/source/trace_win.h36
-rw-r--r--src/system_wrappers/source/unittest_utilities.h83
-rw-r--r--src/system_wrappers/source/unittest_utilities_unittest.cc34
59 files changed, 3916 insertions, 951 deletions
diff --git a/src/system_wrappers/interface/atomic32.h b/src/system_wrappers/interface/atomic32.h
new file mode 100644
index 0000000000..e2b12589d7
--- /dev/null
+++ b/src/system_wrappers/interface/atomic32.h
@@ -0,0 +1,65 @@
+/*
+ * 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.
+ */
+
+// Atomic, system independent 32-bit integer. Unless you know what you're
+// doing, use locks instead! :-)
+//
+// Note: uses full memory barriers.
+// Note: assumes 32-bit (or higher) system
+#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ATOMIC32_H_
+#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ATOMIC32_H_
+
+#include <cstddef>
+
+#include "common_types.h"
+#include "constructor_magic.h"
+
+namespace webrtc {
+
+// 32 bit atomic variable. Note that this class relies on the compiler to
+// align the 32 bit value correctly (on a 32 bit boundary), so as long as you're
+// not doing things like reinterpret_cast over some custom allocated memory
+// without being careful with alignment, you should be fine.
+class Atomic32
+{
+public:
+ Atomic32(WebRtc_Word32 initialValue = 0);
+ ~Atomic32();
+
+ // Prefix operator!
+ WebRtc_Word32 operator++();
+ WebRtc_Word32 operator--();
+
+ WebRtc_Word32 operator+=(WebRtc_Word32 value);
+ WebRtc_Word32 operator-=(WebRtc_Word32 value);
+
+ // Sets the value atomically to newValue if the value equals compare value.
+ // The function returns true if the exchange happened.
+ bool CompareExchange(WebRtc_Word32 newValue, WebRtc_Word32 compareValue);
+ WebRtc_Word32 Value() const;
+
+private:
+ // Disable the + and - operator since it's unclear what these operations
+ // should do.
+ Atomic32 operator+(const Atomic32& other);
+ Atomic32 operator-(const Atomic32& other);
+
+ // Checks if |_value| is 32bit aligned.
+ inline bool Is32bitAligned() const {
+ return (reinterpret_cast<ptrdiff_t>(&_value) & 3) == 0;
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(Atomic32);
+
+ WebRtc_Word32 _value;
+};
+} // namespace webrtc
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ATOMIC32_H_
diff --git a/src/system_wrappers/interface/atomic32_wrapper.h b/src/system_wrappers/interface/atomic32_wrapper.h
deleted file mode 100644
index 40862fb492..0000000000
--- a/src/system_wrappers/interface/atomic32_wrapper.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.
- */
-
-// Atomic system independant 32-bit integer.
-// Note: uses full memory barriers.
-// Note: assumes 32-bit (or higher) system
-#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ATOMIC32_WRAPPER_H_
-#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ATOMIC32_WRAPPER_H_
-
-#include "common_types.h"
-
-namespace webrtc {
-class Atomic32Impl;
-class Atomic32Wrapper
-{
-public:
- Atomic32Wrapper(WebRtc_Word32 initialValue = 0);
- ~Atomic32Wrapper();
-
- // Prefix operator!
- WebRtc_Word32 operator++();
- WebRtc_Word32 operator--();
-
- Atomic32Wrapper& operator=(const Atomic32Wrapper& rhs);
- Atomic32Wrapper& operator=(WebRtc_Word32 rhs);
-
- WebRtc_Word32 operator+=(WebRtc_Word32 rhs);
- WebRtc_Word32 operator-=(WebRtc_Word32 rhs);
-
- // Sets the value atomically to newValue if the value equals compare value.
- // The function returns true if the exchange happened.
- bool CompareExchange(WebRtc_Word32 newValue, WebRtc_Word32 compareValue);
- WebRtc_Word32 Value() const;
-private:
- // Disable the + and - operator since it's unclear what these operations
- // should do.
- Atomic32Wrapper operator+(const Atomic32Wrapper& rhs);
- Atomic32Wrapper operator-(const Atomic32Wrapper& rhs);
-
- WebRtc_Word32& operator++(int);
- WebRtc_Word32& operator--(int);
-
- // Cheshire cat to hide the implementation (faster than
- // using virtual functions)
- Atomic32Impl& _impl;
-};
-} // namespace webrtc
-#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_ATOMIC32_WRAPPER_H_
diff --git a/src/system_wrappers/interface/compile_assert.h b/src/system_wrappers/interface/compile_assert.h
new file mode 100644
index 0000000000..4feda86c3a
--- /dev/null
+++ b/src/system_wrappers/interface/compile_assert.h
@@ -0,0 +1,21 @@
+/*
+ * 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 WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_
+#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_
+
+/* Use this macro to verify at compile time that certain restrictions are met.
+ * The argument is the boolean expression to evaluate.
+ * Example:
+ * COMPILE_ASSERT(sizeof(foo) < 128);
+*/
+#define COMPILE_ASSERT(expression) switch(0){case 0: case expression:;}
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_COMPILE_ASSERT_H_
diff --git a/src/system_wrappers/interface/fix_interlocked_exchange_pointer_win.h b/src/system_wrappers/interface/fix_interlocked_exchange_pointer_win.h
new file mode 100644
index 0000000000..d85c724729
--- /dev/null
+++ b/src/system_wrappers/interface/fix_interlocked_exchange_pointer_win.h
@@ -0,0 +1,35 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file under third_party_mods/chromium directory of
+// source tree or at
+// http://src.chromium.org/viewvc/chrome/trunk/src/LICENSE
+
+// Various inline functions and macros to fix compilation of 32 bit target
+// on MSVC with /Wp64 flag enabled.
+
+// The original code can be found here:
+// http://src.chromium.org/svn/trunk/src/base/fix_wp64.h
+
+#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_FIX_INTERLOCKED_EXCHANGE_POINTER_WINDOWS_H_
+#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_FIX_INTERLOCKED_EXCHANGE_POINTER_WINDOWS_H_
+
+#include <windows.h>
+
+// Platform SDK fixes when building with /Wp64 for a 32 bits target.
+#if !defined(_WIN64) && defined(_Wp64)
+
+#ifdef InterlockedExchangePointer
+#undef InterlockedExchangePointer
+// The problem is that the macro provided for InterlockedExchangePointer() is
+// doing a (LONG) C-style cast that triggers invariably the warning C4312 when
+// building on 32 bits.
+inline void* InterlockedExchangePointer(void* volatile* target, void* value) {
+ return reinterpret_cast<void*>(static_cast<LONG_PTR>(InterlockedExchange(
+ reinterpret_cast<volatile LONG*>(target),
+ static_cast<LONG>(reinterpret_cast<LONG_PTR>(value)))));
+}
+#endif // #ifdef InterlockedExchangePointer
+
+#endif // #if !defined(_WIN64) && defined(_Wp64)
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_FIX_INTERLOCKED_EXCHANGE_POINTER_WINDOWS_H_
diff --git a/src/system_wrappers/interface/ref_count.h b/src/system_wrappers/interface/ref_count.h
index f90b0b3609..5112bd9037 100644
--- a/src/system_wrappers/interface/ref_count.h
+++ b/src/system_wrappers/interface/ref_count.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -11,7 +11,7 @@
#ifndef SYSTEM_WRAPPERS_INTERFACE_REF_COUNT_H_
#define SYSTEM_WRAPPERS_INTERFACE_REF_COUNT_H_
-#include "system_wrappers/interface/atomic32_wrapper.h"
+#include "system_wrappers/interface/atomic32.h"
namespace webrtc {
@@ -74,7 +74,7 @@ class RefCountImpl : public T {
}
protected:
- Atomic32Wrapper ref_count_;
+ Atomic32 ref_count_;
};
} // namespace webrtc
diff --git a/src/system_wrappers/interface/sleep.h b/src/system_wrappers/interface/sleep.h
new file mode 100644
index 0000000000..c0205bf085
--- /dev/null
+++ b/src/system_wrappers/interface/sleep.h
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
+// An OS-independent sleep function.
+
+#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SLEEP_H_
+#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SLEEP_H_
+
+namespace webrtc {
+
+// This function sleeps for the specified number of milliseconds.
+// It may return early if the thread is woken by some other event,
+// such as the delivery of a signal on Unix.
+void SleepMs(int msecs);
+
+} // namespace webrtc
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_SLEEP_H_
diff --git a/src/system_wrappers/interface/static_instance.h b/src/system_wrappers/interface/static_instance.h
index 8fe91cc3e4..b670f969c9 100644
--- a/src/system_wrappers/interface/static_instance.h
+++ b/src/system_wrappers/interface/static_instance.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -128,10 +128,8 @@ static T* GetStaticInstance(CountOperation count_operation) {
// local copy.
T* new_instance = T::CreateInstance();
if (1 == InterlockedIncrement(&instance_count)) {
- T* old_value = static_cast<T*> (InterlockedExchangePointer(
- reinterpret_cast<void* volatile*>(&instance), new_instance));
- assert(old_value == NULL);
- assert(instance);
+ InterlockedExchangePointer(reinterpret_cast<void* volatile*>(&instance),
+ new_instance);
} else {
InterlockedDecrement(&instance_count);
if (new_instance) {
diff --git a/src/system_wrappers/interface/thread_wrapper.h b/src/system_wrappers/interface/thread_wrapper.h
index 72a06e8bdd..030ac8a6f7 100644
--- a/src/system_wrappers/interface/thread_wrapper.h
+++ b/src/system_wrappers/interface/thread_wrapper.h
@@ -16,6 +16,9 @@
#ifndef WEBRTC_SYSTEM_WRAPPERS_INTERFACE_THREAD_WRAPPER_H_
#define WEBRTC_SYSTEM_WRAPPERS_INTERFACE_THREAD_WRAPPER_H_
+#include "common_types.h"
+#include "typedefs.h"
+
namespace webrtc {
// Object that will be passed by the spawned thread when it enters the callback
// function.
@@ -51,9 +54,12 @@ public:
// threadName NULL terminated thread name, will be visable in the Windows
// debugger.
static ThreadWrapper* CreateThread(ThreadRunFunction func = 0,
- ThreadObj obj= 0,
- ThreadPriority prio = kNormalPriority,
- const char* threadName = 0);
+ ThreadObj obj= 0,
+ ThreadPriority prio = kNormalPriority,
+ const char* threadName = 0);
+
+ // Get the current thread's kernel thread ID.
+ static uint32_t GetThreadId();
// Non blocking termination of the spawned thread. Note that it is not safe
// to delete this class until the spawned thread has been reclaimed.
@@ -69,8 +75,9 @@ public:
// should be lower than (number of CPUs - 1). amountOfProcessors should be
// equal to the number of processors listed in processorNumbers
virtual bool SetAffinity(const int* /*processorNumbers*/,
- const unsigned int /*amountOfProcessors*/)
- {return false;}
+ const unsigned int /*amountOfProcessors*/) {
+ return false;
+ }
// Stops the spawned thread and waits for it to be reclaimed with a timeout
// of two seconds. Will return false if the thread was not reclaimed.
diff --git a/src/system_wrappers/interface/tick_util.h b/src/system_wrappers/interface/tick_util.h
index e78e53d2e1..0cd85d0050 100644
--- a/src/system_wrappers/interface/tick_util.h
+++ b/src/system_wrappers/interface/tick_util.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -19,6 +19,9 @@
#include <mmsystem.h>
#elif WEBRTC_LINUX
#include <ctime>
+#elif WEBRTC_MAC
+#include <mach/mach_time.h>
+#include <string.h>
#else
#include <sys/time.h>
#include <time.h>
@@ -133,6 +136,7 @@ inline TickTime TickTime::Now()
{
TickTime result;
#if _WIN32
+ // TODO(wu): Remove QueryPerformanceCounter implementation.
#ifdef USE_QUERY_PERFORMANCE_COUNTER
// QueryPerformanceCounter returns the value from the TSC which is
// incremented at the CPU frequency. The algorithm used requires
@@ -164,12 +168,27 @@ inline TickTime TickTime::Now()
#endif
#elif defined(WEBRTC_LINUX)
struct timespec ts;
+ // TODO(wu): Remove CLOCK_REALTIME implementation.
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
clock_gettime(CLOCK_REALTIME, &ts);
#else
clock_gettime(CLOCK_MONOTONIC, &ts);
#endif
result._ticks = 1000000000LL * static_cast<WebRtc_Word64>(ts.tv_sec) + static_cast<WebRtc_Word64>(ts.tv_nsec);
+#elif defined(WEBRTC_MAC)
+ static mach_timebase_info_data_t timebase;
+ if (timebase.denom == 0) {
+ // Get the timebase if this is the first time we run.
+ // Recommended by Apple's QA1398.
+ kern_return_t retval = mach_timebase_info(&timebase);
+ if (retval != KERN_SUCCESS) {
+ // TODO(wu): Implement CHECK similar to chrome for all the platforms.
+ // Then replace this with a CHECK(retval == KERN_SUCCESS);
+ asm("int3");
+ }
+ }
+ // Use timebase to convert absolute time tick units into nanoseconds.
+ result._ticks = mach_absolute_time() * timebase.numer / timebase.denom;
#else
struct timeval tv;
gettimeofday(&tv, NULL);
@@ -189,7 +208,7 @@ inline WebRtc_Word64 TickTime::MillisecondTimestamp()
#else
return now._ticks;
#endif
-#elif WEBRTC_LINUX
+#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
return now._ticks / 1000000LL;
#else
return now._ticks / 1000LL;
@@ -208,7 +227,7 @@ inline WebRtc_Word64 TickTime::MicrosecondTimestamp()
#else
return now._ticks *1000LL;
#endif
-#elif WEBRTC_LINUX
+#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
return now._ticks / 1000LL;
#else
return now._ticks;
@@ -230,7 +249,7 @@ inline WebRtc_Word64 TickTime::MillisecondsToTicks(const WebRtc_Word64 ms)
#else
return ms;
#endif
-#elif WEBRTC_LINUX
+#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
return ms * 1000000LL;
#else
return ms * 1000LL;
@@ -247,7 +266,7 @@ inline WebRtc_Word64 TickTime::TicksToMilliseconds(const WebRtc_Word64 ticks)
#else
return ticks;
#endif
-#elif WEBRTC_LINUX
+#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
return ticks / 1000000LL;
#else
return ticks / 1000LL;
@@ -280,7 +299,7 @@ inline WebRtc_Word64 TickInterval::Milliseconds() const
// _interval is in ms
return _interval;
#endif
-#elif WEBRTC_LINUX
+#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
// _interval is in ns
return _interval / 1000000;
#else
@@ -300,7 +319,7 @@ inline WebRtc_Word64 TickInterval::Microseconds() const
// _interval is in ms
return _interval *1000LL;
#endif
-#elif WEBRTC_LINUX
+#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
// _interval is in ns
return _interval / 1000;
#else
diff --git a/src/system_wrappers/interface/trace.h b/src/system_wrappers/interface/trace.h
index 8330f7c4e1..f88d23f8a7 100644
--- a/src/system_wrappers/interface/trace.h
+++ b/src/system_wrappers/interface/trace.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -45,11 +45,11 @@ public:
// Sets the file name. If addFileCounter is false the same file will be
// reused when it fills up. If it's true a new file with incremented name
// will be used.
- static WebRtc_Word32 SetTraceFile(const WebRtc_Word8* fileName,
+ static WebRtc_Word32 SetTraceFile(const char* fileName,
const bool addFileCounter = false);
// Returns the name of the file that the trace is currently writing to.
- static WebRtc_Word32 TraceFile(WebRtc_Word8 fileName[1024]);
+ static WebRtc_Word32 TraceFile(char fileName[1024]);
// Registers callback to receive trace messages. TODO (hellner)
// why not use OutStream instead? Why is TraceCallback not defined in this
@@ -70,7 +70,6 @@ public:
const TraceModule module,
const WebRtc_Word32 id,
const char* msg, ...);
-
};
} // namespace webrtc
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TRACE_H_
diff --git a/src/system_wrappers/source/Android.mk b/src/system_wrappers/source/Android.mk
index 575580a497..dee84ca294 100644
--- a/src/system_wrappers/source/Android.mk
+++ b/src/system_wrappers/source/Android.mk
@@ -1,4 +1,4 @@
-# Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+# 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
@@ -17,15 +17,15 @@ LOCAL_MODULE := libwebrtc_system_wrappers
LOCAL_MODULE_TAGS := optional
LOCAL_CPP_EXTENSION := .cc
LOCAL_SRC_FILES := \
+ android/cpu-features.c \
+ cpu_features_android.c \
map.cc \
- rw_lock_generic.cc \
sort.cc \
aligned_malloc.cc \
- atomic32.cc \
+ atomic32_posix.cc \
condition_variable.cc \
cpu_no_op.cc \
cpu_features.cc \
- cpu_features_arm.c \
cpu_info.cc \
critical_section.cc \
event.cc \
@@ -38,6 +38,7 @@ LOCAL_SRC_FILES := \
cpu_linux.cc \
critical_section_posix.cc \
event_posix.cc \
+ sleep.cc \
thread_posix.cc \
trace_posix.cc \
rw_lock_posix.cc
diff --git a/src/system_wrappers/source/android/cpu-features.c b/src/system_wrappers/source/android/cpu-features.c
new file mode 100644
index 0000000000..6a5cd8f1aa
--- /dev/null
+++ b/src/system_wrappers/source/android/cpu-features.c
@@ -0,0 +1,396 @@
+/*
+ * 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 <sys/system_properties.h>
+#ifdef __arm__
+#include <machine/cpu-features.h>
+#endif
+#include <pthread.h>
+#include "cpu-features.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+
+static pthread_once_t g_once;
+static AndroidCpuFamily g_cpuFamily;
+static uint64_t g_cpuFeatures;
+static int g_cpuCount;
+
+static const int android_cpufeatures_debug = 0;
+
+#ifdef __arm__
+# define DEFAULT_CPU_FAMILY ANDROID_CPU_FAMILY_ARM
+#elif defined __i386__
+# define DEFAULT_CPU_FAMILY ANDROID_CPU_FAMILY_X86
+#else
+# define DEFAULT_CPU_FAMILY ANDROID_CPU_FAMILY_UNKNOWN
+#endif
+
+#define D(...) \
+ do { \
+ if (android_cpufeatures_debug) { \
+ printf(__VA_ARGS__); fflush(stdout); \
+ } \
+ } while (0)
+
+#ifdef __i386__
+static __inline__ void x86_cpuid(int func, int values[4])
+{
+ int a, b, c, d;
+ /* We need to preserve ebx since we're compiling PIC code */
+ /* this means we can't use "=b" for the second output register */
+ __asm__ __volatile__ ( \
+ "push %%ebx\n"
+ "cpuid\n" \
+ "mov %1, %%ebx\n"
+ "pop %%ebx\n"
+ : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
+ : "a" (func) \
+ );
+ values[0] = a;
+ values[1] = b;
+ values[2] = c;
+ values[3] = d;
+}
+#endif
+
+/* Read the content of /proc/cpuinfo into a user-provided buffer.
+ * Return the length of the data, or -1 on error. Does *not*
+ * zero-terminate the content. Will not read more
+ * than 'buffsize' bytes.
+ */
+static int
+read_file(const char* pathname, char* buffer, size_t buffsize)
+{
+ int fd, len;
+
+ fd = open(pathname, O_RDONLY);
+ if (fd < 0)
+ return -1;
+
+ do {
+ len = read(fd, buffer, buffsize);
+ } while (len < 0 && errno == EINTR);
+
+ close(fd);
+
+ return len;
+}
+
+/* Extract the content of a the first occurence of a given field in
+ * the content of /proc/cpuinfo and return it as a heap-allocated
+ * string that must be freed by the caller.
+ *
+ * Return NULL if not found
+ */
+static char*
+extract_cpuinfo_field(char* buffer, int buflen, const char* field)
+{
+ int fieldlen = strlen(field);
+ char* bufend = buffer + buflen;
+ char* result = NULL;
+ int len, ignore;
+ const char *p, *q;
+
+ /* Look for first field occurence, and ensures it starts the line.
+ */
+ p = buffer;
+ bufend = buffer + buflen;
+ for (;;) {
+ p = memmem(p, bufend-p, field, fieldlen);
+ if (p == NULL)
+ goto EXIT;
+
+ if (p == buffer || p[-1] == '\n')
+ break;
+
+ p += fieldlen;
+ }
+
+ /* Skip to the first column followed by a space */
+ p += fieldlen;
+ p = memchr(p, ':', bufend-p);
+ if (p == NULL || p[1] != ' ')
+ goto EXIT;
+
+ /* Find the end of the line */
+ p += 2;
+ q = memchr(p, '\n', bufend-p);
+ if (q == NULL)
+ q = bufend;
+
+ /* Copy the line into a heap-allocated buffer */
+ len = q-p;
+ result = malloc(len+1);
+ if (result == NULL)
+ goto EXIT;
+
+ memcpy(result, p, len);
+ result[len] = '\0';
+
+EXIT:
+ return result;
+}
+
+/* Count the number of occurences of a given field prefix in /proc/cpuinfo.
+ */
+static int
+count_cpuinfo_field(char* buffer, int buflen, const char* field)
+{
+ int fieldlen = strlen(field);
+ const char* p = buffer;
+ const char* bufend = buffer + buflen;
+ const char* q;
+ int count = 0;
+
+ for (;;) {
+ const char* q;
+
+ p = memmem(p, bufend-p, field, fieldlen);
+ if (p == NULL)
+ break;
+
+ /* Ensure that the field is at the start of a line */
+ if (p > buffer && p[-1] != '\n') {
+ p += fieldlen;
+ continue;
+ }
+
+
+ /* skip any whitespace */
+ q = p + fieldlen;
+ while (q < bufend && (*q == ' ' || *q == '\t'))
+ q++;
+
+ /* we must have a colon now */
+ if (q < bufend && *q == ':') {
+ count += 1;
+ q ++;
+ }
+ p = q;
+ }
+
+ return count;
+}
+
+/* Like strlen(), but for constant string literals */
+#define STRLEN_CONST(x) ((sizeof(x)-1)
+
+
+/* Checks that a space-separated list of items contains one given 'item'.
+ * Returns 1 if found, 0 otherwise.
+ */
+static int
+has_list_item(const char* list, const char* item)
+{
+ const char* p = list;
+ int itemlen = strlen(item);
+
+ if (list == NULL)
+ return 0;
+
+ while (*p) {
+ const char* q;
+
+ /* skip spaces */
+ while (*p == ' ' || *p == '\t')
+ p++;
+
+ /* find end of current list item */
+ q = p;
+ while (*q && *q != ' ' && *q != '\t')
+ q++;
+
+ if (itemlen == q-p && !memcmp(p, item, itemlen))
+ return 1;
+
+ /* skip to next item */
+ p = q;
+ }
+ return 0;
+}
+
+
+static void
+android_cpuInit(void)
+{
+ char cpuinfo[4096];
+ int cpuinfo_len;
+
+ g_cpuFamily = DEFAULT_CPU_FAMILY;
+ g_cpuFeatures = 0;
+ g_cpuCount = 1;
+
+ cpuinfo_len = read_file("/proc/cpuinfo", cpuinfo, sizeof cpuinfo);
+ D("cpuinfo_len is (%d):\n%.*s\n", cpuinfo_len,
+ cpuinfo_len >= 0 ? cpuinfo_len : 0, cpuinfo);
+
+ if (cpuinfo_len < 0) /* should not happen */ {
+ return;
+ }
+
+ /* Count the CPU cores, the value may be 0 for single-core CPUs */
+ g_cpuCount = count_cpuinfo_field(cpuinfo, cpuinfo_len, "processor");
+ if (g_cpuCount == 0) {
+ g_cpuCount = count_cpuinfo_field(cpuinfo, cpuinfo_len, "Processor");
+ if (g_cpuCount == 0) {
+ g_cpuCount = 1;
+ }
+ }
+
+ D("found cpuCount = %d\n", g_cpuCount);
+
+#ifdef __ARM_ARCH__
+ {
+ char* features = NULL;
+ char* architecture = NULL;
+
+ /* Extract architecture from the "CPU Architecture" field.
+ * The list is well-known, unlike the the output of
+ * the 'Processor' field which can vary greatly.
+ *
+ * See the definition of the 'proc_arch' array in
+ * $KERNEL/arch/arm/kernel/setup.c and the 'c_show' function in
+ * same file.
+ */
+ char* cpuArch = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "CPU architecture");
+
+ if (cpuArch != NULL) {
+ char* end;
+ long archNumber;
+ int hasARMv7 = 0;
+
+ D("found cpuArch = '%s'\n", cpuArch);
+
+ /* read the initial decimal number, ignore the rest */
+ archNumber = strtol(cpuArch, &end, 10);
+
+ /* Here we assume that ARMv8 will be upwards compatible with v7
+ * in the future. Unfortunately, there is no 'Features' field to
+ * indicate that Thumb-2 is supported.
+ */
+ if (end > cpuArch && archNumber >= 7) {
+ hasARMv7 = 1;
+ }
+
+ /* Unfortunately, it seems that certain ARMv6-based CPUs
+ * report an incorrect architecture number of 7!
+ *
+ * See http://code.google.com/p/android/issues/detail?id=10812
+ *
+ * We try to correct this by looking at the 'elf_format'
+ * field reported by the 'Processor' field, which is of the
+ * form of "(v7l)" for an ARMv7-based CPU, and "(v6l)" for
+ * an ARMv6-one.
+ */
+ if (hasARMv7) {
+ char* cpuProc = extract_cpuinfo_field(cpuinfo, cpuinfo_len,
+ "Processor");
+ if (cpuProc != NULL) {
+ D("found cpuProc = '%s'\n", cpuProc);
+ if (has_list_item(cpuProc, "(v6l)")) {
+ D("CPU processor and architecture mismatch!!\n");
+ hasARMv7 = 0;
+ }
+ free(cpuProc);
+ }
+ }
+
+ if (hasARMv7) {
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_ARMv7;
+ }
+
+ /* The LDREX / STREX instructions are available from ARMv6 */
+ if (archNumber >= 6) {
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_LDREX_STREX;
+ }
+
+ free(cpuArch);
+ }
+
+ /* Extract the list of CPU features from 'Features' field */
+ char* cpuFeatures = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "Features");
+
+ if (cpuFeatures != NULL) {
+
+ D("found cpuFeatures = '%s'\n", cpuFeatures);
+
+ if (has_list_item(cpuFeatures, "vfpv3"))
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
+
+ else if (has_list_item(cpuFeatures, "vfpv3d16"))
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
+
+ if (has_list_item(cpuFeatures, "neon")) {
+ /* Note: Certain kernels only report neon but not vfpv3
+ * in their features list. However, ARM mandates
+ * that if Neon is implemented, so must be VFPv3
+ * so always set the flag.
+ */
+ g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON |
+ ANDROID_CPU_ARM_FEATURE_VFPv3;
+ }
+ free(cpuFeatures);
+ }
+ }
+#endif /* __ARM_ARCH__ */
+
+#ifdef __i386__
+ g_cpuFamily = ANDROID_CPU_FAMILY_X86;
+
+ int regs[4];
+
+/* According to http://en.wikipedia.org/wiki/CPUID */
+#define VENDOR_INTEL_b 0x756e6547
+#define VENDOR_INTEL_c 0x6c65746e
+#define VENDOR_INTEL_d 0x49656e69
+
+ x86_cpuid(0, regs);
+ int vendorIsIntel = (regs[1] == VENDOR_INTEL_b &&
+ regs[2] == VENDOR_INTEL_c &&
+ regs[3] == VENDOR_INTEL_d);
+
+ x86_cpuid(1, regs);
+ if ((regs[2] & (1 << 9)) != 0) {
+ g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSSE3;
+ }
+ if ((regs[2] & (1 << 23)) != 0) {
+ g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_POPCNT;
+ }
+ if (vendorIsIntel && (regs[2] & (1 << 22)) != 0) {
+ g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_MOVBE;
+ }
+#endif
+}
+
+
+AndroidCpuFamily
+android_getCpuFamily(void)
+{
+ pthread_once(&g_once, android_cpuInit);
+ return g_cpuFamily;
+}
+
+
+uint64_t
+android_getCpuFeatures(void)
+{
+ pthread_once(&g_once, android_cpuInit);
+ return g_cpuFeatures;
+}
+
+
+int
+android_getCpuCount(void)
+{
+ pthread_once(&g_once, android_cpuInit);
+ return g_cpuCount;
+}
diff --git a/src/system_wrappers/source/android/cpu-features.h b/src/system_wrappers/source/android/cpu-features.h
new file mode 100644
index 0000000000..f20c0bc4d9
--- /dev/null
+++ b/src/system_wrappers/source/android/cpu-features.h
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+// You can download Android source at
+// http://source.android.com/source/downloading.html
+// Original files are in ndk/sources/android/cpufeatures
+// Revision is Change-Id: I9a0629efba36a6023f05e5f092e7addcc1b7d2a9
+
+#ifndef CPU_FEATURES_H
+#define CPU_FEATURES_H
+
+#include <sys/cdefs.h>
+#include <stdint.h>
+
+__BEGIN_DECLS
+
+typedef enum {
+ ANDROID_CPU_FAMILY_UNKNOWN = 0,
+ ANDROID_CPU_FAMILY_ARM,
+ ANDROID_CPU_FAMILY_X86,
+
+ ANDROID_CPU_FAMILY_MAX /* do not remove */
+
+} AndroidCpuFamily;
+
+/* Return family of the device's CPU */
+extern AndroidCpuFamily android_getCpuFamily(void);
+
+enum {
+ ANDROID_CPU_ARM_FEATURE_ARMv7 = (1 << 0),
+ ANDROID_CPU_ARM_FEATURE_VFPv3 = (1 << 1),
+ ANDROID_CPU_ARM_FEATURE_NEON = (1 << 2),
+ ANDROID_CPU_ARM_FEATURE_LDREX_STREX = (1 << 3),
+};
+
+enum {
+ ANDROID_CPU_X86_FEATURE_SSSE3 = (1 << 0),
+ ANDROID_CPU_X86_FEATURE_POPCNT = (1 << 1),
+ ANDROID_CPU_X86_FEATURE_MOVBE = (1 << 2),
+};
+
+extern uint64_t android_getCpuFeatures(void);
+
+/* Return the number of CPU cores detected on this device. */
+extern int android_getCpuCount(void);
+
+__END_DECLS
+
+#endif /* CPU_FEATURES_H */
diff --git a/src/system_wrappers/source/atomic32.cc b/src/system_wrappers/source/atomic32.cc
deleted file mode 100644
index 588dd3e07d..0000000000
--- a/src/system_wrappers/source/atomic32.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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 "atomic32_wrapper.h"
-
-#if defined(_WIN32)
- #include "atomic32_win.h"
-#elif defined(WEBRTC_LINUX)
- #include "atomic32_linux.h"
-#elif defined(WEBRTC_MAC)
- #include "atomic32_mac.h"
-#else
- #error unsupported os!
-#endif
-
-namespace webrtc {
-Atomic32Wrapper::Atomic32Wrapper(WebRtc_Word32 initialValue)
- : _impl(*new Atomic32Impl(initialValue))
-{
-}
-
-Atomic32Wrapper::~Atomic32Wrapper()
-{
- delete &_impl;
-}
-
-WebRtc_Word32 Atomic32Wrapper::operator++()
-{
- return ++_impl;
-}
-
-WebRtc_Word32 Atomic32Wrapper::operator--()
-{
- return --_impl;
-}
-
-// Read and write to properly aligned variables are atomic operations.
-// Ex reference (for Windows): http://msdn.microsoft.com/en-us/library/ms684122(v=VS.85).aspx
-// TODO (hellner) operator= and Atomic32Wrapper::Value() can be fully
-// implemented here.
-Atomic32Wrapper& Atomic32Wrapper::operator=(const Atomic32Wrapper& rhs)
-{
- if(this == &rhs)
- {
- return *this;
- }
- _impl = rhs._impl;
- return *this;
-}
-
-Atomic32Wrapper& Atomic32Wrapper::operator=(WebRtc_Word32 rhs)
-{
- _impl = rhs;
- return *this;
-}
-
-WebRtc_Word32 Atomic32Wrapper::operator+=(WebRtc_Word32 rhs)
-{
- return _impl += rhs;
-}
-
-WebRtc_Word32 Atomic32Wrapper::operator-=(WebRtc_Word32 rhs)
-{
- return _impl -= rhs;
-}
-
-bool Atomic32Wrapper::CompareExchange(WebRtc_Word32 newValue,
- WebRtc_Word32 compareValue)
-{
- return _impl.CompareExchange(newValue,compareValue);
-}
-
-WebRtc_Word32 Atomic32Wrapper::Value() const
-{
- return _impl.Value();
-}
-} // namespace webrtc
diff --git a/src/system_wrappers/source/atomic32_linux.h b/src/system_wrappers/source/atomic32_linux.h
deleted file mode 100644
index f9f5650f2a..0000000000
--- a/src/system_wrappers/source/atomic32_linux.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * 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.
- */
-
-// Atomic system independant 32-bit signed integer.
-// Linux implementation.
-// Note: Requires gcc 4.1.2 or later.
-#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_LINUX_H_
-#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_LINUX_H_
-
-#include <inttypes.h>
-#include <malloc.h>
-
-#include "common_types.h"
-
-namespace webrtc {
-class Atomic32Impl
-{
-public:
- inline Atomic32Impl(WebRtc_Word32 initialValue);
- inline ~Atomic32Impl();
-
- inline WebRtc_Word32 operator++();
- inline WebRtc_Word32 operator--();
-
- inline Atomic32Impl& operator=(const Atomic32Impl& rhs);
- inline Atomic32Impl& operator=(WebRtc_Word32 rhs);
- inline WebRtc_Word32 operator+=(WebRtc_Word32 rhs);
- inline WebRtc_Word32 operator-=(WebRtc_Word32 rhs);
-
- inline bool CompareExchange(WebRtc_Word32 newValue,
- WebRtc_Word32 compareValue);
-
- inline WebRtc_Word32 Value() const;
-private:
- void* _ptrMemory;
- // Volatile ensures full memory barriers.
- volatile WebRtc_Word32* _value;
-};
-
-// TODO (hellner) use aligned_malloc instead of doing it manually.
-inline Atomic32Impl::Atomic32Impl(WebRtc_Word32 initialValue)
- : _ptrMemory(NULL),
- _value(NULL)
-{ // Align the memory associated with _value on a 32-bit boundary. This is a
- // requirement for the used Linux APIs to be atomic.
- // Keep _ptrMemory to be able to reclaim memory.
- _ptrMemory = malloc(sizeof(WebRtc_Word32)*2);
- _value = (WebRtc_Word32*) (((uintptr_t)_ptrMemory+3)&(~0x3));
- *_value = initialValue;
-}
-
-inline Atomic32Impl::~Atomic32Impl()
-{
- if(_ptrMemory != NULL)
- {
- free(_ptrMemory);
- }
-}
-
-inline WebRtc_Word32 Atomic32Impl::operator++()
-{
- WebRtc_Word32 returnValue = __sync_fetch_and_add(_value,1);
- returnValue++;
- return returnValue;
-}
-
-inline WebRtc_Word32 Atomic32Impl::operator--()
-{
- WebRtc_Word32 returnValue = __sync_fetch_and_sub(_value,1);
- returnValue--;
- return returnValue;
-}
-
-inline Atomic32Impl& Atomic32Impl::operator=(const Atomic32Impl& rhs)
-{
- *_value = *rhs._value;
- return *this;
-}
-
-inline Atomic32Impl& Atomic32Impl::operator=(WebRtc_Word32 rhs)
-{
- *_value = rhs;
- return *this;
-}
-
-inline WebRtc_Word32 Atomic32Impl::operator+=(WebRtc_Word32 rhs)
-{
- WebRtc_Word32 returnValue = __sync_fetch_and_add(_value,rhs);
- returnValue += rhs;
- return returnValue;
-}
-
-inline WebRtc_Word32 Atomic32Impl::operator-=(WebRtc_Word32 rhs)
-{
- WebRtc_Word32 returnValue = __sync_fetch_and_sub(_value,rhs);
- returnValue -= rhs;
- return returnValue;
-}
-
-inline bool Atomic32Impl::CompareExchange(WebRtc_Word32 newValue,
- WebRtc_Word32 compareValue)
-{
- return __sync_bool_compare_and_swap(_value,compareValue,newValue);
-}
-
-inline WebRtc_Word32 Atomic32Impl::Value() const
-{
- return *_value;
-}
-} // namespace webrtc
-
-#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_LINUX_H_
diff --git a/src/system_wrappers/source/atomic32_mac.cc b/src/system_wrappers/source/atomic32_mac.cc
new file mode 100644
index 0000000000..9a493b580c
--- /dev/null
+++ b/src/system_wrappers/source/atomic32_mac.cc
@@ -0,0 +1,60 @@
+/*
+ * 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 "atomic32.h"
+
+#include <assert.h>
+#include <libkern/OSAtomic.h>
+#include <stdlib.h>
+
+#include "common_types.h"
+
+namespace webrtc {
+
+Atomic32::Atomic32(WebRtc_Word32 initialValue) : _value(initialValue)
+{
+ assert(Is32bitAligned());
+}
+
+Atomic32::~Atomic32()
+{
+}
+
+WebRtc_Word32 Atomic32::operator++()
+{
+ return OSAtomicIncrement32Barrier(&_value);
+}
+
+WebRtc_Word32 Atomic32::operator--()
+{
+ return OSAtomicDecrement32Barrier(&_value);
+}
+
+WebRtc_Word32 Atomic32::operator+=(WebRtc_Word32 value)
+{
+ return OSAtomicAdd32Barrier(value, &_value);
+}
+
+WebRtc_Word32 Atomic32::operator-=(WebRtc_Word32 value)
+{
+ return OSAtomicAdd32Barrier(-value, &_value);
+}
+
+bool Atomic32::CompareExchange(WebRtc_Word32 newValue,
+ WebRtc_Word32 compareValue)
+{
+ return OSAtomicCompareAndSwap32Barrier(compareValue, newValue, &_value);
+}
+
+WebRtc_Word32 Atomic32::Value() const
+{
+ return _value;
+}
+} // namespace webrtc
diff --git a/src/system_wrappers/source/atomic32_mac.h b/src/system_wrappers/source/atomic32_mac.h
deleted file mode 100644
index bf8febcdb5..0000000000
--- a/src/system_wrappers/source/atomic32_mac.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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.
- */
-
-// Atomic system independant 32-bit signed integer.
-// Mac implementation.
-#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_MAC_H_
-#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_MAC_H_
-
-#include <stdlib.h>
-#include <libkern/OSAtomic.h>
-
-#include "common_types.h"
-
-namespace webrtc {
-class Atomic32Impl
-{
-public:
- inline Atomic32Impl(WebRtc_Word32 initialValue);
- inline ~Atomic32Impl();
-
- inline WebRtc_Word32 operator++();
- inline WebRtc_Word32 operator--();
-
- inline Atomic32Impl& operator=(const Atomic32Impl& rhs);
- inline Atomic32Impl& operator=(WebRtc_Word32 rhs);
- inline WebRtc_Word32 operator+=(WebRtc_Word32 rhs);
- inline WebRtc_Word32 operator-=(WebRtc_Word32 rhs);
-
- inline bool CompareExchange(WebRtc_Word32 newValue,
- WebRtc_Word32 compareValue);
-
- inline WebRtc_Word32 Value() const;
-private:
- void* _ptrMemory;
- // Volatile ensures full memory barriers.
- volatile WebRtc_Word32* _value;
-};
-
-// TODO (hellner) use aligned_malloc instead of doing it manually.
-inline Atomic32Impl::Atomic32Impl(WebRtc_Word32 initialValue)
- :
- _ptrMemory(NULL),
- _value(NULL)
-{ // Align the memory associated with _value on a 32-bit boundary. This is a
- // requirement for the used Mac APIs to be atomic.
- // Keep _ptrMemory to be able to reclaim memory.
- _ptrMemory = malloc(sizeof(WebRtc_Word32)*2);
- _value = (WebRtc_Word32*) (((uintptr_t)_ptrMemory+3)&(~0x3));
- *_value = initialValue;
-}
-
-inline Atomic32Impl::~Atomic32Impl()
-{
- if(_ptrMemory != NULL)
- {
- free(_ptrMemory);
- }
-}
-
-inline WebRtc_Word32 Atomic32Impl::operator++()
-{
- return OSAtomicIncrement32Barrier(
- reinterpret_cast<volatile int32_t*>(_value));
-}
-
-inline WebRtc_Word32 Atomic32Impl::operator--()
-{
- return OSAtomicDecrement32Barrier(
- reinterpret_cast<volatile int32_t*>(_value));
-}
-
-inline Atomic32Impl& Atomic32Impl::operator=(const Atomic32Impl& rhs)
-{
- *_value = *rhs._value;
- return *this;
-}
-
-inline Atomic32Impl& Atomic32Impl::operator=(WebRtc_Word32 rhs)
-{
- *_value = rhs;
- return *this;
-}
-
-inline WebRtc_Word32 Atomic32Impl::operator+=(WebRtc_Word32 rhs)
-{
- return OSAtomicAdd32Barrier(rhs,
- reinterpret_cast<volatile int32_t*>(_value));
-}
-
-inline WebRtc_Word32 Atomic32Impl::operator-=(WebRtc_Word32 rhs)
-{
- return OSAtomicAdd32Barrier(-rhs,
- reinterpret_cast<volatile int32_t*>(_value));
-}
-
-inline bool Atomic32Impl::CompareExchange(WebRtc_Word32 newValue,
- WebRtc_Word32 compareValue)
-{
- return OSAtomicCompareAndSwap32Barrier(
- compareValue,
- newValue,
- reinterpret_cast<volatile int32_t*>(_value));
-}
-
-inline WebRtc_Word32 Atomic32Impl::Value() const
-{
- return *_value;
-}
-} // namespace webrtc
-#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_ATOMIC32_MAC_H_
diff --git a/src/system_wrappers/source/atomic32_posix.cc b/src/system_wrappers/source/atomic32_posix.cc
new file mode 100644
index 0000000000..05b0e57456
--- /dev/null
+++ b/src/system_wrappers/source/atomic32_posix.cc
@@ -0,0 +1,64 @@
+/*
+ * 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 "atomic32.h"
+
+#include <assert.h>
+#include <inttypes.h>
+#include <malloc.h>
+
+#include "common_types.h"
+
+namespace webrtc {
+
+Atomic32::Atomic32(WebRtc_Word32 initialValue) : _value(initialValue)
+{
+ assert(Is32bitAligned());
+}
+
+Atomic32::~Atomic32()
+{
+}
+
+WebRtc_Word32 Atomic32::operator++()
+{
+ return __sync_fetch_and_add(&_value, 1) + 1;
+}
+
+WebRtc_Word32 Atomic32::operator--()
+{
+ return __sync_fetch_and_sub(&_value, 1) - 1;
+}
+
+WebRtc_Word32 Atomic32::operator+=(WebRtc_Word32 value)
+{
+ WebRtc_Word32 returnValue = __sync_fetch_and_add(&_value, value);
+ returnValue += value;
+ return returnValue;
+}
+
+WebRtc_Word32 Atomic32::operator-=(WebRtc_Word32 value)
+{
+ WebRtc_Word32 returnValue = __sync_fetch_and_sub(&_value, value);
+ returnValue -= value;
+ return returnValue;
+}
+
+bool Atomic32::CompareExchange(WebRtc_Word32 newValue,
+ WebRtc_Word32 compareValue)
+{
+ return __sync_bool_compare_and_swap(&_value, compareValue, newValue);
+}
+
+WebRtc_Word32 Atomic32::Value() const
+{
+ return _value;
+}
+} // namespace webrtc
diff --git a/src/system_wrappers/source/atomic32_win.cc b/src/system_wrappers/source/atomic32_win.cc
new file mode 100644
index 0000000000..2fa9d3dd59
--- /dev/null
+++ b/src/system_wrappers/source/atomic32_win.cc
@@ -0,0 +1,72 @@
+/*
+ * 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 "atomic32.h"
+
+#include <assert.h>
+#include <windows.h>
+
+#include "common_types.h"
+#include "compile_assert.h"
+
+namespace webrtc {
+
+Atomic32::Atomic32(WebRtc_Word32 initialValue) : _value(initialValue)
+{
+ // Make sure that the counter variable we're using is of the same size
+ // as what the API expects.
+ COMPILE_ASSERT(sizeof(_value) == sizeof(LONG));
+ assert(Is32bitAligned());
+}
+
+Atomic32::~Atomic32()
+{
+}
+
+WebRtc_Word32 Atomic32::operator++()
+{
+ return static_cast<WebRtc_Word32>(InterlockedIncrement(
+ reinterpret_cast<volatile LONG*>(&_value)));
+}
+
+WebRtc_Word32 Atomic32::operator--()
+{
+ return static_cast<WebRtc_Word32>(InterlockedDecrement(
+ reinterpret_cast<volatile LONG*>(&_value)));
+}
+
+WebRtc_Word32 Atomic32::operator+=(WebRtc_Word32 value)
+{
+ return InterlockedExchangeAdd(reinterpret_cast<volatile LONG*>(&_value),
+ value);
+}
+
+WebRtc_Word32 Atomic32::operator-=(WebRtc_Word32 value)
+{
+ return InterlockedExchangeAdd(reinterpret_cast<volatile LONG*>(&_value),
+ -value);
+}
+
+bool Atomic32::CompareExchange(WebRtc_Word32 newValue,
+ WebRtc_Word32 compareValue)
+{
+ const LONG oldValue = InterlockedCompareExchange(
+ reinterpret_cast<volatile LONG*>(&_value),
+ newValue,
+ compareValue);
+ // If the old value and the compare value is the same an exchange happened.
+ return (oldValue == compareValue);
+}
+
+WebRtc_Word32 Atomic32::Value() const
+{
+ return _value;
+}
+} // namespace webrtc
diff --git a/src/system_wrappers/source/condition_variable_unittest.cc b/src/system_wrappers/source/condition_variable_unittest.cc
new file mode 100644
index 0000000000..a9fdd0d24e
--- /dev/null
+++ b/src/system_wrappers/source/condition_variable_unittest.cc
@@ -0,0 +1,208 @@
+/*
+ * 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/condition_variable_wrapper.h"
+
+#include "gtest/gtest.h"
+#include "system_wrappers/interface/critical_section_wrapper.h"
+#include "system_wrappers/interface/thread_wrapper.h"
+#include "system_wrappers/interface/trace.h"
+#include "system_wrappers/source/unittest_utilities.h"
+
+namespace webrtc {
+
+namespace {
+
+const int kLogTrace = false; // Set to true to enable debug logging to stdout.
+const int kLongWaitMs = 100*1000; // A long time in testing terms
+const int kShortWaitMs = 2*1000; // Long enough for process switches to happen
+
+#define LOG(...) WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, __VA_ARGS__);
+
+// A Baton is one possible control structure one can build using
+// conditional variables.
+// A Baton is always held by one and only one active thread - unlike
+// a lock, it can never be free.
+// One can pass it or grab it - both calls have timeouts.
+// Note - a production tool would guard against passing it without
+// grabbing it first. This one is for testing, so it doesn't.
+class Baton {
+ public:
+ Baton()
+ : giver_sect_(CriticalSectionWrapper::CreateCriticalSection()),
+ crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
+ cond_var_(ConditionVariableWrapper::CreateConditionVariable()),
+ being_passed_(false),
+ pass_count_(0) {
+ }
+
+ ~Baton() {
+ delete giver_sect_;
+ delete crit_sect_;
+ delete cond_var_;
+ }
+
+ // Pass the baton. Returns false if baton is not picked up in |max_msecs|.
+ // Only one process can pass at the same time; this property is
+ // ensured by the |giver_sect_| lock.
+ bool Pass(WebRtc_UWord32 max_msecs) {
+ LOG("Locking giver_sect");
+ CriticalSectionScoped cs_giver(giver_sect_);
+ LOG("Locked giver_sect, locking crit_sect");
+ CriticalSectionScoped cs(crit_sect_);
+ SignalBatonAvailable();
+ const bool result = TakeBatonIfStillFree(max_msecs);
+ if (result) {
+ ++pass_count_;
+ LOG("Pass count is %d", pass_count_);
+ }
+ return result;
+ }
+
+ // Grab the baton. Returns false if baton is not passed.
+ bool Grab(WebRtc_UWord32 max_msecs) {
+ CriticalSectionScoped cs(crit_sect_);
+ return WaitUntilBatonOffered(max_msecs);
+ }
+
+ int PassCount() {
+ // We don't allow polling PassCount() during a Pass()-call since there is
+ // no guarantee that |pass_count_| is incremented until the Pass()-call
+ // finishes. I.e. the Grab()-call may finish before |pass_count_| has been
+ // incremented.
+ // Thus, this function waits on giver_sect_.
+ CriticalSectionScoped cs(giver_sect_);
+ return pass_count_;
+ }
+
+ private:
+ // Wait/Signal forms a classical semaphore on |being_passed_|.
+ // These functions must be called with crit_sect_ held.
+ bool WaitUntilBatonOffered(int timeout_ms) {
+ while (!being_passed_) {
+ LOG("Wait waiting");
+ if (!cond_var_->SleepCS(*crit_sect_, timeout_ms)) {
+ LOG("Wait timeout");
+ return false;
+ }
+ }
+ being_passed_ = false;
+ cond_var_->Wake();
+ return true;
+ }
+
+ void SignalBatonAvailable() {
+ assert(!being_passed_);
+ being_passed_ = true;
+ LOG("Signal waking");
+ cond_var_->Wake();
+ }
+
+ // Timeout extension: Wait for a limited time for someone else to
+ // take it, and take it if it's not taken.
+ // Returns true if resource is taken by someone else, false
+ // if it is taken back by the caller.
+ // This function must be called with both |giver_sect_| and
+ // |crit_sect_| held.
+ bool TakeBatonIfStillFree(int timeout_ms) {
+ bool not_timeout = true;
+ while (being_passed_ && not_timeout) {
+ LOG("Takeback waiting");
+ not_timeout = cond_var_->SleepCS(*crit_sect_, timeout_ms);
+ // If we're woken up while variable is still held, we may have
+ // gotten a wakeup destined for a grabber thread.
+ // This situation is not treated specially here.
+ }
+ if (!being_passed_) {
+ return true;
+ } else {
+ LOG("Takeback grab");
+ assert(!not_timeout);
+ being_passed_ = false;
+ return false;
+ }
+ }
+
+ // Lock that ensures that there is only one thread in the active
+ // part of Pass() at a time.
+ // |giver_sect_| must always be acquired before |cond_var_|.
+ CriticalSectionWrapper* giver_sect_;
+ // Lock that protects |being_passed_|.
+ CriticalSectionWrapper* crit_sect_;
+ ConditionVariableWrapper* cond_var_;
+ bool being_passed_;
+ // Statistics information: Number of successfull passes.
+ int pass_count_;
+};
+
+// Function that waits on a Baton, and passes it right back.
+// We expect these calls never to time out.
+bool WaitingRunFunction(void* obj) {
+ Baton* the_baton = static_cast<Baton*> (obj);
+ LOG("Thread waiting");
+ EXPECT_TRUE(the_baton->Grab(kLongWaitMs));
+ LOG("Thread waking parent");
+ EXPECT_TRUE(the_baton->Pass(kLongWaitMs));
+ return true;
+}
+
+class CondVarTest : public ::testing::Test {
+ public:
+ CondVarTest()
+ : trace_(kLogTrace) {
+ }
+
+ virtual void SetUp() {
+ thread_ = ThreadWrapper::CreateThread(&WaitingRunFunction,
+ &baton_);
+ unsigned int id = 42;
+ ASSERT_TRUE(thread_->Start(id));
+ }
+
+ virtual void TearDown() {
+ // We have to wake the thread in order to make it obey the stop order.
+ // But we don't know if the thread has completed the run function, so
+ // we don't know if it will exit before or after the Pass.
+ // Thus, we need to pin it down inside its Run function (between Grab
+ // and Pass).
+ ASSERT_TRUE(baton_.Pass(kShortWaitMs));
+ thread_->SetNotAlive();
+ ASSERT_TRUE(baton_.Grab(kShortWaitMs));
+ ASSERT_TRUE(thread_->Stop());
+ delete thread_;
+ }
+
+ protected:
+ Baton baton_;
+
+ private:
+ ScopedTracing trace_;
+ ThreadWrapper* thread_;
+};
+
+// The SetUp and TearDown functions use condition variables.
+// This test verifies those pieces in isolation.
+TEST_F(CondVarTest, InitFunctionsWork) {
+ // All relevant asserts are in the SetUp and TearDown functions.
+}
+
+// This test verifies that one can use the baton multiple times.
+TEST_F(CondVarTest, PassBatonMultipleTimes) {
+ const int kNumberOfRounds = 2;
+ for (int i = 0; i < kNumberOfRounds; ++i) {
+ ASSERT_TRUE(baton_.Pass(kShortWaitMs));
+ ASSERT_TRUE(baton_.Grab(kShortWaitMs));
+ }
+ EXPECT_EQ(2*kNumberOfRounds, baton_.PassCount());
+}
+
+} // anonymous namespace
+
+} // namespace webrtc
diff --git a/src/system_wrappers/source/condition_variable_win.cc b/src/system_wrappers/source/condition_variable_win.cc
new file mode 100644
index 0000000000..f4fae0b75f
--- /dev/null
+++ b/src/system_wrappers/source/condition_variable_win.cc
@@ -0,0 +1,224 @@
+/*
+ * Use of this source code is governed by the ACE copyright license which
+ * can be found in the LICENSE file in the third_party_mods/ace directory of
+ * the source tree or at http://www1.cse.wustl.edu/~schmidt/ACE-copying.html.
+ */
+/*
+ * This source code contain modifications to the original source code
+ * which can be found here:
+ * http://www.cs.wustl.edu/~schmidt/win32-cv-1.html (section 3.2).
+ * Modifications:
+ * 1) Dynamic detection of native support for condition variables.
+ * 2) Use of WebRTC defined types and classes. Renaming of some functions.
+ * 3) Introduction of a second event for wake all functionality. This prevents
+ * a thread from spinning on the same condition variable, preventing other
+ * threads from waking up.
+ */
+
+// TODO (hellner): probably nicer to split up native and generic
+// implementation into two different files
+
+#include "condition_variable_win.h"
+
+#include "critical_section_win.h"
+#include "trace.h"
+
+namespace webrtc {
+bool ConditionVariableWindows::_winSupportConditionVariablesPrimitive = false;
+static HMODULE library = NULL;
+
+PInitializeConditionVariable _PInitializeConditionVariable;
+PSleepConditionVariableCS _PSleepConditionVariableCS;
+PWakeConditionVariable _PWakeConditionVariable;
+PWakeAllConditionVariable _PWakeAllConditionVariable;
+
+typedef void (WINAPI *PInitializeConditionVariable)(PCONDITION_VARIABLE);
+typedef BOOL (WINAPI *PSleepConditionVariableCS)(PCONDITION_VARIABLE,
+ PCRITICAL_SECTION, DWORD);
+typedef void (WINAPI *PWakeConditionVariable)(PCONDITION_VARIABLE);
+typedef void (WINAPI *PWakeAllConditionVariable)(PCONDITION_VARIABLE);
+
+ConditionVariableWindows::ConditionVariableWindows()
+ : _eventID(WAKEALL_0)
+{
+ if (!library)
+ {
+ // Use native implementation if supported (i.e Vista+)
+ library = LoadLibrary(TEXT("Kernel32.dll"));
+ if (library)
+ {
+ WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
+ "Loaded Kernel.dll");
+
+ _PInitializeConditionVariable =
+ (PInitializeConditionVariable) GetProcAddress(
+ library,
+ "InitializeConditionVariable");
+ _PSleepConditionVariableCS =
+ (PSleepConditionVariableCS)GetProcAddress(
+ library,
+ "SleepConditionVariableCS");
+ _PWakeConditionVariable =
+ (PWakeConditionVariable)GetProcAddress(
+ library,
+ "WakeConditionVariable");
+ _PWakeAllConditionVariable =
+ (PWakeAllConditionVariable)GetProcAddress(
+ library,
+ "WakeAllConditionVariable");
+
+ if(_PInitializeConditionVariable &&
+ _PSleepConditionVariableCS &&
+ _PWakeConditionVariable &&
+ _PWakeAllConditionVariable)
+ {
+ WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
+ "Loaded native condition variables");
+ _winSupportConditionVariablesPrimitive = true;
+ }
+ }
+ }
+
+ if (_winSupportConditionVariablesPrimitive)
+ {
+ _PInitializeConditionVariable(&_conditionVariable);
+
+ _events[WAKEALL_0] = NULL;
+ _events[WAKEALL_1] = NULL;
+ _events[WAKE] = NULL;
+
+ } else {
+ memset(&_numWaiters[0],0,sizeof(_numWaiters));
+
+ InitializeCriticalSection(&_numWaitersCritSect);
+
+ _events[WAKEALL_0] = CreateEvent(NULL, // no security attributes
+ TRUE, // manual-reset, sticky event
+ FALSE, // initial state non-signaled
+ NULL); // no name for event
+
+ _events[WAKEALL_1] = CreateEvent(NULL, // no security attributes
+ TRUE, // manual-reset, sticky event
+ FALSE, // initial state non-signaled
+ NULL); // no name for event
+
+ _events[WAKE] = CreateEvent(NULL, // no security attributes
+ FALSE, // auto-reset, sticky event
+ FALSE, // initial state non-signaled
+ NULL); // no name for event
+ }
+}
+
+ConditionVariableWindows::~ConditionVariableWindows()
+{
+ if(!_winSupportConditionVariablesPrimitive)
+ {
+ CloseHandle(_events[WAKE]);
+ CloseHandle(_events[WAKEALL_1]);
+ CloseHandle(_events[WAKEALL_0]);
+
+ DeleteCriticalSection(&_numWaitersCritSect);
+ }
+}
+
+void ConditionVariableWindows::SleepCS(CriticalSectionWrapper& critSect)
+{
+ SleepCS(critSect, INFINITE);
+}
+
+bool ConditionVariableWindows::SleepCS(CriticalSectionWrapper& critSect,
+ unsigned long maxTimeInMS)
+{
+ CriticalSectionWindows* cs = reinterpret_cast<CriticalSectionWindows*>(
+ &critSect);
+
+ if(_winSupportConditionVariablesPrimitive)
+ {
+ BOOL retVal = _PSleepConditionVariableCS(&_conditionVariable,
+ &(cs->crit),maxTimeInMS);
+ return (retVal == 0) ? false : true;
+
+ }else
+ {
+ EnterCriticalSection(&_numWaitersCritSect);
+ // Get the eventID for the event that will be triggered by next
+ // WakeAll() call and start waiting for it.
+ const EventWakeUpType eventID = (WAKEALL_0 == _eventID) ?
+ WAKEALL_1 : WAKEALL_0;
+ ++(_numWaiters[eventID]);
+ LeaveCriticalSection(&_numWaitersCritSect);
+
+ LeaveCriticalSection(&cs->crit);
+ HANDLE events[2];
+ events[0] = _events[WAKE];
+ events[1] = _events[eventID];
+ const DWORD result = WaitForMultipleObjects(2, // Wait on 2 events.
+ events,
+ FALSE, // Wait for either.
+ maxTimeInMS);
+
+ const bool retVal = (result != WAIT_TIMEOUT);
+
+ EnterCriticalSection(&_numWaitersCritSect);
+ --(_numWaiters[eventID]);
+ // Last waiter should only be true for WakeAll(). WakeAll() correspond
+ // to position 1 in events[] -> (result == WAIT_OBJECT_0 + 1)
+ const bool lastWaiter = (result == WAIT_OBJECT_0 + 1) &&
+ (_numWaiters[eventID] == 0);
+ LeaveCriticalSection(&_numWaitersCritSect);
+
+ if (lastWaiter)
+ {
+ // Reset/unset the WakeAll() event since all threads have been
+ // released.
+ ResetEvent(_events[eventID]);
+ }
+
+ EnterCriticalSection(&cs->crit);
+ return retVal;
+ }
+}
+
+void
+ConditionVariableWindows::Wake()
+{
+ if(_winSupportConditionVariablesPrimitive)
+ {
+ _PWakeConditionVariable(&_conditionVariable);
+ }else
+ {
+ EnterCriticalSection(&_numWaitersCritSect);
+ const bool haveWaiters = (_numWaiters[WAKEALL_0] > 0) ||
+ (_numWaiters[WAKEALL_1] > 0);
+ LeaveCriticalSection(&_numWaitersCritSect);
+
+ if (haveWaiters)
+ {
+ SetEvent(_events[WAKE]);
+ }
+ }
+}
+
+void
+ConditionVariableWindows::WakeAll()
+{
+ if(_winSupportConditionVariablesPrimitive)
+ {
+ _PWakeAllConditionVariable(&_conditionVariable);
+ }else
+ {
+ EnterCriticalSection(&_numWaitersCritSect);
+ // Update current WakeAll() event
+ _eventID = (WAKEALL_0 == _eventID) ? WAKEALL_1 : WAKEALL_0;
+ // Trigger current event
+ const EventWakeUpType eventID = _eventID;
+ const bool haveWaiters = _numWaiters[eventID] > 0;
+ LeaveCriticalSection(&_numWaitersCritSect);
+
+ if (haveWaiters)
+ {
+ SetEvent(_events[eventID]);
+ }
+ }
+}
+} // namespace webrtc
diff --git a/src/system_wrappers/source/condition_variable_win.h b/src/system_wrappers/source/condition_variable_win.h
new file mode 100644
index 0000000000..aab2564dd1
--- /dev/null
+++ b/src/system_wrappers/source/condition_variable_win.h
@@ -0,0 +1,67 @@
+/*
+ * 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_CONDITION_VARIABLE_WINDOWS_H_
+#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_WINDOWS_H_
+
+#include "condition_variable_wrapper.h"
+
+#include <windows.h>
+
+namespace webrtc {
+#if !defined CONDITION_VARIABLE_INIT
+ typedef struct _RTL_CONDITION_VARIABLE
+ {
+ void* Ptr;
+ } RTL_CONDITION_VARIABLE, *PRTL_CONDITION_VARIABLE;
+
+ typedef RTL_CONDITION_VARIABLE CONDITION_VARIABLE, *PCONDITION_VARIABLE;
+#endif
+
+typedef void (WINAPI *PInitializeConditionVariable)(PCONDITION_VARIABLE);
+typedef BOOL (WINAPI *PSleepConditionVariableCS)(PCONDITION_VARIABLE,
+ PCRITICAL_SECTION, DWORD);
+typedef void (WINAPI *PWakeConditionVariable)(PCONDITION_VARIABLE);
+typedef void (WINAPI *PWakeAllConditionVariable)(PCONDITION_VARIABLE);
+
+
+class ConditionVariableWindows : public ConditionVariableWrapper
+{
+public:
+ ConditionVariableWindows();
+ ~ConditionVariableWindows();
+
+ void SleepCS(CriticalSectionWrapper& critSect);
+ bool SleepCS(CriticalSectionWrapper& critSect, unsigned long maxTimeInMS);
+ void Wake();
+ void WakeAll();
+
+private:
+ enum EventWakeUpType
+ {
+ WAKEALL_0 = 0,
+ WAKEALL_1 = 1,
+ WAKE = 2,
+ EVENT_COUNT = 3
+ };
+
+private:
+ // Native support for Windows Vista+
+ static bool _winSupportConditionVariablesPrimitive;
+ CONDITION_VARIABLE _conditionVariable;
+
+ unsigned int _numWaiters[2];
+ EventWakeUpType _eventID;
+ CRITICAL_SECTION _numWaitersCritSect;
+ HANDLE _events[EVENT_COUNT];
+};
+} // namespace webrtc
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_WINDOWS_H_
diff --git a/src/system_wrappers/source/cpu_features_android.c b/src/system_wrappers/source/cpu_features_android.c
new file mode 100644
index 0000000000..7a4fa6ef20
--- /dev/null
+++ b/src/system_wrappers/source/cpu_features_android.c
@@ -0,0 +1,15 @@
+/*
+ * 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 "android/cpu-features.h"
+
+uint64_t WebRtc_GetCPUFeaturesARM(void) {
+ return android_getCpuFeatures();
+}
diff --git a/src/system_wrappers/source/cpu_features_arm.c b/src/system_wrappers/source/cpu_features_arm.c
deleted file mode 100644
index 106511852c..0000000000
--- a/src/system_wrappers/source/cpu_features_arm.c
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * 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.
- */
-
-// This file is derived from Android's NDK package r7, located at
-// <ndk>/sources/android/cpufeatures/ (downloadable from
-// http://developer.android.com/sdk/ndk/index.html).
-
-#include "cpu_features_wrapper.h"
-
-#include <fcntl.h>
-#include <errno.h>
-#include <pthread.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-// Define CPU family.
-typedef enum {
- CPU_FAMILY_UNKNOWN = 0,
- CPU_FAMILY_ARM,
- CPU_FAMILY_X86,
- CPU_FAMILY_MAX // Do not remove.
-} CpuFamily;
-
-static pthread_once_t g_once;
-static CpuFamily g_cpuFamily;
-static uint64_t g_cpuFeatures;
-static int g_cpuCount;
-
-static const int cpufeatures_debug = 0;
-
-#ifdef __arm__
-# define DEFAULT_CPU_FAMILY CPU_FAMILY_ARM
-#elif defined __i386__
-# define DEFAULT_CPU_FAMILY CPU_FAMILY_X86
-#else
-# define DEFAULT_CPU_FAMILY CPU_FAMILY_UNKNOWN
-#endif
-
-#define D(...) \
- do { \
- if (cpufeatures_debug) { \
- printf(__VA_ARGS__); fflush(stdout); \
- } \
- } while (0)
-
-/* Read the content of /proc/cpuinfo into a user-provided buffer.
- * Return the length of the data, or -1 on error. Does *not*
- * zero-terminate the content. Will not read more
- * than 'buffsize' bytes.
- */
-static int read_file(const char* pathname, char* buffer, size_t buffsize) {
- int fd, len;
-
- fd = open(pathname, O_RDONLY);
- if (fd < 0)
- return -1;
-
- do {
- len = read(fd, buffer, buffsize);
- } while (len < 0 && errno == EINTR);
-
- close(fd);
-
- return len;
-}
-
-/* Extract the content of a the first occurence of a given field in
- * the content of /proc/cpuinfo and return it as a heap-allocated
- * string that must be freed by the caller.
- *
- * Return NULL if not found
- */
-static char* extract_cpuinfo_field(char* buffer, int buflen, const char* field) {
- int fieldlen = strlen(field);
- char* bufend = buffer + buflen;
- char* result = NULL;
- int len, ignore;
- const char* p, *q;
-
- /* Look for first field occurence, and ensures it starts the line.
- */
- p = buffer;
- bufend = buffer + buflen;
- for (;;) {
- p = memmem(p, bufend - p, field, fieldlen);
- if (p == NULL)
- goto EXIT;
-
- if (p == buffer || p[-1] == '\n')
- break;
-
- p += fieldlen;
- }
-
- /* Skip to the first column followed by a space */
- p += fieldlen;
- p = memchr(p, ':', bufend - p);
- if (p == NULL || p[1] != ' ')
- goto EXIT;
-
- /* Find the end of the line */
- p += 2;
- q = memchr(p, '\n', bufend - p);
- if (q == NULL)
- q = bufend;
-
- /* Copy the line into a heap-allocated buffer */
- len = q - p;
- result = malloc(len + 1);
- if (result == NULL)
- goto EXIT;
-
- memcpy(result, p, len);
- result[len] = '\0';
-
-EXIT:
- return result;
-}
-
-/* Count the number of occurences of a given field prefix in /proc/cpuinfo.
- */
-static int count_cpuinfo_field(char* buffer, int buflen, const char* field) {
- int fieldlen = strlen(field);
- const char* p = buffer;
- const char* bufend = buffer + buflen;
- const char* q;
- int count = 0;
-
- for (;;) {
- const char* q;
-
- p = memmem(p, bufend - p, field, fieldlen);
- if (p == NULL)
- break;
-
- /* Ensure that the field is at the start of a line */
- if (p > buffer && p[-1] != '\n') {
- p += fieldlen;
- continue;
- }
-
-
- /* skip any whitespace */
- q = p + fieldlen;
- while (q < bufend && (*q == ' ' || *q == '\t'))
- q++;
-
- /* we must have a colon now */
- if (q < bufend && *q == ':') {
- count += 1;
- q ++;
- }
- p = q;
- }
-
- return count;
-}
-
-/* Like strlen(), but for constant string literals */
-#define STRLEN_CONST(x) ((sizeof(x)-1)
-
-
-/* Checks that a space-separated list of items contains one given 'item'.
- * Returns 1 if found, 0 otherwise.
- */
-static int has_list_item(const char* list, const char* item) {
- const char* p = list;
- int itemlen = strlen(item);
-
- if (list == NULL)
- return 0;
-
- while (*p) {
- const char* q;
-
- /* skip spaces */
- while (*p == ' ' || *p == '\t')
- p++;
-
- /* find end of current list item */
- q = p;
- while (*q && *q != ' ' && *q != '\t')
- q++;
-
- if (itemlen == q - p && !memcmp(p, item, itemlen))
- return 1;
-
- /* skip to next item */
- p = q;
- }
- return 0;
-}
-
-
-static void cpuInit(void) {
- char cpuinfo[4096];
- int cpuinfo_len;
-
- g_cpuFamily = DEFAULT_CPU_FAMILY;
- g_cpuFeatures = 0;
- g_cpuCount = 1;
-
- cpuinfo_len = read_file("/proc/cpuinfo", cpuinfo, sizeof cpuinfo);
- D("cpuinfo_len is (%d):\n%.*s\n", cpuinfo_len,
- cpuinfo_len >= 0 ? cpuinfo_len : 0, cpuinfo);
-
- if (cpuinfo_len < 0) { /* should not happen */
- return;
- }
-
- /* Count the CPU cores, the value may be 0 for single-core CPUs */
- g_cpuCount = count_cpuinfo_field(cpuinfo, cpuinfo_len, "processor");
- if (g_cpuCount == 0) {
- g_cpuCount = count_cpuinfo_field(cpuinfo, cpuinfo_len, "Processor");
- if (g_cpuCount == 0) {
- g_cpuCount = 1;
- }
- }
-
- D("found cpuCount = %d\n", g_cpuCount);
-
-#ifdef __arm__
- {
- char* features = NULL;
- char* architecture = NULL;
-
- /* Extract architecture from the "CPU Architecture" field.
- * The list is well-known, unlike the the output of
- * the 'Processor' field which can vary greatly.
- *
- * See the definition of the 'proc_arch' array in
- * $KERNEL/arch/arm/kernel/setup.c and the 'c_show' function in
- * same file.
- */
- char* cpuArch = extract_cpuinfo_field(cpuinfo, cpuinfo_len,
- "CPU architecture");
-
- if (cpuArch != NULL) {
- char* end;
- long archNumber;
- int hasARMv7 = 0;
-
- D("found cpuArch = '%s'\n", cpuArch);
-
- /* read the initial decimal number, ignore the rest */
- archNumber = strtol(cpuArch, &end, 10);
-
- /* Here we assume that ARMv8 will be upwards compatible with v7
- * in the future. Unfortunately, there is no 'Features' field to
- * indicate that Thumb-2 is supported.
- */
- if (end > cpuArch && archNumber >= 7) {
- hasARMv7 = 1;
- }
-
- /* Unfortunately, it seems that certain ARMv6-based CPUs
- * report an incorrect architecture number of 7!
- *
- * We try to correct this by looking at the 'elf_format'
- * field reported by the 'Processor' field, which is of the
- * form of "(v7l)" for an ARMv7-based CPU, and "(v6l)" for
- * an ARMv6-one.
- */
- if (hasARMv7) {
- char* cpuProc = extract_cpuinfo_field(cpuinfo, cpuinfo_len,
- "Processor");
- if (cpuProc != NULL) {
- D("found cpuProc = '%s'\n", cpuProc);
- if (has_list_item(cpuProc, "(v6l)")) {
- D("CPU processor and architecture mismatch!!\n");
- hasARMv7 = 0;
- }
- free(cpuProc);
- }
- }
-
- if (hasARMv7) {
- g_cpuFeatures |= kCPUFeatureARMv7;
- }
-
- /* The LDREX / STREX instructions are available from ARMv6 */
- if (archNumber >= 6) {
- g_cpuFeatures |= kCPUFeatureLDREXSTREX;
- }
-
- free(cpuArch);
- }
-
- /* Extract the list of CPU features from 'Features' field */
- char* cpuFeatures = extract_cpuinfo_field(cpuinfo, cpuinfo_len,
- "Features");
-
- if (cpuFeatures != NULL) {
-
- D("found cpuFeatures = '%s'\n", cpuFeatures);
-
- if (has_list_item(cpuFeatures, "vfpv3"))
- g_cpuFeatures |= kCPUFeatureVFPv3;
-
- else if (has_list_item(cpuFeatures, "vfpv3d16"))
- g_cpuFeatures |= kCPUFeatureVFPv3;
-
- if (has_list_item(cpuFeatures, "neon")) {
- /* Note: Certain kernels only report neon but not vfpv3
- * in their features list. However, ARM mandates
- * that if Neon is implemented, so must be VFPv3
- * so always set the flag.
- */
- g_cpuFeatures |= kCPUFeatureNEON |
- kCPUFeatureVFPv3;
- }
- free(cpuFeatures);
- }
- }
-#endif // __arm__
-
-#ifdef __i386__
- g_cpuFamily = CPU_FAMILY_X86;
-#endif
-}
-
-
-uint64_t WebRtc_GetCPUFeaturesARM(void) {
- pthread_once(&g_once, cpuInit);
- return g_cpuFeatures;
-}
diff --git a/src/system_wrappers/source/cpu_linux.cc b/src/system_wrappers/source/cpu_linux.cc
index 9d7d89de64..8e8ecda6ca 100644
--- a/src/system_wrappers/source/cpu_linux.cc
+++ b/src/system_wrappers/source/cpu_linux.cc
@@ -179,6 +179,7 @@ int CpuLinux::GetNumCores()
char line[100];
if (!fgets(line, 100, fp))
{
+ fclose(fp);
return -1;
}
int numCores = -1;
diff --git a/src/system_wrappers/source/cpu_measurement_harness.cc b/src/system_wrappers/source/cpu_measurement_harness.cc
new file mode 100644
index 0000000000..237e776506
--- /dev/null
+++ b/src/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/src/system_wrappers/source/cpu_measurement_harness.h b/src/system_wrappers/source/cpu_measurement_harness.h
new file mode 100644
index 0000000000..3b87f2775b
--- /dev/null
+++ b/src/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/src/system_wrappers/source/cpu_win.cc b/src/system_wrappers/source/cpu_win.cc
new file mode 100644
index 0000000000..86a6a6ad38
--- /dev/null
+++ b/src/system_wrappers/source/cpu_win.cc
@@ -0,0 +1,530 @@
+/*
+ * 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 (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/src/system_wrappers/source/cpu_win.h b/src/system_wrappers/source/cpu_win.h
new file mode 100644
index 0000000000..d15073c0ba
--- /dev/null
+++ b/src/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/src/system_wrappers/source/cpu_wrapper_unittest.cc b/src/system_wrappers/source/cpu_wrapper_unittest.cc
index dd49c3ac94..cd149dc30f 100644
--- a/src/system_wrappers/source/cpu_wrapper_unittest.cc
+++ b/src/system_wrappers/source/cpu_wrapper_unittest.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -23,7 +23,14 @@ using webrtc::EventWrapper;
using webrtc::scoped_ptr;
using webrtc::Trace;
-TEST(CpuWrapperTest, Usage) {
+// 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";
@@ -42,7 +49,7 @@ TEST(CpuWrapperTest, Usage) {
// 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)) {
+ while (!cpu_usage_available && (++num_iterations < 10000)) {
if (cores != NULL) {
ASSERT_GT(num_cores, 0u);
break;
diff --git a/src/system_wrappers/source/critical_section_posix.cc b/src/system_wrappers/source/critical_section_posix.cc
index b499b9ffe2..70f85f9a68 100644
--- a/src/system_wrappers/source/critical_section_posix.cc
+++ b/src/system_wrappers/source/critical_section_posix.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -8,31 +8,39 @@
* be found in the AUTHORS file in the root of the source tree.
*/
+// General note: return values for the various pthread synchronization APIs
+// are explicitly ignored here. In Chromium, the same thing is done for release.
+// However, in debugging, failure in these APIs are logged. There is currently
+// no equivalent to DCHECK_EQ in WebRTC code so this is the best we can do here.
+// TODO(henrike): add logging when pthread synchronization APIs are failing.
+
#include "critical_section_posix.h"
namespace webrtc {
+
CriticalSectionPosix::CriticalSectionPosix()
{
pthread_mutexattr_t attr;
- pthread_mutexattr_init(&attr);
- pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
- pthread_mutex_init(&_mutex, &attr);
+ (void) pthread_mutexattr_init(&attr);
+ (void) pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+ (void) pthread_mutex_init(&_mutex, &attr);
}
CriticalSectionPosix::~CriticalSectionPosix()
{
- pthread_mutex_destroy(&_mutex);
+ (void) pthread_mutex_destroy(&_mutex);
}
void
CriticalSectionPosix::Enter()
{
- pthread_mutex_lock(&_mutex);
+ (void) pthread_mutex_lock(&_mutex);
}
void
CriticalSectionPosix::Leave()
{
- pthread_mutex_unlock(&_mutex);
+ (void) pthread_mutex_unlock(&_mutex);
}
+
} // namespace webrtc
diff --git a/src/system_wrappers/source/critical_section_unittest.cc b/src/system_wrappers/source/critical_section_unittest.cc
new file mode 100644
index 0000000000..c48b9f7515
--- /dev/null
+++ b/src/system_wrappers/source/critical_section_unittest.cc
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ */
+
+#ifdef _WIN32
+// For Sleep()
+#include <windows.h>
+#else
+// For nanosleep()
+#include <time.h>
+#endif
+
+#include "system_wrappers/interface/critical_section_wrapper.h"
+
+#include "gtest/gtest.h"
+#include "system_wrappers/interface/sleep.h"
+#include "system_wrappers/interface/thread_wrapper.h"
+#include "system_wrappers/interface/trace.h"
+#include "system_wrappers/source/unittest_utilities.h"
+
+namespace webrtc {
+
+namespace {
+
+const bool kLogTrace = false; // Set to true to enable debug logging to stdout.
+
+#define LOG(...) WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1, __VA_ARGS__);
+
+// Cause a process switch. Needed to avoid depending on
+// busy-wait in tests.
+static void SwitchProcess() {
+ // Note - sched_yield has been tried as process switch. This does
+ // not cause a process switch enough of the time for reliability.
+ SleepMs(1);
+}
+
+class ProtectedCount {
+ public:
+ explicit ProtectedCount(CriticalSectionWrapper* crit_sect)
+ : crit_sect_(crit_sect),
+ count_(0) {
+ }
+
+ void Increment() {
+ CriticalSectionScoped cs(crit_sect_);
+ ++count_;
+ LOG("Inc to %d", count_);
+ }
+
+ int Count() const {
+ CriticalSectionScoped cs(crit_sect_);
+ return count_;
+ }
+
+ private:
+ CriticalSectionWrapper* crit_sect_;
+ int count_;
+};
+
+class CritSectTest : public ::testing::Test {
+ public:
+ CritSectTest() : trace_(kLogTrace) {
+ }
+
+ // Waits a number of cycles for the count to reach a given value.
+ // Returns true if the target is reached or passed.
+ bool WaitForCount(int target, ProtectedCount* count) {
+ int loop_counter = 0;
+ // On Posix, this SwitchProcess() needs to be in a loop to make the
+ // test both fast and non-flaky.
+ // With 1 us wait as the switch, up to 7 rounds have been observed.
+ while (count->Count() < target && loop_counter < 100*target) {
+ ++loop_counter;
+ SwitchProcess();
+ }
+ LOG("Test looped %d times\n", loop_counter);
+ return (count->Count() >= target);
+ }
+
+ private:
+ ScopedTracing trace_;
+};
+
+bool LockUnlockThenStopRunFunction(void* obj) {
+ LOG("Wait starting");
+ ProtectedCount* the_count = static_cast<ProtectedCount*> (obj);
+ LOG("Wait incrementing");
+ the_count->Increment();
+ LOG("Wait returning");
+ return false;
+}
+
+TEST_F(CritSectTest, ThreadWakesOnce) {
+ CriticalSectionWrapper* crit_sect
+ = CriticalSectionWrapper::CreateCriticalSection();
+ ProtectedCount count(crit_sect);
+ ThreadWrapper* thread = ThreadWrapper::CreateThread(
+ &LockUnlockThenStopRunFunction, &count);
+ unsigned int id = 42;
+ crit_sect->Enter();
+ ASSERT_TRUE(thread->Start(id));
+ SwitchProcess();
+ // The critical section is of reentrant mode, so this should not release
+ // the lock, even though count.Count() locks and unlocks the critical section
+ // again.
+ // Thus, the thread should not be able to increment the count
+ ASSERT_EQ(0, count.Count());
+ crit_sect->Leave(); // This frees the thread to act.
+ EXPECT_TRUE(WaitForCount(1, &count));
+ EXPECT_TRUE(thread->Stop());
+ delete thread;
+ delete crit_sect;
+}
+
+bool LockUnlockRunFunction(void* obj) {
+ LOG("Wait starting");
+ ProtectedCount* the_count = static_cast<ProtectedCount*> (obj);
+ LOG("Wait incrementing");
+ the_count->Increment();
+ SwitchProcess();
+ LOG("Wait returning");
+ return true;
+}
+
+TEST_F(CritSectTest, ThreadWakesTwice) {
+ CriticalSectionWrapper* crit_sect
+ = CriticalSectionWrapper::CreateCriticalSection();
+ ProtectedCount count(crit_sect);
+ ThreadWrapper* thread = ThreadWrapper::CreateThread(&LockUnlockRunFunction,
+ &count);
+ unsigned int id = 42;
+ crit_sect->Enter(); // Make sure counter stays 0 until we wait for it.
+ ASSERT_TRUE(thread->Start(id));
+ crit_sect->Leave();
+
+ // The thread is capable of grabbing the lock multiple times,
+ // incrementing counter once each time.
+ // It's possible for the count to be incremented by more than 2.
+ EXPECT_TRUE(WaitForCount(2, &count));
+ EXPECT_LE(2, count.Count());
+
+ // The thread does not increment while lock is held.
+ crit_sect->Enter();
+ int count_before = count.Count();
+ for (int i = 0; i < 10; i++) {
+ SwitchProcess();
+ }
+ EXPECT_EQ(count_before, count.Count());
+ crit_sect->Leave();
+
+ thread->SetNotAlive(); // Tell thread to exit once run function finishes.
+ SwitchProcess();
+ EXPECT_LT(count_before, count.Count());
+ EXPECT_TRUE(thread->Stop());
+ delete thread;
+ delete crit_sect;
+}
+
+} // anonymous namespace
+
+} // namespace webrtc
diff --git a/src/system_wrappers/source/critical_section_win.cc b/src/system_wrappers/source/critical_section_win.cc
new file mode 100644
index 0000000000..bbc66e5c7d
--- /dev/null
+++ b/src/system_wrappers/source/critical_section_win.cc
@@ -0,0 +1,35 @@
+/*
+ * 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 "critical_section_win.h"
+
+namespace webrtc {
+CriticalSectionWindows::CriticalSectionWindows()
+{
+ InitializeCriticalSection(&crit);
+}
+
+CriticalSectionWindows::~CriticalSectionWindows()
+{
+ DeleteCriticalSection(&crit);
+}
+
+void
+CriticalSectionWindows::Enter()
+{
+ EnterCriticalSection(&crit);
+}
+
+void
+CriticalSectionWindows::Leave()
+{
+ LeaveCriticalSection(&crit);
+}
+} // namespace webrtc
diff --git a/src/system_wrappers/source/critical_section_win.h b/src/system_wrappers/source/critical_section_win.h
new file mode 100644
index 0000000000..9556fa9556
--- /dev/null
+++ b/src/system_wrappers/source/critical_section_win.h
@@ -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.
+ */
+
+#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_WINDOWS_H_
+#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_WINDOWS_H_
+
+#include "typedefs.h"
+#include "critical_section_wrapper.h"
+#include <windows.h>
+
+namespace webrtc {
+class CriticalSectionWindows : public CriticalSectionWrapper
+{
+public:
+ CriticalSectionWindows();
+
+ virtual ~CriticalSectionWindows();
+
+ virtual void Enter();
+ virtual void Leave();
+
+private:
+ CRITICAL_SECTION crit;
+
+ friend class ConditionVariableWindows;
+};
+} // namespace webrtc
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CRITICAL_SECTION_WINDOWS_H_
diff --git a/src/system_wrappers/source/event_win.cc b/src/system_wrappers/source/event_win.cc
new file mode 100644
index 0000000000..efcb5af870
--- /dev/null
+++ b/src/system_wrappers/source/event_win.cc
@@ -0,0 +1,84 @@
+/*
+ * 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 "event_win.h"
+
+#include "Mmsystem.h"
+
+namespace webrtc {
+EventWindows::EventWindows()
+ : _event(::CreateEvent(NULL /* security attributes */,
+ FALSE /* manual reset */,
+ FALSE /* initial state */,
+ NULL /* name of event */)),
+ _timerID(NULL)
+{
+}
+
+EventWindows::~EventWindows()
+{
+ CloseHandle(_event);
+}
+
+bool EventWindows::Set()
+{
+ // Note: setting an event that is already set has no effect.
+ return SetEvent(_event) == 1 ? true : false;
+}
+
+bool EventWindows::Reset()
+{
+ return ResetEvent(_event) == 1 ? true : false;
+}
+
+EventTypeWrapper EventWindows::Wait(unsigned long maxTime)
+{
+ unsigned long res = WaitForSingleObject(_event, maxTime);
+ switch(res)
+ {
+ case WAIT_OBJECT_0:
+ return kEventSignaled;
+ case WAIT_TIMEOUT:
+ return kEventTimeout;
+ default:
+ return kEventError;
+ }
+}
+
+bool EventWindows::StartTimer(bool periodic, unsigned long time)
+{
+ if (_timerID != NULL)
+ {
+ timeKillEvent(_timerID);
+ _timerID=NULL;
+ }
+ if (periodic)
+ {
+ _timerID=timeSetEvent(time, 0,(LPTIMECALLBACK)HANDLE(_event),0,
+ TIME_PERIODIC|TIME_CALLBACK_EVENT_PULSE);
+ } else {
+ _timerID=timeSetEvent(time, 0,(LPTIMECALLBACK)HANDLE(_event),0,
+ TIME_ONESHOT|TIME_CALLBACK_EVENT_SET);
+ }
+
+ if (_timerID == NULL)
+ {
+ return false;
+ }
+ return true;
+}
+
+bool EventWindows::StopTimer()
+{
+ timeKillEvent(_timerID);
+ _timerID = NULL;
+ return true;
+}
+} // namespace webrtc
diff --git a/src/system_wrappers/source/event_win.h b/src/system_wrappers/source/event_win.h
new file mode 100644
index 0000000000..8ca1360c35
--- /dev/null
+++ b/src/system_wrappers/source/event_win.h
@@ -0,0 +1,40 @@
+/*
+ * 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_EVENT_WINDOWS_H_
+#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_WINDOWS_H_
+
+#include <windows.h>
+
+#include "event_wrapper.h"
+
+#include "typedefs.h"
+
+namespace webrtc {
+class EventWindows : public EventWrapper
+{
+public:
+ EventWindows();
+ virtual ~EventWindows();
+
+ virtual EventTypeWrapper Wait(unsigned long maxTime);
+ virtual bool Set();
+ virtual bool Reset();
+
+ virtual bool StartTimer(bool periodic, unsigned long time);
+ virtual bool StopTimer();
+
+private:
+ HANDLE _event;
+ WebRtc_UWord32 _timerID;
+};
+} // namespace webrtc
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_EVENT_WINDOWS_H_
diff --git a/src/system_wrappers/source/file_impl.cc b/src/system_wrappers/source/file_impl.cc
index d163bf6c26..4d06c54707 100644
--- a/src/system_wrappers/source/file_impl.cc
+++ b/src/system_wrappers/source/file_impl.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -118,7 +118,7 @@ int FileWrapperImpl::OpenFile(const char *fileNameUTF8, bool readOnly,
bool loop, bool text)
{
size_t length = strlen(fileNameUTF8);
- if (length > kMaxFileNameSize)
+ if (length > kMaxFileNameSize - 1)
{
return -1;
}
diff --git a/src/system_wrappers/source/rw_lock.cc b/src/system_wrappers/source/rw_lock.cc
index b308358d8a..16da0e321d 100644
--- a/src/system_wrappers/source/rw_lock.cc
+++ b/src/system_wrappers/source/rw_lock.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -14,9 +14,6 @@
#if defined(_WIN32)
#include "rw_lock_win.h"
-#elif defined(WEBRTC_ANDROID)
- #include <stdlib.h>
- #include "rw_lock_generic.h"
#else
#include "rw_lock_posix.h"
#endif
@@ -26,8 +23,6 @@ RWLockWrapper* RWLockWrapper::CreateRWLock()
{
#ifdef _WIN32
RWLockWrapper* lock = new RWLockWindows();
-#elif defined(WEBRTC_ANDROID)
- RWLockWrapper* lock = new RWLockWrapperGeneric();
#else
RWLockWrapper* lock = new RWLockPosix();
#endif
diff --git a/src/system_wrappers/source/rw_lock_win.cc b/src/system_wrappers/source/rw_lock_win.cc
new file mode 100644
index 0000000000..82cd0ac04f
--- /dev/null
+++ b/src/system_wrappers/source/rw_lock_win.cc
@@ -0,0 +1,186 @@
+/*
+ * 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 "rw_lock_win.h"
+
+#include "critical_section_wrapper.h"
+#include "condition_variable_wrapper.h"
+#include "trace.h"
+
+// TODO (hellner) why not just use the rw_lock_generic.cc solution if
+// native is not supported? Unnecessary redundancy!
+
+namespace webrtc {
+bool RWLockWindows::_winSupportRWLockPrimitive = false;
+static HMODULE library = NULL;
+
+PInitializeSRWLock _PInitializeSRWLock;
+PAcquireSRWLockExclusive _PAcquireSRWLockExclusive;
+PAcquireSRWLockShared _PAcquireSRWLockShared;
+PReleaseSRWLockShared _PReleaseSRWLockShared;
+PReleaseSRWLockExclusive _PReleaseSRWLockExclusive;
+
+RWLockWindows::RWLockWindows()
+ : _critSectPtr(NULL),
+ _readCondPtr(NULL),
+ _writeCondPtr(NULL),
+ _readersActive(0),
+ _writerActive(false),
+ _readersWaiting(0),
+ _writersWaiting(0)
+{
+}
+
+RWLockWindows::~RWLockWindows()
+{
+ delete _writeCondPtr;
+ delete _readCondPtr;
+ delete _critSectPtr;
+}
+
+int RWLockWindows::Init()
+{
+ if(!library)
+ {
+ // Use native implementation if supported (i.e Vista+)
+ library = LoadLibrary(TEXT("Kernel32.dll"));
+ if(library)
+ {
+ WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
+ "Loaded Kernel.dll");
+
+ _PInitializeSRWLock =
+ (PInitializeSRWLock)GetProcAddress(
+ library,
+ "InitializeSRWLock");
+
+ _PAcquireSRWLockExclusive =
+ (PAcquireSRWLockExclusive)GetProcAddress(
+ library,
+ "AcquireSRWLockExclusive");
+ _PReleaseSRWLockExclusive =
+ (PReleaseSRWLockExclusive)GetProcAddress(
+ library,
+ "ReleaseSRWLockExclusive");
+ _PAcquireSRWLockShared =
+ (PAcquireSRWLockShared)GetProcAddress(
+ library,
+ "AcquireSRWLockShared");
+ _PReleaseSRWLockShared =
+ (PReleaseSRWLockShared)GetProcAddress(
+ library,
+ "ReleaseSRWLockShared");
+
+ if( _PInitializeSRWLock &&
+ _PAcquireSRWLockExclusive &&
+ _PReleaseSRWLockExclusive &&
+ _PAcquireSRWLockShared &&
+ _PReleaseSRWLockShared )
+ {
+ WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
+ "Loaded Simple RW Lock");
+ _winSupportRWLockPrimitive = true;
+ }
+ }
+ }
+ if(_winSupportRWLockPrimitive)
+ {
+ _PInitializeSRWLock(&_lock);
+ } else {
+ _critSectPtr = CriticalSectionWrapper::CreateCriticalSection();
+ _readCondPtr = ConditionVariableWrapper::CreateConditionVariable();
+ _writeCondPtr = ConditionVariableWrapper::CreateConditionVariable();
+ }
+ return 0;
+}
+
+void RWLockWindows::AcquireLockExclusive()
+{
+ if (_winSupportRWLockPrimitive)
+ {
+ _PAcquireSRWLockExclusive(&_lock);
+ } else {
+ _critSectPtr->Enter();
+
+ if (_writerActive || _readersActive > 0)
+ {
+ ++_writersWaiting;
+ while (_writerActive || _readersActive > 0)
+ {
+ _writeCondPtr->SleepCS(*_critSectPtr);
+ }
+ --_writersWaiting;
+ }
+ _writerActive = true;
+ _critSectPtr->Leave();
+ }
+}
+
+void RWLockWindows::ReleaseLockExclusive()
+{
+ if(_winSupportRWLockPrimitive)
+ {
+ _PReleaseSRWLockExclusive(&_lock);
+ } else {
+ _critSectPtr->Enter();
+ _writerActive = false;
+ if (_writersWaiting > 0)
+ {
+ _writeCondPtr->Wake();
+
+ }else if (_readersWaiting > 0) {
+ _readCondPtr->WakeAll();
+ }
+ _critSectPtr->Leave();
+ }
+}
+
+void RWLockWindows::AcquireLockShared()
+{
+ if(_winSupportRWLockPrimitive)
+ {
+ _PAcquireSRWLockShared(&_lock);
+ } else
+ {
+ _critSectPtr->Enter();
+ if (_writerActive || _writersWaiting > 0)
+ {
+ ++_readersWaiting;
+
+ while (_writerActive || _writersWaiting > 0)
+ {
+ _readCondPtr->SleepCS(*_critSectPtr);
+ }
+ --_readersWaiting;
+ }
+ ++_readersActive;
+ _critSectPtr->Leave();
+ }
+}
+
+void RWLockWindows::ReleaseLockShared()
+{
+ if(_winSupportRWLockPrimitive)
+ {
+ _PReleaseSRWLockShared(&_lock);
+ } else
+ {
+ _critSectPtr->Enter();
+
+ --_readersActive;
+
+ if (_readersActive == 0 && _writersWaiting > 0)
+ {
+ _writeCondPtr->Wake();
+ }
+ _critSectPtr->Leave();
+ }
+}
+} // namespace webrtc
diff --git a/src/system_wrappers/source/rw_lock_win.h b/src/system_wrappers/source/rw_lock_win.h
new file mode 100644
index 0000000000..dc5355e4d6
--- /dev/null
+++ b/src/system_wrappers/source/rw_lock_win.h
@@ -0,0 +1,71 @@
+/*
+ * 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_RW_LOCK_WINDOWS_H_
+#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WINDOWS_H_
+
+#include "rw_lock_wrapper.h"
+
+#include <Windows.h>
+
+#if !defined(RTL_SRWLOCK_INIT)
+ typedef struct _RTL_SRWLOCK
+ {
+ void* Ptr;
+ } RTL_SRWLOCK, *PRTL_SRWLOCK;
+ typedef RTL_SRWLOCK SRWLOCK, *PSRWLOCK;
+#endif
+
+namespace webrtc {
+class CriticalSectionWrapper;
+class ConditionVariableWrapper;
+
+typedef void (WINAPI *PInitializeSRWLock)(PSRWLOCK);
+
+typedef void (WINAPI *PAcquireSRWLockExclusive)(PSRWLOCK);
+typedef void (WINAPI *PReleaseSRWLockExclusive)(PSRWLOCK);
+
+typedef void (WINAPI *PAcquireSRWLockShared)(PSRWLOCK);
+typedef void (WINAPI *PReleaseSRWLockShared)(PSRWLOCK);
+
+
+class RWLockWindows :public RWLockWrapper
+{
+public:
+ RWLockWindows();
+ virtual ~RWLockWindows();
+
+ virtual void AcquireLockExclusive();
+ virtual void ReleaseLockExclusive();
+
+ virtual void AcquireLockShared();
+ virtual void ReleaseLockShared();
+
+protected:
+ virtual int Init();
+
+private:
+ // For native implementation.
+ static bool _winSupportRWLockPrimitive;
+ SRWLOCK _lock;
+
+ // Genric implementation, fallback if native is not supported.
+ CriticalSectionWrapper* _critSectPtr;
+ ConditionVariableWrapper* _readCondPtr;
+ ConditionVariableWrapper* _writeCondPtr;
+
+ int _readersActive;
+ bool _writerActive;
+ int _readersWaiting;
+ int _writersWaiting;
+};
+} // namespace webrtc
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_RW_LOCK_WINDOWS_H_
diff --git a/src/system_wrappers/source/set_thread_name_win.h b/src/system_wrappers/source/set_thread_name_win.h
new file mode 100644
index 0000000000..a46f4d6305
--- /dev/null
+++ b/src/system_wrappers/source/set_thread_name_win.h
@@ -0,0 +1,43 @@
+/*
+ * Use of this source code is governed by the MICROSOFT LIMITED PUBLIC LICENSE
+ * copyright license which can be found in the LICENSE file in the
+ * third_party_mods/mslpl directory of the source tree or at
+ * http://msdn.microsoft.com/en-us/cc300389.aspx#P.
+ */
+/*
+ * The original code can be found here:
+ * http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.71).aspx
+ */
+
+#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WINDOWS_SET_NAME_H_
+#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WINDOWS_SET_NAME_H_
+
+namespace webrtc {
+
+struct THREADNAME_INFO
+{
+ DWORD dwType; // must be 0x1000
+ LPCSTR szName; // pointer to name (in user addr space)
+ DWORD dwThreadID; // thread ID (-1 = caller thread)
+ DWORD dwFlags; // reserved for future use, must be zero
+};
+
+void SetThreadName(DWORD dwThreadID, LPCSTR szThreadName)
+{
+ THREADNAME_INFO info;
+ info.dwType = 0x1000;
+ info.szName = szThreadName;
+ info.dwThreadID = dwThreadID;
+ info.dwFlags = 0;
+
+ __try
+ {
+ RaiseException(0x406D1388, 0, sizeof(info) / sizeof(DWORD),
+ (ULONG_PTR*)&info);
+ }
+ __except (EXCEPTION_CONTINUE_EXECUTION)
+ {
+ }
+}
+} // namespace webrtc
+#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WINDOWS_SET_NAME_H_
diff --git a/src/system_wrappers/source/sleep.cc b/src/system_wrappers/source/sleep.cc
new file mode 100644
index 0000000000..be8523857c
--- /dev/null
+++ b/src/system_wrappers/source/sleep.cc
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+// An OS-independent sleep function.
+
+#include "system_wrappers/interface/sleep.h"
+
+#ifdef _WIN32
+// For Sleep()
+#include <windows.h>
+#else
+// For nanosleep()
+#include <time.h>
+#endif
+
+namespace webrtc {
+
+void SleepMs(int msecs) {
+#ifdef _WIN32
+ Sleep(msecs);
+#else
+ struct timespec short_wait;
+ struct timespec remainder;
+ short_wait.tv_sec = msecs / 1000;
+ short_wait.tv_nsec = (msecs % 1000) * 1000 * 1000;
+ nanosleep(&short_wait, &remainder);
+#endif
+}
+
+} // namespace webrtc
diff --git a/src/system_wrappers/source/sort.cc b/src/system_wrappers/source/sort.cc
index f44b644978..34aa4373ee 100644
--- a/src/system_wrappers/source/sort.cc
+++ b/src/system_wrappers/source/sort.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -412,8 +412,6 @@ namespace webrtc
case TYPE_Float64:
StdSort<double>(data, numOfElements);
break;
- default:
- return -1;
}
#endif
return 0;
@@ -543,9 +541,9 @@ namespace webrtc
return StdKeySort<float>(data, key, numOfElements, sizeOfElement);
case TYPE_Float64:
return StdKeySort<double>(data, key, numOfElements, sizeOfElement);
- default:
- return -1;
}
+ assert(false);
+ return -1;
#endif
}
} // namespace webrtc
diff --git a/src/system_wrappers/source/system_wrappers.gyp b/src/system_wrappers/source/system_wrappers.gyp
index ce2438ffe9..b530d6f483 100644
--- a/src/system_wrappers/source/system_wrappers.gyp
+++ b/src/system_wrappers/source/system_wrappers.gyp
@@ -1,4 +1,4 @@
-# Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+# 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
@@ -23,7 +23,8 @@
},
'sources': [
'../interface/aligned_malloc.h',
- '../interface/atomic32_wrapper.h',
+ '../interface/atomic32.h',
+ '../interface/compile_assert.h',
'../interface/condition_variable_wrapper.h',
'../interface/cpu_info.h',
'../interface/cpu_wrapper.h',
@@ -41,16 +42,16 @@
'../interface/rw_lock_wrapper.h',
'../interface/scoped_ptr.h',
'../interface/scoped_refptr.h',
+ '../interface/sleep.h',
'../interface/sort.h',
'../interface/static_instance.h',
'../interface/thread_wrapper.h',
'../interface/tick_util.h',
'../interface/trace.h',
'aligned_malloc.cc',
- 'atomic32.cc',
- 'atomic32_linux.h',
- 'atomic32_mac.h',
- 'atomic32_win.h',
+ 'atomic32_mac.cc',
+ 'atomic32_posix.cc',
+ 'atomic32_win.cc',
'condition_variable.cc',
'condition_variable_posix.cc',
'condition_variable_posix.h',
@@ -88,6 +89,7 @@
'rw_lock_posix.h',
'rw_lock_win.cc',
'rw_lock_win.h',
+ 'sleep.cc',
'sort.cc',
'thread.cc',
'thread_posix.cc',
@@ -109,6 +111,9 @@
},{
'sources!': [ 'data_log.cc', ],
},],
+ ['OS=="android"', {
+ 'dependencies': [ 'cpu_features_android', ],
+ }],
['OS=="linux"', {
'link_settings': {
'libraries': [ '-lrt', ],
@@ -118,6 +123,9 @@
'link_settings': {
'libraries': [ '$(SDKROOT)/System/Library/Frameworks/ApplicationServices.framework', ],
},
+ 'sources!': [
+ 'atomic32_posix.cc',
+ ],
}],
['OS=="win"', {
'link_settings': {
@@ -147,18 +155,41 @@
},
], # targets
'conditions': [
- ['build_with_chromium==0', {
+ ['OS=="android"', {
+ 'targets': [
+ {
+ 'variables': {
+ # Treat this as third-party code.
+ 'chromium_code': 0,
+ },
+ 'target_name': 'cpu_features_android',
+ 'type': '<(library)',
+ 'sources': [
+ 'android/cpu-features.c',
+ 'android/cpu-features.h',
+ # TODO(leozwang): Ideally we want to audomatically exclude .c files
+ # as with .cc files, gyp currently only excludes .cc files.
+ 'cpu_features_android.c',
+ ],
+ },
+ ],
+ }],
+ ['include_tests==1', {
'targets': [
{
'target_name': 'system_wrappers_unittests',
'type': 'executable',
'dependencies': [
'system_wrappers',
- '<(webrtc_root)/../testing/gtest.gyp:gtest',
- '<(webrtc_root)/../test/test.gyp:test_support_main',
+ '<(DEPTH)/testing/gtest.gyp:gtest',
+ '<(webrtc_root)/test/test.gyp:test_support_main',
],
'sources': [
+ 'condition_variable_unittest.cc',
'cpu_wrapper_unittest.cc',
+ 'cpu_measurement_harness.h',
+ 'cpu_measurement_harness.cc',
+ 'critical_section_unittest.cc',
'list_unittest.cc',
'map_unittest.cc',
'data_log_unittest.cc',
@@ -166,6 +197,9 @@
'data_log_helpers_unittest.cc',
'data_log_c_helpers_unittest.c',
'data_log_c_helpers_unittest.h',
+ 'thread_unittest.cc',
+ 'trace_unittest.cc',
+ 'unittest_utilities_unittest.cc',
],
'conditions': [
['enable_data_logging==1', {
@@ -176,7 +210,7 @@
],
},
], # targets
- }], # build_with_chromium
+ }], # include_tests
], # conditions
}
diff --git a/src/system_wrappers/source/thread_posix.cc b/src/system_wrappers/source/thread_posix.cc
index eb0e8f46a0..6334490f78 100644
--- a/src/system_wrappers/source/thread_posix.cc
+++ b/src/system_wrappers/source/thread_posix.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -8,6 +8,40 @@
* be found in the AUTHORS file in the root of the source tree.
*/
+// The state of a thread is controlled by the two member variables
+// _alive and _dead.
+// _alive represents the state the thread has been ordered to achieve.
+// It is set to true by the thread at startup, and is set to false by
+// other threads, using SetNotAlive() and Stop().
+// _dead represents the state the thread has achieved.
+// It is written by the thread encapsulated by this class only
+// (except at init). It is read only by the Stop() method.
+// The Run() method fires _event when it's started; this ensures that the
+// Start() method does not continue until after _dead is false.
+// This protects against premature Stop() calls from the creator thread, but
+// not from other threads.
+
+// Their transitions and states:
+// _alive _dead Set by
+// false true Constructor
+// true false Run() method entry
+// false any Run() method runFunction failure
+// any false Run() method exit (happens only with _alive false)
+// false any SetNotAlive
+// false any Stop Stop waits for _dead to become true.
+//
+// Summarized a different way:
+// Variable Writer Reader
+// _alive Constructor(false) Run.loop
+// Run.start(true)
+// Run.fail(false)
+// SetNotAlive(false)
+// Stop(false)
+//
+// _dead Constructor(true) Stop.loop
+// Run.start(false)
+// Run.exit(true)
+
#include "thread_posix.h"
#include <errno.h>
@@ -22,8 +56,13 @@
#include <sys/prctl.h>
#endif
-#include "event_wrapper.h"
-#include "trace.h"
+#if defined(WEBRTC_MAC)
+#include <mach/mach.h>
+#endif
+
+#include "system_wrappers/interface/critical_section_wrapper.h"
+#include "system_wrappers/interface/event_wrapper.h"
+#include "system_wrappers/interface/trace.h"
namespace webrtc {
extern "C"
@@ -35,17 +74,6 @@ extern "C"
}
}
-#if (defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID))
-static pid_t gettid()
-{
-#if defined(__NR_gettid)
- return syscall(__NR_gettid);
-#else
- return -1;
-#endif
-}
-#endif
-
ThreadWrapper* ThreadPosix::Create(ThreadRunFunction func, ThreadObj obj,
ThreadPriority prio, const char* threadName)
{
@@ -67,22 +95,37 @@ ThreadPosix::ThreadPosix(ThreadRunFunction func, ThreadObj obj,
ThreadPriority prio, const char* threadName)
: _runFunction(func),
_obj(obj),
+ _crit_state(CriticalSectionWrapper::CreateCriticalSection()),
_alive(false),
_dead(true),
_prio(prio),
_event(EventWrapper::Create()),
- _setThreadName(false)
-{
-#ifdef WEBRTC_LINUX
- _linuxPid = -1;
+ _name(),
+ _setThreadName(false),
+#if (defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID))
+ _pid(-1),
#endif
+ _attr(),
+ _thread(0)
+{
if (threadName != NULL)
{
_setThreadName = true;
strncpy(_name, threadName, kThreadMaxNameLength);
+ _name[kThreadMaxNameLength - 1] = '\0';
}
}
+uint32_t ThreadWrapper::GetThreadId() {
+#if defined(WEBRTC_ANDROID) || defined(WEBRTC_LINUX)
+ return static_cast<uint32_t>(syscall(__NR_gettid));
+#elif defined(WEBRTC_MAC)
+ return static_cast<uint32_t>(mach_thread_self());
+#else
+ return reinterpret_cast<uint32_t>(pthread_self());
+#endif
+}
+
int ThreadPosix::Construct()
{
int result = 0;
@@ -104,7 +147,6 @@ int ThreadPosix::Construct()
{
return -1;
}
-
return 0;
}
@@ -112,6 +154,7 @@ ThreadPosix::~ThreadPosix()
{
pthread_attr_destroy(&_attr);
delete _event;
+ delete _crit_state;
}
#define HAS_THREAD_ID !defined(MAC_IPHONE) && !defined(MAC_IPHONE_SIM) && \
@@ -180,8 +223,6 @@ bool ThreadPosix::Start(unsigned int& /*threadID*/)
case kRealtimePriority:
param.sched_priority = maxPrio - 1;
break;
- default:
- return false;
}
result = pthread_setschedparam(_thread, policy, &param);
if (result == EINVAL)
@@ -191,33 +232,40 @@ bool ThreadPosix::Start(unsigned int& /*threadID*/)
return true;
}
-#if (defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID))
+// CPU_ZERO and CPU_SET are not available in NDK r7, so disable
+// SetAffinity on Android for now.
+#if (defined(WEBRTC_LINUX) && (!defined(WEBRTC_ANDROID)))
bool ThreadPosix::SetAffinity(const int* processorNumbers,
- const unsigned int amountOfProcessors)
-{
- if (!processorNumbers || (amountOfProcessors == 0))
- {
- return false;
- }
-
- cpu_set_t mask;
- CPU_ZERO(&mask);
-
- for(unsigned int processor = 0;
- processor < amountOfProcessors;
- processor++)
- {
- CPU_SET(processorNumbers[processor], &mask);
- }
- const int result = sched_setaffinity(_linuxPid, (unsigned int)sizeof(mask),
- &mask);
- if (result != 0)
- {
- return false;
+ const unsigned int amountOfProcessors) {
+ if (!processorNumbers || (amountOfProcessors == 0)) {
+ return false;
+ }
+ cpu_set_t mask;
+ CPU_ZERO(&mask);
- }
- return true;
+ for (unsigned int processor = 0;
+ processor < amountOfProcessors;
+ processor++) {
+ CPU_SET(processorNumbers[processor], &mask);
+ }
+#if defined(WEBRTC_ANDROID)
+ // Android.
+ const int result = syscall(__NR_sched_setaffinity,
+ _pid,
+ sizeof(mask),
+ &mask);
+#else
+ // "Normal" Linux.
+ const int result = sched_setaffinity(_pid,
+ sizeof(mask),
+ &mask);
+#endif
+ if (result != 0) {
+ return false;
+ }
+ return true;
}
+
#else
// NOTE: On Mac OS X, use the Thread affinity API in
// /usr/include/mach/thread_policy.h: thread_policy_set and mach_thread_self()
@@ -230,6 +278,7 @@ bool ThreadPosix::SetAffinity(const int* , const unsigned int)
void ThreadPosix::SetNotAlive()
{
+ CriticalSectionScoped cs(_crit_state);
_alive = false;
}
@@ -249,18 +298,27 @@ bool ThreadPosix::Shutdown()
bool ThreadPosix::Stop()
{
- _alive = false;
+ bool dead = false;
+ {
+ CriticalSectionScoped cs(_crit_state);
+ _alive = false;
+ dead = _dead;
+ }
// TODO (hellner) why not use an event here?
// Wait up to 10 seconds for the thread to terminate
- for (int i = 0; i < 1000 && !_dead; i++)
+ for (int i = 0; i < 1000 && !dead; i++)
{
timespec t;
t.tv_sec = 0;
t.tv_nsec = 10*1000*1000;
nanosleep(&t, NULL);
+ {
+ CriticalSectionScoped cs(_crit_state);
+ dead = _dead;
+ }
}
- if (_dead)
+ if (dead)
{
return true;
}
@@ -272,13 +330,13 @@ bool ThreadPosix::Stop()
void ThreadPosix::Run()
{
- _alive = true;
- _dead = false;
-#ifdef WEBRTC_LINUX
- if(_linuxPid == -1)
{
- _linuxPid = gettid();
+ CriticalSectionScoped cs(_crit_state);
+ _alive = true;
+ _dead = false;
}
+#if (defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID))
+ _pid = GetThreadId();
#endif
// The event the Start() is waiting for.
_event->Set();
@@ -286,38 +344,38 @@ void ThreadPosix::Run()
if (_setThreadName)
{
#ifdef WEBRTC_LINUX
- WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,-1,
- "Thread with id:%d name:%s started ", _linuxPid, _name);
prctl(PR_SET_NAME, (unsigned long)_name, 0, 0, 0);
-#else
+#endif
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,-1,
"Thread with name:%s started ", _name);
-#endif
- }else
+ } else
{
-#ifdef WEBRTC_LINUX
- WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
- "Thread with id:%d without name started", _linuxPid);
-#else
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, -1,
"Thread without name started");
-#endif
}
+ bool alive = true;
do
{
if (_runFunction)
{
if (!_runFunction(_obj))
{
- _alive = false;
+ alive = false;
}
}
else
{
- _alive = false;
+ alive = false;
+ }
+ {
+ CriticalSectionScoped cs(_crit_state);
+ if (!alive) {
+ _alive = false;
+ }
+ alive = _alive;
}
}
- while (_alive);
+ while (alive);
if (_setThreadName)
{
@@ -335,6 +393,9 @@ void ThreadPosix::Run()
WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,-1,
"Thread without name stopped");
}
- _dead = true;
+ {
+ CriticalSectionScoped cs(_crit_state);
+ _dead = true;
+ }
}
} // namespace webrtc
diff --git a/src/system_wrappers/source/thread_posix.h b/src/system_wrappers/source/thread_posix.h
index f664a52e70..45489a8622 100644
--- a/src/system_wrappers/source/thread_posix.h
+++ b/src/system_wrappers/source/thread_posix.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -15,6 +15,8 @@
#include <pthread.h>
namespace webrtc {
+
+class CriticalSectionWrapper;
class EventWrapper;
class ThreadPosix : public ThreadWrapper
@@ -47,6 +49,7 @@ private:
ThreadObj _obj;
// internal state
+ CriticalSectionWrapper* _crit_state; // Protects _alive and _dead
bool _alive;
bool _dead;
ThreadPriority _prio;
@@ -57,12 +60,11 @@ private:
bool _setThreadName;
// handle to thread
+#if (defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID))
+ pid_t _pid;
+#endif
pthread_attr_t _attr;
pthread_t _thread;
-#ifdef WEBRTC_LINUX
- pid_t _linuxPid;
-#endif
-
};
} // namespace webrtc
diff --git a/src/system_wrappers/source/thread_unittest.cc b/src/system_wrappers/source/thread_unittest.cc
new file mode 100644
index 0000000000..361424a7fb
--- /dev/null
+++ b/src/system_wrappers/source/thread_unittest.cc
@@ -0,0 +1,96 @@
+/*
+ * 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/thread_wrapper.h"
+
+#include "gtest/gtest.h"
+#include "system_wrappers/interface/trace.h"
+
+namespace webrtc {
+
+const int kLogTrace = 0;
+
+class TestTraceCallback : public TraceCallback {
+ public:
+ virtual void Print(const TraceLevel level,
+ const char* traceString,
+ const int length) {
+ if (traceString) {
+ char* cmd_print = new char[length+1];
+ memcpy(cmd_print, traceString, length);
+ cmd_print[length] = '\0';
+ printf("%s\n", cmd_print);
+ fflush(stdout);
+ delete[] cmd_print;
+ }
+ }
+};
+
+class ThreadTest : public ::testing::Test {
+ public:
+ ThreadTest() {
+ StartTrace();
+ }
+ ~ThreadTest() {
+ StopTrace();
+ }
+
+ private:
+ void StartTrace() {
+ if (kLogTrace) {
+ Trace::CreateTrace();
+ Trace::SetLevelFilter(webrtc::kTraceAll);
+ Trace::SetTraceCallback(&trace_);
+ }
+ }
+
+ void StopTrace() {
+ if (kLogTrace) {
+ Trace::ReturnTrace();
+ }
+ }
+
+ TestTraceCallback trace_;
+};
+
+// Function that does nothing, and reports success.
+bool NullRunFunction(void* /* obj */) {
+ return true;
+}
+
+TEST_F(ThreadTest, StartStop) {
+ ThreadWrapper* thread = ThreadWrapper::CreateThread(&NullRunFunction);
+ unsigned int id = 42;
+ ASSERT_TRUE(thread->Start(id));
+ EXPECT_TRUE(thread->Stop());
+ delete thread;
+}
+
+// Function that sets a boolean.
+bool SetFlagRunFunction(void* obj) {
+ bool* obj_as_bool = static_cast<bool*> (obj);
+ *obj_as_bool = true;
+ return true;
+}
+
+TEST_F(ThreadTest, RunFunctionIsCalled) {
+ bool flag = false;
+ ThreadWrapper* thread = ThreadWrapper::CreateThread(&SetFlagRunFunction,
+ &flag);
+ unsigned int id = 42;
+ ASSERT_TRUE(thread->Start(id));
+ // At this point, the flag may be either true or false.
+ EXPECT_TRUE(thread->Stop());
+ // We expect the thread to have run at least once.
+ EXPECT_TRUE(flag);
+ delete thread;
+}
+
+} // namespace webrtc
diff --git a/src/system_wrappers/source/thread_win.cc b/src/system_wrappers/source/thread_win.cc
new file mode 100644
index 0000000000..07c586a87c
--- /dev/null
+++ b/src/system_wrappers/source/thread_win.cc
@@ -0,0 +1,233 @@
+/*
+ * 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 "thread_win.h"
+
+#include <assert.h>
+#include <process.h>
+#include <stdio.h>
+#include <windows.h>
+
+#include "set_thread_name_win.h"
+#include "trace.h"
+
+namespace webrtc {
+ThreadWindows::ThreadWindows(ThreadRunFunction func, ThreadObj obj,
+ ThreadPriority prio, const char* threadName)
+ : ThreadWrapper(),
+ _runFunction(func),
+ _obj(obj),
+ _alive(false),
+ _dead(true),
+ _doNotCloseHandle(false),
+ _prio(prio),
+ _event(NULL),
+ _thread(NULL),
+ _id(0),
+ _name(),
+ _setThreadName(false)
+{
+ _event = EventWrapper::Create();
+ _critsectStop = CriticalSectionWrapper::CreateCriticalSection();
+ if (threadName != NULL)
+ {
+ // Set the thread name to appear in the VS debugger.
+ _setThreadName = true;
+ strncpy(_name, threadName, kThreadMaxNameLength);
+ }
+}
+
+ThreadWindows::~ThreadWindows()
+{
+#ifdef _DEBUG
+ assert(!_alive);
+#endif
+ if (_thread)
+ {
+ CloseHandle(_thread);
+ }
+ if(_event)
+ {
+ delete _event;
+ }
+ if(_critsectStop)
+ {
+ delete _critsectStop;
+ }
+}
+
+uint32_t ThreadWrapper::GetThreadId() {
+ return GetCurrentThreadId();
+}
+
+unsigned int WINAPI ThreadWindows::StartThread(LPVOID lpParameter)
+{
+ static_cast<ThreadWindows*>(lpParameter)->Run();
+ return 0;
+}
+
+bool ThreadWindows::Start(unsigned int& threadID)
+{
+ _doNotCloseHandle = false;
+
+ // Set stack size to 1M
+ _thread=(HANDLE)_beginthreadex(NULL, 1024*1024, StartThread, (void*)this, 0,
+ &threadID);
+ if(_thread == NULL)
+ {
+ return false;
+ }
+ _id = threadID;
+ _event->Wait(INFINITE);
+
+ switch(_prio)
+ {
+ case kLowPriority:
+ SetThreadPriority(_thread, THREAD_PRIORITY_BELOW_NORMAL);
+ break;
+ case kNormalPriority:
+ SetThreadPriority(_thread, THREAD_PRIORITY_NORMAL);
+ break;
+ case kHighPriority:
+ SetThreadPriority(_thread, THREAD_PRIORITY_ABOVE_NORMAL);
+ break;
+ case kHighestPriority:
+ SetThreadPriority(_thread, THREAD_PRIORITY_HIGHEST);
+ break;
+ case kRealtimePriority:
+ SetThreadPriority(_thread, THREAD_PRIORITY_TIME_CRITICAL);
+ break;
+ };
+ return true;
+}
+
+bool ThreadWindows::SetAffinity(const int* processorNumbers,
+ const unsigned int amountOfProcessors)
+{
+ DWORD_PTR processorBitMask = 0;
+ for(unsigned int processorIndex = 0;
+ processorIndex < amountOfProcessors;
+ processorIndex++)
+ {
+ // Convert from an array with processor numbers to a bitmask
+ // Processor numbers start at zero.
+ // TODO (hellner): this looks like a bug. Shouldn't the '=' be a '+='?
+ // Or even better |=
+ processorBitMask = 1 << processorNumbers[processorIndex];
+ }
+ return SetThreadAffinityMask(_thread,processorBitMask) != 0;
+}
+
+void ThreadWindows::SetNotAlive()
+{
+ _alive = false;
+}
+
+bool ThreadWindows::Shutdown()
+{
+ DWORD exitCode = 0;
+ BOOL ret = TRUE;
+ if (_thread)
+ {
+ ret = TerminateThread(_thread, exitCode);
+ _alive = false;
+ _dead = true;
+ _thread = NULL;
+ }
+ return ret == TRUE;
+}
+
+bool ThreadWindows::Stop()
+{
+ _critsectStop->Enter();
+ // Prevents the handle from being closed in ThreadWindows::Run()
+ _doNotCloseHandle = true;
+ _alive = false;
+ bool signaled = false;
+ if (_thread && !_dead)
+ {
+ _critsectStop->Leave();
+ // Wait up to 2 seconds for the thread to complete.
+ if( WAIT_OBJECT_0 == WaitForSingleObject(_thread, 2000))
+ {
+ signaled = true;
+ }
+ _critsectStop->Enter();
+ }
+ if (_thread)
+ {
+ CloseHandle(_thread);
+ _thread = NULL;
+ }
+ _critsectStop->Leave();
+
+ if (_dead || signaled)
+ {
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+void ThreadWindows::Run()
+{
+ _alive = true;
+ _dead = false;
+ _event->Set();
+
+ // All tracing must be after _event->Set to avoid deadlock in Trace.
+ if (_setThreadName)
+ {
+ WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, _id,
+ "Thread with name:%s started ", _name);
+ SetThreadName(-1, _name); // -1, set thread name for the calling thread.
+ }else
+ {
+ WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, _id,
+ "Thread without name started");
+ }
+
+ do
+ {
+ if (_runFunction)
+ {
+ if (!_runFunction(_obj))
+ {
+ _alive = false;
+ }
+ } else {
+ _alive = false;
+ }
+ } while(_alive);
+
+ if (_setThreadName)
+ {
+ WEBRTC_TRACE(kTraceStateInfo, kTraceUtility, _id,
+ "Thread with name:%s stopped", _name);
+ } else {
+ WEBRTC_TRACE(kTraceStateInfo, kTraceUtility,_id,
+ "Thread without name stopped");
+ }
+
+ _critsectStop->Enter();
+
+ if (_thread && !_doNotCloseHandle)
+ {
+ HANDLE thread = _thread;
+ _thread = NULL;
+ CloseHandle(thread);
+ }
+ _dead = true;
+
+ _critsectStop->Leave();
+};
+} // namespace webrtc
diff --git a/src/system_wrappers/source/thread_win.h b/src/system_wrappers/source/thread_win.h
new file mode 100644
index 0000000000..4fd7523ec9
--- /dev/null
+++ b/src/system_wrappers/source/thread_win.h
@@ -0,0 +1,66 @@
+/*
+ * 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_THREAD_WINDOWS_H_
+#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WINDOWS_H_
+
+#include "thread_wrapper.h"
+#include "event_wrapper.h"
+#include "critical_section_wrapper.h"
+
+#include <windows.h>
+
+namespace webrtc {
+
+class ThreadWindows : public ThreadWrapper
+{
+public:
+ ThreadWindows(ThreadRunFunction func, ThreadObj obj, ThreadPriority prio,
+ const char* threadName);
+ virtual ~ThreadWindows();
+
+ virtual bool Start(unsigned int& id);
+ bool SetAffinity(const int* processorNumbers,
+ const unsigned int amountOfProcessors);
+ virtual bool Stop();
+ virtual void SetNotAlive();
+
+ static unsigned int WINAPI StartThread(LPVOID lpParameter);
+
+ virtual bool Shutdown();
+
+protected:
+ virtual void Run();
+
+private:
+ ThreadRunFunction _runFunction;
+ ThreadObj _obj;
+
+ bool _alive;
+ bool _dead;
+
+ // TODO (hellner)
+ // _doNotCloseHandle member seem pretty redundant. Should be able to remove
+ // it. Basically it should be fine to reclaim the handle when calling stop
+ // and in the destructor.
+ bool _doNotCloseHandle;
+ ThreadPriority _prio;
+ EventWrapper* _event;
+ CriticalSectionWrapper* _critsectStop;
+
+ HANDLE _thread;
+ unsigned int _id;
+ char _name[kThreadMaxNameLength];
+ bool _setThreadName;
+
+};
+} // namespace webrtc
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_THREAD_WINDOWS_H_
diff --git a/src/system_wrappers/source/trace_impl.cc b/src/system_wrappers/source/trace_impl.cc
index 1156519eb9..c6d9296651 100644
--- a/src/system_wrappers/source/trace_impl.cc
+++ b/src/system_wrappers/source/trace_impl.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -17,17 +17,16 @@
#include "trace_win.h"
#else
#include <stdio.h>
-#include <time.h>
#include <stdarg.h>
#include "trace_posix.h"
#endif // _WIN32
+#include "system_wrappers/interface/sleep.h"
+
#define KEY_LEN_CHARS 31
#ifdef _WIN32
- #pragma warning(disable:4355)
-// VS 2005: Disable warnings for default initialized arrays.
- #pragma warning(disable:4351)
+#pragma warning(disable:4355)
#endif // _WIN32
namespace webrtc {
@@ -94,7 +93,7 @@ TraceImpl::TraceImpl()
for(int n = 0; n < WEBRTC_TRACE_MAX_QUEUE; n++)
{
_messageQueue[m][n] = new
- WebRtc_Word8[WEBRTC_TRACE_MAX_MESSAGE_SIZE];
+ char[WEBRTC_TRACE_MAX_MESSAGE_SIZE];
}
}
}
@@ -108,14 +107,7 @@ bool TraceImpl::StopThread()
// TODO (hellner): why not use condition variables to do this? Or let the
// worker thread die and let this thread flush remaining
// messages?
-#ifdef _WIN32
- Sleep(10);
-#else
- timespec t;
- t.tv_sec = 0;
- t.tv_nsec = 10*1000000;
- nanosleep(&t,NULL);
-#endif
+ SleepMs(10);
_thread.SetNotAlive();
// Make sure the thread finishes as quickly as possible (instead of having
@@ -147,6 +139,12 @@ TraceImpl::~TraceImpl()
}
}
+WebRtc_Word32 TraceImpl::AddThreadId(char* traceMessage) const {
+ WebRtc_UWord32 threadId = ThreadWrapper::GetThreadId();
+ // Messages is 12 characters.
+ return sprintf(traceMessage, "%10u; ", threadId);
+}
+
WebRtc_Word32 TraceImpl::AddLevel(char* szMessage, const TraceLevel level) const
{
switch (level)
@@ -277,9 +275,6 @@ WebRtc_Word32 TraceImpl::AddModuleAndId(char* traceMessage,
sprintf(traceMessage, " VIDEO PROC:%5ld %5ld;", idEngine,
idChannel);
break;
- default:
- assert(false);
- return 0;
}
} else {
switch (module)
@@ -335,16 +330,13 @@ WebRtc_Word32 TraceImpl::AddModuleAndId(char* traceMessage,
case kTraceVideoPreocessing:
sprintf (traceMessage, " VIDEO PROC:%11ld;", idl);
break;
- default:
- assert(false);
- return 0;
}
}
// All messages are 25 characters.
return 25;
}
-WebRtc_Word32 TraceImpl::SetTraceFileImpl(const WebRtc_Word8* fileNameUTF8,
+WebRtc_Word32 TraceImpl::SetTraceFileImpl(const char* fileNameUTF8,
const bool addFileCounter)
{
CriticalSectionScoped lock(_critsectInterface);
@@ -358,7 +350,7 @@ WebRtc_Word32 TraceImpl::SetTraceFileImpl(const WebRtc_Word8* fileNameUTF8,
{
_fileCountText = 1;
- WebRtc_Word8 fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize];
+ char fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize];
CreateFileName(fileNameUTF8, fileNameWithCounterUTF8,
_fileCountText);
if(_traceFile.OpenFile(fileNameWithCounterUTF8, false, false,
@@ -379,7 +371,7 @@ WebRtc_Word32 TraceImpl::SetTraceFileImpl(const WebRtc_Word8* fileNameUTF8,
}
WebRtc_Word32 TraceImpl::TraceFileImpl(
- WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize])
+ char fileNameUTF8[FileWrapper::kMaxFileNameSize])
{
CriticalSectionScoped lock(_critsectInterface);
return _traceFile.FileName(fileNameUTF8, FileWrapper::kMaxFileNameSize);
@@ -429,8 +421,14 @@ WebRtc_Word32 TraceImpl::AddMessage(
void TraceImpl::AddMessageToList(
const char traceMessage[WEBRTC_TRACE_MAX_MESSAGE_SIZE],
const WebRtc_UWord16 length,
- const TraceLevel level)
-{
+ const TraceLevel level) {
+#ifdef WEBRTC_DIRECT_TRACE
+ if (_callback) {
+ _callback->Print(level, traceMessage, length);
+ }
+ return;
+#endif
+
CriticalSectionScoped lock(_critsectArray);
if(_nextFreeIdx[_activeQueue] >= WEBRTC_TRACE_MAX_QUEUE)
@@ -550,8 +548,8 @@ void TraceImpl::WriteToFile()
_traceFile.Rewind();
} else
{
- WebRtc_Word8 oldFileName[FileWrapper::kMaxFileNameSize];
- WebRtc_Word8 newFileName[FileWrapper::kMaxFileNameSize];
+ char oldFileName[FileWrapper::kMaxFileNameSize];
+ char newFileName[FileWrapper::kMaxFileNameSize];
// get current name
_traceFile.FileName(oldFileName,
@@ -571,7 +569,7 @@ void TraceImpl::WriteToFile()
}
if(_rowCountText == 0)
{
- WebRtc_Word8 message[WEBRTC_TRACE_MAX_MESSAGE_SIZE + 1];
+ char message[WEBRTC_TRACE_MAX_MESSAGE_SIZE + 1];
WebRtc_Word32 length = AddDateTimeInfo(message);
if(length != -1)
{
@@ -637,7 +635,7 @@ void TraceImpl::AddImpl(const TraceLevel level, const TraceModule module,
ackLen += len;
len = AddThreadId(meassagePtr);
- if(len == -1)
+ if(len < 0)
{
return;
}
@@ -663,8 +661,8 @@ bool TraceImpl::TraceCheck(const TraceLevel level) const
}
bool TraceImpl::UpdateFileName(
- const WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize],
- WebRtc_Word8 fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
+ const char fileNameUTF8[FileWrapper::kMaxFileNameSize],
+ char fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
const WebRtc_UWord32 newCount) const
{
WebRtc_Word32 length = (WebRtc_Word32)strlen(fileNameUTF8);
@@ -706,8 +704,8 @@ bool TraceImpl::UpdateFileName(
}
bool TraceImpl::CreateFileName(
- const WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize],
- WebRtc_Word8 fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
+ const char fileNameUTF8[FileWrapper::kMaxFileNameSize],
+ char fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
const WebRtc_UWord32 newCount) const
{
WebRtc_Word32 length = (WebRtc_Word32)strlen(fileNameUTF8);
@@ -760,7 +758,7 @@ WebRtc_Word32 Trace::LevelFilter(WebRtc_UWord32& filter)
return 0;
}
-WebRtc_Word32 Trace::TraceFile(WebRtc_Word8 fileName[FileWrapper::kMaxFileNameSize])
+WebRtc_Word32 Trace::TraceFile(char fileName[FileWrapper::kMaxFileNameSize])
{
TraceImpl* trace = TraceImpl::GetTrace();
if(trace)
@@ -772,7 +770,7 @@ WebRtc_Word32 Trace::TraceFile(WebRtc_Word8 fileName[FileWrapper::kMaxFileNameSi
return -1;
}
-WebRtc_Word32 Trace::SetTraceFile(const WebRtc_Word8* fileName,
+WebRtc_Word32 Trace::SetTraceFile(const char* fileName,
const bool addFileCounter)
{
TraceImpl* trace = TraceImpl::GetTrace();
diff --git a/src/system_wrappers/source/trace_impl.h b/src/system_wrappers/source/trace_impl.h
index 455a3d5523..2b85813a88 100644
--- a/src/system_wrappers/source/trace_impl.h
+++ b/src/system_wrappers/source/trace_impl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -49,10 +49,10 @@ public:
static TraceImpl* CreateInstance();
static TraceImpl* GetTrace(const TraceLevel level = kTraceAll);
- WebRtc_Word32 SetTraceFileImpl(const WebRtc_Word8* fileName,
+ WebRtc_Word32 SetTraceFileImpl(const char* fileName,
const bool addFileCounter);
WebRtc_Word32 TraceFileImpl(
- WebRtc_Word8 fileName[FileWrapper::kMaxFileNameSize]);
+ char fileName[FileWrapper::kMaxFileNameSize]);
WebRtc_Word32 SetTraceCallbackImpl(TraceCallback* callback);
@@ -69,8 +69,9 @@ protected:
static TraceImpl* StaticInstance(CountOperation count_operation,
const TraceLevel level = kTraceAll);
+ WebRtc_Word32 AddThreadId(char* traceMessage) const;
+
// OS specific implementations
- virtual WebRtc_Word32 AddThreadId(char* traceMessage) const = 0;
virtual WebRtc_Word32 AddTime(char* traceMessage,
const TraceLevel level) const = 0;
@@ -98,13 +99,13 @@ private:
const TraceLevel level);
bool UpdateFileName(
- const WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize],
- WebRtc_Word8 fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
+ const char fileNameUTF8[FileWrapper::kMaxFileNameSize],
+ char fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
const WebRtc_UWord32 newCount) const;
bool CreateFileName(
- const WebRtc_Word8 fileNameUTF8[FileWrapper::kMaxFileNameSize],
- WebRtc_Word8 fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
+ const char fileNameUTF8[FileWrapper::kMaxFileNameSize],
+ char fileNameWithCounterUTF8[FileWrapper::kMaxFileNameSize],
const WebRtc_UWord32 newCount) const;
void WriteToFile();
@@ -123,7 +124,7 @@ private:
WebRtc_UWord16 _nextFreeIdx[WEBRTC_TRACE_NUM_ARRAY];
TraceLevel _level[WEBRTC_TRACE_NUM_ARRAY][WEBRTC_TRACE_MAX_QUEUE];
WebRtc_UWord16 _length[WEBRTC_TRACE_NUM_ARRAY][WEBRTC_TRACE_MAX_QUEUE];
- WebRtc_Word8* _messageQueue[WEBRTC_TRACE_NUM_ARRAY][WEBRTC_TRACE_MAX_QUEUE];
+ char* _messageQueue[WEBRTC_TRACE_NUM_ARRAY][WEBRTC_TRACE_MAX_QUEUE];
WebRtc_UWord8 _activeQueue;
};
} // namespace webrtc
diff --git a/src/system_wrappers/source/trace_impl_no_op.cc b/src/system_wrappers/source/trace_impl_no_op.cc
index 17528711bc..e74d901a54 100644
--- a/src/system_wrappers/source/trace_impl_no_op.cc
+++ b/src/system_wrappers/source/trace_impl_no_op.cc
@@ -31,12 +31,12 @@ WebRtc_Word32 Trace::LevelFilter(WebRtc_UWord32& /*filter*/)
}
WebRtc_Word32 Trace::TraceFile(
- WebRtc_Word8 /*fileName*/[1024])
+ char/*fileName*/[1024])
{
return -1;
}
-WebRtc_Word32 Trace::SetTraceFile(const WebRtc_Word8* /*fileName*/,
+WebRtc_Word32 Trace::SetTraceFile(const char* /*fileName*/,
const bool /*addFileCounter*/)
{
return -1;
diff --git a/src/system_wrappers/source/trace_posix.cc b/src/system_wrappers/source/trace_posix.cc
index 198c4349b0..1b8dd934d2 100644
--- a/src/system_wrappers/source/trace_posix.cc
+++ b/src/system_wrappers/source/trace_posix.cc
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ * 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
@@ -14,10 +14,8 @@
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
+#include <sys/time.h>
#include <time.h>
-#ifdef __linux__
- #include <sys/syscall.h>
-#endif
#ifdef WEBRTC_ANDROID
#include <pthread.h>
#else
@@ -41,8 +39,9 @@
namespace webrtc {
TracePosix::TracePosix()
{
- _prevAPITickCount = time(NULL);
- _prevTickCount = _prevAPITickCount;
+ struct timeval systemTimeHighRes;
+ gettimeofday(&systemTimeHighRes, 0);
+ _prevAPITickCount = _prevTickCount = systemTimeHighRes.tv_sec;
}
TracePosix::~TracePosix()
@@ -50,69 +49,47 @@ TracePosix::~TracePosix()
StopThread();
}
-WebRtc_Word32 TracePosix::AddThreadId(char* traceMessage) const {
-#ifdef __linux__
- pid_t threadId = (pid_t) syscall(__NR_gettid);
- sprintf(traceMessage, "%10d; ", threadId);
-#else
- WebRtc_UWord64 threadId = (WebRtc_UWord64)pthread_self();
- sprintf(traceMessage, "%10llu; ",
- static_cast<long long unsigned int>(threadId));
-#endif
- // 12 bytes are written.
- return 12;
-}
-
WebRtc_Word32 TracePosix::AddTime(char* traceMessage,
const TraceLevel level) const
{
- time_t dwCurrentTimeInSeconds = time(NULL);
- struct tm systemTime;
- gmtime_r(&dwCurrentTimeInSeconds, &systemTime);
-
- if(level == kTraceApiCall)
+ struct timeval systemTimeHighRes;
+ if (gettimeofday(&systemTimeHighRes, 0) == -1)
{
- WebRtc_UWord32 dwDeltaTime = dwCurrentTimeInSeconds - _prevTickCount;
- _prevTickCount = dwCurrentTimeInSeconds;
-
- if(_prevTickCount == 0)
- {
- dwDeltaTime = 0;
- }
- if(dwDeltaTime > 0x0fffffff)
- {
- // Either wraparound or data race.
- dwDeltaTime = 0;
- }
- if(dwDeltaTime > 99999)
- {
- dwDeltaTime = 99999;
- }
+ return -1;
+ }
+ struct tm buffer;
+ const struct tm* systemTime =
+ localtime_r(&systemTimeHighRes.tv_sec, &buffer);
- sprintf(traceMessage, "(%2u:%2u:%2u:%3u |%5lu) ", systemTime.tm_hour,
- systemTime.tm_min, systemTime.tm_sec, 0,
- static_cast<unsigned long>(dwDeltaTime));
+ const WebRtc_UWord32 ms_time = systemTimeHighRes.tv_usec / 1000;
+ WebRtc_UWord32 prevTickCount = 0;
+ if (level == kTraceApiCall)
+ {
+ prevTickCount = _prevTickCount;
+ _prevTickCount = ms_time;
} else {
- WebRtc_UWord32 dwDeltaTime = dwCurrentTimeInSeconds - _prevAPITickCount;
- _prevAPITickCount = dwCurrentTimeInSeconds;
- if(_prevAPITickCount == 0)
- {
- dwDeltaTime = 0;
- }
- if(dwDeltaTime > 0x0fffffff)
- {
- // Either wraparound or data race.
- dwDeltaTime = 0;
- }
- if(dwDeltaTime > 99999)
- {
- dwDeltaTime = 99999;
- }
- sprintf(traceMessage, "(%2u:%2u:%2u:%3u |%5lu) ", systemTime.tm_hour,
- systemTime.tm_min, systemTime.tm_sec, 0,
- static_cast<unsigned long>(dwDeltaTime));
+ prevTickCount = _prevAPITickCount;
+ _prevAPITickCount = ms_time;
+ }
+ WebRtc_UWord32 dwDeltaTime = ms_time - prevTickCount;
+ if (prevTickCount == 0)
+ {
+ dwDeltaTime = 0;
+ }
+ if (dwDeltaTime > 0x0fffffff)
+ {
+ // Either wraparound or data race.
+ dwDeltaTime = 0;
+ }
+ if(dwDeltaTime > 99999)
+ {
+ dwDeltaTime = 99999;
}
- // Messages is 22 characters.
+
+ sprintf(traceMessage, "(%2u:%2u:%2u:%3u |%5lu) ", systemTime->tm_hour,
+ systemTime->tm_min, systemTime->tm_sec, ms_time,
+ static_cast<unsigned long>(dwDeltaTime));
+ // Messages are 22 characters.
return 22;
}
@@ -127,7 +104,8 @@ WebRtc_Word32 TracePosix::AddDateTimeInfo(char* traceMessage) const
{
time_t t;
time(&t);
- sprintf(traceMessage, "Local Date: %s", ctime(&t));
+ char buffer[26]; // man ctime says buffer should have room for >=26 bytes.
+ sprintf(traceMessage, "Local Date: %s", ctime_r(&t, buffer));
WebRtc_Word32 len = static_cast<WebRtc_Word32>(strlen(traceMessage));
if ('\n' == traceMessage[len - 1])
diff --git a/src/system_wrappers/source/trace_posix.h b/src/system_wrappers/source/trace_posix.h
index 099bcc874e..8c37cd2b4e 100644
--- a/src/system_wrappers/source/trace_posix.h
+++ b/src/system_wrappers/source/trace_posix.h
@@ -21,7 +21,6 @@ public:
TracePosix();
virtual ~TracePosix();
- virtual WebRtc_Word32 AddThreadId(char *traceMessage) const;
virtual WebRtc_Word32 AddTime(char* traceMessage,
const TraceLevel level) const;
diff --git a/src/system_wrappers/source/trace_unittest.cc b/src/system_wrappers/source/trace_unittest.cc
new file mode 100644
index 0000000000..982e715726
--- /dev/null
+++ b/src/system_wrappers/source/trace_unittest.cc
@@ -0,0 +1,57 @@
+/*
+ * 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/trace.h"
+
+#include "gtest/gtest.h"
+#include "system_wrappers/source/cpu_measurement_harness.h"
+#include "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/src/system_wrappers/source/trace_win.cc b/src/system_wrappers/source/trace_win.cc
new file mode 100644
index 0000000000..f81ed8b044
--- /dev/null
+++ b/src/system_wrappers/source/trace_win.cc
@@ -0,0 +1,131 @@
+/*
+ * 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 "trace_win.h"
+
+#include <cassert>
+#include <stdarg.h>
+
+#include "Mmsystem.h"
+
+#if defined(_DEBUG)
+ #define BUILDMODE "d"
+#elif defined(DEBUG)
+ #define BUILDMODE "d"
+#elif defined(NDEBUG)
+ #define BUILDMODE "r"
+#else
+ #define BUILDMODE "?"
+#endif
+#define BUILDTIME __TIME__
+#define BUILDDATE __DATE__
+// Example: "Oct 10 2002 12:05:30 r"
+#define BUILDINFO BUILDDATE " " BUILDTIME " " BUILDMODE
+
+namespace webrtc {
+TraceWindows::TraceWindows()
+ : _prevAPITickCount(0),
+ _prevTickCount(0)
+{
+}
+
+TraceWindows::~TraceWindows()
+{
+ StopThread();
+}
+
+WebRtc_Word32 TraceWindows::AddTime(char* traceMessage,
+ const TraceLevel level) const
+{
+ WebRtc_UWord32 dwCurrentTime = timeGetTime();
+ SYSTEMTIME systemTime;
+ GetSystemTime(&systemTime);
+
+ if(level == kTraceApiCall)
+ {
+ WebRtc_UWord32 dwDeltaTime = dwCurrentTime- _prevTickCount;
+ _prevTickCount = dwCurrentTime;
+
+ if(_prevTickCount == 0)
+ {
+ dwDeltaTime = 0;
+ }
+ if(dwDeltaTime > 0x0fffffff)
+ {
+ // Either wraparound or data race.
+ dwDeltaTime = 0;
+ }
+ if(dwDeltaTime > 99999)
+ {
+ dwDeltaTime = 99999;
+ }
+
+ sprintf (traceMessage, "(%2u:%2u:%2u:%3u |%5lu) ", systemTime.wHour,
+ systemTime.wMinute, systemTime.wSecond,
+ systemTime.wMilliseconds, dwDeltaTime);
+ } else {
+ WebRtc_UWord32 dwDeltaTime = dwCurrentTime - _prevAPITickCount;
+ _prevAPITickCount = dwCurrentTime;
+
+ if(_prevAPITickCount == 0)
+ {
+ dwDeltaTime = 0;
+ }
+ if(dwDeltaTime > 0x0fffffff)
+ {
+ // Either wraparound or data race.
+ dwDeltaTime = 0;
+ }
+ if(dwDeltaTime > 99999)
+ {
+ dwDeltaTime = 99999;
+ }
+ sprintf (traceMessage, "(%2u:%2u:%2u:%3u |%5lu) ", systemTime.wHour,
+ systemTime.wMinute, systemTime.wSecond,
+ systemTime.wMilliseconds, dwDeltaTime);
+ }
+ // Messages is 12 characters.
+ return 22;
+}
+
+WebRtc_Word32 TraceWindows::AddBuildInfo(char* traceMessage) const
+{
+ // write data and time to text file
+ sprintf(traceMessage, "Build info: %s", BUILDINFO);
+ // Include NULL termination (hence + 1).
+ return static_cast<WebRtc_Word32>(strlen(traceMessage)+1);
+}
+
+WebRtc_Word32 TraceWindows::AddDateTimeInfo(char* traceMessage) const
+{
+ _prevAPITickCount = timeGetTime();
+ _prevTickCount = _prevAPITickCount;
+
+ SYSTEMTIME sysTime;
+ GetLocalTime (&sysTime);
+
+ TCHAR szDateStr[20];
+ TCHAR szTimeStr[20];
+
+ // Create date string (e.g. Apr 04 2002)
+ GetDateFormat(LOCALE_SYSTEM_DEFAULT, 0, &sysTime, TEXT("MMM dd yyyy"),
+ szDateStr, 20);
+
+ // Create time string (e.g. 15:32:08)
+ GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, &sysTime, TEXT("HH':'mm':'ss"),
+ szTimeStr, 20);
+
+ sprintf(traceMessage, "Local Date: %s Local Time: %s", szDateStr,
+ szTimeStr);
+
+ // Include NULL termination (hence + 1).
+ return static_cast<WebRtc_Word32>(strlen(traceMessage)+ 1);
+}
+} // namespace webrtc
diff --git a/src/system_wrappers/source/trace_win.h b/src/system_wrappers/source/trace_win.h
new file mode 100644
index 0000000000..803198e0fb
--- /dev/null
+++ b/src/system_wrappers/source/trace_win.h
@@ -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.
+ */
+
+#ifndef WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_WINDOWS_H_
+#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_WINDOWS_H_
+
+#include "trace_impl.h"
+#include <stdio.h>
+#include <windows.h>
+
+namespace webrtc {
+class TraceWindows : public TraceImpl
+{
+public:
+ TraceWindows();
+ virtual ~TraceWindows();
+
+ virtual WebRtc_Word32 AddTime(char* traceMessage,
+ const TraceLevel level) const;
+
+ virtual WebRtc_Word32 AddBuildInfo(char* traceMessage) const;
+ virtual WebRtc_Word32 AddDateTimeInfo(char* traceMessage) const;
+private:
+ volatile mutable WebRtc_UWord32 _prevAPITickCount;
+ volatile mutable WebRtc_UWord32 _prevTickCount;
+};
+} // namespace webrtc
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_TRACE_WINDOWS_H_
diff --git a/src/system_wrappers/source/unittest_utilities.h b/src/system_wrappers/source/unittest_utilities.h
new file mode 100644
index 0000000000..771d798f5d
--- /dev/null
+++ b/src/system_wrappers/source/unittest_utilities.h
@@ -0,0 +1,83 @@
+/*
+ * 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 WEBRTC_SYSTEM_WRAPPERS_SOURCE_UNITTEST_UTILITIES_H_
+#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_UNITTEST_UTILITIES_H_
+
+// This file contains utilities that make it simpler to write unittests
+// that are appropriate for the system_wrappers classes.
+
+#include <stdio.h>
+#include <string.h>
+
+#include "system_wrappers/interface/trace.h"
+
+namespace webrtc {
+
+class TestTraceCallback : public TraceCallback {
+ public:
+ virtual void Print(const TraceLevel level,
+ const char* traceString,
+ const int length) {
+ if (traceString) {
+ char* cmd_print = new char[length+1];
+ memcpy(cmd_print, traceString, length);
+ cmd_print[length] = '\0';
+ printf("%s\n", cmd_print);
+ fflush(stdout);
+ delete[] cmd_print;
+ }
+ }
+};
+
+// A class that turns on tracing to stdout at the beginning of the test,
+// and turns it off once the test is finished.
+// Intended usage:
+// class SomeTest : public ::testing::Test {
+// protected:
+// SomeTest()
+// : trace_(false) {} // Change to true to turn on tracing.
+// private:
+// ScopedTracing trace_;
+// }
+class ScopedTracing {
+ public:
+ explicit ScopedTracing(bool logOn) {
+ logging_ = logOn;
+ StartTrace();
+ }
+
+ ~ScopedTracing() {
+ StopTrace();
+ }
+
+ private:
+ void StartTrace() {
+ if (logging_) {
+ Trace::CreateTrace();
+ Trace::SetLevelFilter(webrtc::kTraceAll);
+ Trace::SetTraceCallback(&trace_);
+ }
+ }
+
+ void StopTrace() {
+ if (logging_) {
+ Trace::ReturnTrace();
+ }
+ }
+
+ private:
+ bool logging_;
+ TestTraceCallback trace_;
+};
+
+} // namespace webrtc
+
+#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_UNITTEST_UTILITIES_H_
diff --git a/src/system_wrappers/source/unittest_utilities_unittest.cc b/src/system_wrappers/source/unittest_utilities_unittest.cc
new file mode 100644
index 0000000000..6e9a0c6186
--- /dev/null
+++ b/src/system_wrappers/source/unittest_utilities_unittest.cc
@@ -0,0 +1,34 @@
+/*
+ * 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/source/unittest_utilities.h"
+
+#include "gtest/gtest.h"
+#include "system_wrappers/interface/trace.h"
+
+namespace webrtc {
+
+// These tests merely check that the code compiles and that no
+// fatal accidents happen when logging.
+TEST(UnittestUtilities, TraceOn) {
+ ScopedTracing trace(true);
+ WEBRTC_TRACE(kTraceInfo, kTraceUtility, 0, "Log line that should appear");
+ // TODO(hta): Verify that output appears.
+ // Note - output is written on another thread, so can take time to appear.
+}
+
+TEST(UnittestUtilities, TraceOff) {
+ ScopedTracing trace(false);
+ WEBRTC_TRACE(kTraceInfo, kTraceUtility, 0,
+ "Log line that should not appear");
+ // TODO(hta): Verify that no output appears.
+}
+
+} // namespace webrtc