Add missing windows conditions variable

Those are used by generic RW lock implementation.

https://bugs.freedesktop.org/show_bug.cgi?id=96754
This commit is contained in:
Nicolas Dufresne 2016-07-04 22:12:20 -04:00 committed by Arun Raghavan
parent db2f422578
commit 6ad2f51e9e
7 changed files with 514 additions and 9 deletions

View File

@ -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,49 @@ 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/event_timer_win.cc \
source/rw_lock_win.cc \
source/rw_lock_generic.cc \
source/thread_win.cc \
source/trace_win.cc
endif
libsystem_wrappers_la_CXXFLAGS = $(AM_CXXFLAGS) $(COMMON_CXXFLAGS)
EXTRA_DIST = BUILD.gn \
if HAVE_WIN
libsystem_wrappers_la_SOURCES += include/fix_interlocked_exchange_pointer_win.h \
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 += include/fix_interlocked_exchange_pointer_win.h \
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)

View File

@ -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_

View File

@ -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 <windows.h>
#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 <pthread.h>
#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

View File

@ -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<CriticalSectionWindows*>(&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

View File

@ -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 <windows.h>
#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_

View File

@ -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<CriticalSectionWindows*>(&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

View File

@ -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 <windows.h>
#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_