From ad9e9c0349e3486adfac62ed819060805e43d932 Mon Sep 17 00:00:00 2001 From: Nicolas Dufresne Date: Mon, 4 Jul 2016 22:12:20 -0400 Subject: [PATCH] Add missing windows conditions variable Those are used by generic RW lock implementation. https://bugs.freedesktop.org/show_bug.cgi?id=96754 --- webrtc/system_wrappers/Makefile.am | 37 +++- .../include/condition_variable_wrapper.h | 42 +++++ .../system_wrappers/source/condition_variable.cc | 41 +++++ .../source/condition_variable_event_win.cc | 195 +++++++++++++++++++++ .../source/condition_variable_event_win.h | 46 +++++ .../source/condition_variable_native_win.cc | 104 +++++++++++ .../source/condition_variable_native_win.h | 54 ++++++ 7 files changed, 511 insertions(+), 8 deletions(-) create mode 100644 webrtc/system_wrappers/include/condition_variable_wrapper.h create mode 100644 webrtc/system_wrappers/source/condition_variable.cc create mode 100644 webrtc/system_wrappers/source/condition_variable_event_win.cc create mode 100644 webrtc/system_wrappers/source/condition_variable_event_win.h create mode 100644 webrtc/system_wrappers/source/condition_variable_native_win.cc create mode 100644 webrtc/system_wrappers/source/condition_variable_native_win.h diff --git a/webrtc/system_wrappers/Makefile.am b/webrtc/system_wrappers/Makefile.am index 8215013..4838d82 100644 --- a/webrtc/system_wrappers/Makefile.am +++ b/webrtc/system_wrappers/Makefile.am @@ -2,6 +2,7 @@ noinst_LTLIBRARIES = libsystem_wrappers.la noinst_HEADERS = include/aligned_array.h \ include/asm_defines.h \ + include/condition_variable_wrapper.h \ include/compile_assert_c.h \ include/event_wrapper.h \ include/scoped_vector.h \ @@ -42,27 +43,47 @@ libsystem_wrappers_la_SOURCES = include/aligned_malloc.h \ source/trace_impl.h \ source/trace_posix.h \ source/trace_win.h + +EXTRA_DIST = BUILD.gn + if HAVE_POSIX libsystem_wrappers_la_SOURCES += source/critical_section_posix.cc \ source/event_timer_posix.cc \ source/rw_lock_posix.cc \ source/thread_posix.cc \ source/trace_posix.cc +else +EXTRA_DIST += source/critical_section_posix.cc \ + source/event_timer_posix.cc \ + source/rw_lock_posix.cc \ + source/thread_posix.cc \ + source/trace_posix.cc endif + if HAVE_WIN libsystem_wrappers_la_SOURCES += source/critical_section_win.cc \ + source/condition_variable.cc \ + source/condition_variable_event_win.cc \ + source/condition_variable_event_win.h \ + source/condition_variable_native_win.cc \ + source/condition_variable_native_win.h \ source/event_timer_win.cc \ source/rw_lock_win.cc \ source/rw_lock_generic.cc \ source/thread_win.cc \ source/trace_win.cc +else +EXTRA_DIST += source/critical_section_win.cc \ + source/condition_variable.cc \ + source/condition_variable_event_win.cc \ + source/condition_variable_event_win.h \ + source/condition_variable_native_win.cc \ + source/condition_variable_native_win.h \ + source/event_timer_win.cc \ + source/rw_lock_generic.cc \ + source/rw_lock_win.cc \ + source/thread_win.cc \ + source/trace_win.cc endif -libsystem_wrappers_la_CXXFLAGS = $(AM_CXXFLAGS) $(COMMON_CXXFLAGS) -EXTRA_DIST = BUILD.gn \ - source/critical_section_win.cc \ - source/event_timer_win.cc \ - source/rw_lock_generic.cc \ - source/rw_lock_win.cc \ - source/thread_win.cc \ - source/trace_win.cc +libsystem_wrappers_la_CXXFLAGS = $(AM_CXXFLAGS) $(COMMON_CXXFLAGS) diff --git a/webrtc/system_wrappers/include/condition_variable_wrapper.h b/webrtc/system_wrappers/include/condition_variable_wrapper.h new file mode 100644 index 0000000..37ca30f --- /dev/null +++ b/webrtc/system_wrappers/include/condition_variable_wrapper.h @@ -0,0 +1,42 @@ +/* + * 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_INCLUDE_CONDITION_VARIABLE_WRAPPER_H_ +#define WEBRTC_SYSTEM_WRAPPERS_INCLUDE_CONDITION_VARIABLE_WRAPPER_H_ + +namespace webrtc { + +class CriticalSectionWrapper; + +class ConditionVariableWrapper { + public: + // Factory method, constructor disabled. + static ConditionVariableWrapper* CreateConditionVariable(); + + virtual ~ConditionVariableWrapper() {} + + // Calling thread will atomically release crit_sect and wait until next + // some other thread calls Wake() or WakeAll(). + virtual void SleepCS(CriticalSectionWrapper& crit_sect) = 0; + + // Same as above but with a timeout. + virtual bool SleepCS(CriticalSectionWrapper& crit_sect, + unsigned long max_time_in_ms) = 0; + + // Wakes one thread calling SleepCS(). + virtual void Wake() = 0; + + // Wakes all threads calling SleepCS(). + virtual void WakeAll() = 0; +}; + +} // namespace webrtc + +#endif // WEBRTC_SYSTEM_WRAPPERS_INCLUDE_CONDITION_VARIABLE_WRAPPER_H_ diff --git a/webrtc/system_wrappers/source/condition_variable.cc b/webrtc/system_wrappers/source/condition_variable.cc new file mode 100644 index 0000000..f5ae93a --- /dev/null +++ b/webrtc/system_wrappers/source/condition_variable.cc @@ -0,0 +1,41 @@ +/* + * 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 "webrtc/system_wrappers/include/condition_variable_wrapper.h" + +#if defined(_WIN32) +#include +#include "webrtc/system_wrappers/source/condition_variable_event_win.h" +#include "webrtc/system_wrappers/source/condition_variable_native_win.h" +#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) +#include +#include "webrtc/system_wrappers/source/condition_variable_posix.h" +#endif + +namespace webrtc { + +ConditionVariableWrapper* ConditionVariableWrapper::CreateConditionVariable() { +#if defined(_WIN32) + // Try to create native condition variable implementation. + ConditionVariableWrapper* ret_val = ConditionVariableNativeWin::Create(); + if (!ret_val) { + // Native condition variable implementation does not exist. Create generic + // condition variable based on events. + ret_val = new ConditionVariableEventWin(); + } + return ret_val; +#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) + return ConditionVariablePosix::Create(); +#else + return NULL; +#endif +} + +} // namespace webrtc diff --git a/webrtc/system_wrappers/source/condition_variable_event_win.cc b/webrtc/system_wrappers/source/condition_variable_event_win.cc new file mode 100644 index 0000000..41b019d --- /dev/null +++ b/webrtc/system_wrappers/source/condition_variable_event_win.cc @@ -0,0 +1,195 @@ +/* +Source: +http://www1.cse.wustl.edu/~schmidt/ACE-copying.html + +License: +Copyright and Licensing Information for ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM), +and CoSMIC(TM) + +ACE(TM), TAO(TM), CIAO(TM), DAnCE>(TM), and CoSMIC(TM) (henceforth referred to +as "DOC software") are copyrighted by Douglas C. Schmidt and his research +group at Washington University, University of California, Irvine, and +Vanderbilt University, Copyright (c) 1993-2009, all rights reserved. Since DOC +software is open-source, freely available software, you are free to use, +modify, copy, and distribute--perpetually and irrevocably--the DOC software +source code and object code produced from the source, as well as copy and +distribute modified versions of this software. You must, however, include this +copyright statement along with any code built using DOC software that you +release. No copyright statement needs to be provided if you just ship binary +executables of your software products. +You can use DOC software in commercial and/or binary software releases and are +under no obligation to redistribute any of your source code that is built +using DOC software. Note, however, that you may not misappropriate the DOC +software code, such as copyrighting it yourself or claiming authorship of the +DOC software code, in a way that will prevent DOC software from being +distributed freely using an open-source development model. You needn't inform +anyone that you're using DOC software in your software, though we encourage +you to let us know so we can promote your project in the DOC software success +stories. + +The ACE, TAO, CIAO, DAnCE, and CoSMIC web sites are maintained by the DOC +Group at the Institute for Software Integrated Systems (ISIS) and the Center +for Distributed Object Computing of Washington University, St. Louis for the +development of open-source software as part of the open-source software +community. Submissions are provided by the submitter ``as is'' with no +warranties whatsoever, including any warranty of merchantability, +noninfringement of third party intellectual property, or fitness for any +particular purpose. In no event shall the submitter be liable for any direct, +indirect, special, exemplary, punitive, or consequential damages, including +without limitation, lost profits, even if advised of the possibility of such +damages. Likewise, DOC software is provided as is with no warranties of any +kind, including the warranties of design, merchantability, and fitness for a +particular purpose, noninfringement, or arising from a course of dealing, +usage or trade practice. Washington University, UC Irvine, Vanderbilt +University, their employees, and students shall have no liability with respect +to the infringement of copyrights, trade secrets or any patents by DOC +software or any part thereof. Moreover, in no event will Washington +University, UC Irvine, or Vanderbilt University, their employees, or students +be liable for any lost revenue or profits or other special, indirect and +consequential damages. + +DOC software is provided with no support and without any obligation on the +part of Washington University, UC Irvine, Vanderbilt University, their +employees, or students to assist in its use, correction, modification, or +enhancement. A number of companies around the world provide commercial support +for DOC software, however. DOC software is Y2K-compliant, as long as the +underlying OS platform is Y2K-compliant. Likewise, DOC software is compliant +with the new US daylight savings rule passed by Congress as "The Energy Policy +Act of 2005," which established new daylight savings times (DST) rules for the +United States that expand DST as of March 2007. Since DOC software obtains +time/date and calendaring information from operating systems users will not be +affected by the new DST rules as long as they upgrade their operating systems +accordingly. + +The names ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM), CoSMIC(TM), Washington +University, UC Irvine, and Vanderbilt University, may not be used to endorse +or promote products or services derived from this source without express +written permission from Washington University, UC Irvine, or Vanderbilt +University. This license grants no permission to call products or services +derived from this source ACE(TM), TAO(TM), CIAO(TM), DAnCE(TM), or CoSMIC(TM), +nor does it grant permission for the name Washington University, UC Irvine, or +Vanderbilt University to appear in their names. +*/ + +/* + * 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. + */ + +#include "webrtc/system_wrappers/source/condition_variable_event_win.h" +#include "webrtc/system_wrappers/source/critical_section_win.h" + +namespace webrtc { + +ConditionVariableEventWin::ConditionVariableEventWin() : eventID_(WAKEALL_0) { + memset(&num_waiters_[0], 0, sizeof(num_waiters_)); + + InitializeCriticalSection(&num_waiters_crit_sect_); + + 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 +} + +ConditionVariableEventWin::~ConditionVariableEventWin() { + CloseHandle(events_[WAKE]); + CloseHandle(events_[WAKEALL_1]); + CloseHandle(events_[WAKEALL_0]); + + DeleteCriticalSection(&num_waiters_crit_sect_); +} + +void ConditionVariableEventWin::SleepCS(CriticalSectionWrapper& crit_sect) { + SleepCS(crit_sect, INFINITE); +} + +bool ConditionVariableEventWin::SleepCS(CriticalSectionWrapper& crit_sect, + unsigned long max_time_in_ms) { + EnterCriticalSection(&num_waiters_crit_sect_); + + // 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; + + ++(num_waiters_[eventID]); + LeaveCriticalSection(&num_waiters_crit_sect_); + + CriticalSectionWindows* cs = + static_cast(&crit_sect); + 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. + max_time_in_ms); + + const bool ret_val = (result != WAIT_TIMEOUT); + + EnterCriticalSection(&num_waiters_crit_sect_); + --(num_waiters_[eventID]); + + // Last waiter should only be true for WakeAll(). WakeAll() correspond + // to position 1 in events[] -> (result == WAIT_OBJECT_0 + 1) + const bool last_waiter = (result == WAIT_OBJECT_0 + 1) && + (num_waiters_[eventID] == 0); + LeaveCriticalSection(&num_waiters_crit_sect_); + + if (last_waiter) { + // Reset/unset the WakeAll() event since all threads have been + // released. + ResetEvent(events_[eventID]); + } + + EnterCriticalSection(&cs->crit); + return ret_val; +} + +void ConditionVariableEventWin::Wake() { + EnterCriticalSection(&num_waiters_crit_sect_); + const bool have_waiters = (num_waiters_[WAKEALL_0] > 0) || + (num_waiters_[WAKEALL_1] > 0); + LeaveCriticalSection(&num_waiters_crit_sect_); + + if (have_waiters) { + SetEvent(events_[WAKE]); + } +} + +void ConditionVariableEventWin::WakeAll() { + EnterCriticalSection(&num_waiters_crit_sect_); + + // Update current WakeAll() event + eventID_ = (WAKEALL_0 == eventID_) ? WAKEALL_1 : WAKEALL_0; + + // Trigger current event + const EventWakeUpType eventID = eventID_; + const bool have_waiters = num_waiters_[eventID] > 0; + LeaveCriticalSection(&num_waiters_crit_sect_); + + if (have_waiters) { + SetEvent(events_[eventID]); + } +} + +} // namespace webrtc diff --git a/webrtc/system_wrappers/source/condition_variable_event_win.h b/webrtc/system_wrappers/source/condition_variable_event_win.h new file mode 100644 index 0000000..cdcef7d --- /dev/null +++ b/webrtc/system_wrappers/source/condition_variable_event_win.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013 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_EVENT_WIN_H_ +#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_EVENT_WIN_H_ + +#include + +#include "webrtc/system_wrappers/include/condition_variable_wrapper.h" + +namespace webrtc { + +class ConditionVariableEventWin : public ConditionVariableWrapper { + public: + ConditionVariableEventWin(); + virtual ~ConditionVariableEventWin(); + + void SleepCS(CriticalSectionWrapper& crit_sect); + bool SleepCS(CriticalSectionWrapper& crit_sect, unsigned long max_time_inMS); + void Wake(); + void WakeAll(); + + private: + enum EventWakeUpType { + WAKEALL_0 = 0, + WAKEALL_1 = 1, + WAKE = 2, + EVENT_COUNT = 3 + }; + + unsigned int num_waiters_[2]; + EventWakeUpType eventID_; + CRITICAL_SECTION num_waiters_crit_sect_; + HANDLE events_[EVENT_COUNT]; +}; + +} // namespace webrtc + +#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_EVENT_WIN_H_ diff --git a/webrtc/system_wrappers/source/condition_variable_native_win.cc b/webrtc/system_wrappers/source/condition_variable_native_win.cc new file mode 100644 index 0000000..45225f2 --- /dev/null +++ b/webrtc/system_wrappers/source/condition_variable_native_win.cc @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2013 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 "webrtc/system_wrappers/include/trace.h" +#include "webrtc/system_wrappers/source/condition_variable_native_win.h" +#include "webrtc/system_wrappers/source/critical_section_win.h" + +namespace webrtc { + +static HMODULE library = NULL; +static bool win_support_condition_variables_primitive = false; + +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); + +ConditionVariableNativeWin::ConditionVariableNativeWin() { +} + +ConditionVariableNativeWin::~ConditionVariableNativeWin() { +} + +ConditionVariableWrapper* ConditionVariableNativeWin::Create() { + ConditionVariableNativeWin* ret_val = new ConditionVariableNativeWin(); + if (!ret_val->Init()) { + delete ret_val; + return NULL; + } + return ret_val; +} + +bool ConditionVariableNativeWin::Init() { + if (!library) { + // Native implementation is supported on Vista+. + library = LoadLibrary(TEXT("Kernel32.dll")); + // TODO(henrike): this code results in an attempt to load the above dll + // every time the previous attempt failed. Only try to load once. + if (library) { + // TODO(henrike): not thread safe as reading and writing to library is not + // serialized. Fix. + 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"); + win_support_condition_variables_primitive = true; + } + } + } + if (!win_support_condition_variables_primitive) { + return false; + } + PInitializeConditionVariable_(&condition_variable_); + return true; +} + +void ConditionVariableNativeWin::SleepCS(CriticalSectionWrapper& crit_sect) { + SleepCS(crit_sect, INFINITE); +} + +bool ConditionVariableNativeWin::SleepCS(CriticalSectionWrapper& crit_sect, + unsigned long max_time_in_ms) { + CriticalSectionWindows* cs = + static_cast(&crit_sect); + BOOL ret_val = PSleepConditionVariableCS_(&condition_variable_, + &(cs->crit), max_time_in_ms); + return ret_val != 0; +} + +void ConditionVariableNativeWin::Wake() { + PWakeConditionVariable_(&condition_variable_); +} + +void ConditionVariableNativeWin::WakeAll() { + PWakeAllConditionVariable_(&condition_variable_); +} + +} // namespace webrtc diff --git a/webrtc/system_wrappers/source/condition_variable_native_win.h b/webrtc/system_wrappers/source/condition_variable_native_win.h new file mode 100644 index 0000000..c22787f --- /dev/null +++ b/webrtc/system_wrappers/source/condition_variable_native_win.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2013 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_NATIVE_WIN_H_ +#define WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_NATIVE_WIN_H_ + +#include + +#include "webrtc/system_wrappers/include/condition_variable_wrapper.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 ConditionVariableNativeWin : public ConditionVariableWrapper { + public: + static ConditionVariableWrapper* Create(); + virtual ~ConditionVariableNativeWin(); + + void SleepCS(CriticalSectionWrapper& crit_sect); + bool SleepCS(CriticalSectionWrapper& crit_sect, unsigned long max_time_inMS); + void Wake(); + void WakeAll(); + + private: + ConditionVariableNativeWin(); + + bool Init(); + + CONDITION_VARIABLE condition_variable_; +}; + +} // namespace webrtc + +#endif // WEBRTC_SYSTEM_WRAPPERS_SOURCE_CONDITION_VARIABLE_NATIVE_WIN_H_ -- 2.7.4