diff options
Diffstat (limited to 'security/sandbox/chromium/base/synchronization')
9 files changed, 0 insertions, 1190 deletions
diff --git a/security/sandbox/chromium/base/synchronization/condition_variable.h b/security/sandbox/chromium/base/synchronization/condition_variable.h deleted file mode 100644 index a41b2ba5a..000000000 --- a/security/sandbox/chromium/base/synchronization/condition_variable.h +++ /dev/null @@ -1,118 +0,0 @@ -// Copyright (c) 2011 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. - -// ConditionVariable wraps pthreads condition variable synchronization or, on -// Windows, simulates it. This functionality is very helpful for having -// several threads wait for an event, as is common with a thread pool managed -// by a master. The meaning of such an event in the (worker) thread pool -// scenario is that additional tasks are now available for processing. It is -// used in Chrome in the DNS prefetching system to notify worker threads that -// a queue now has items (tasks) which need to be tended to. A related use -// would have a pool manager waiting on a ConditionVariable, waiting for a -// thread in the pool to announce (signal) that there is now more room in a -// (bounded size) communications queue for the manager to deposit tasks, or, -// as a second example, that the queue of tasks is completely empty and all -// workers are waiting. -// -// USAGE NOTE 1: spurious signal events are possible with this and -// most implementations of condition variables. As a result, be -// *sure* to retest your condition before proceeding. The following -// is a good example of doing this correctly: -// -// while (!work_to_be_done()) Wait(...); -// -// In contrast do NOT do the following: -// -// if (!work_to_be_done()) Wait(...); // Don't do this. -// -// Especially avoid the above if you are relying on some other thread only -// issuing a signal up *if* there is work-to-do. There can/will -// be spurious signals. Recheck state on waiting thread before -// assuming the signal was intentional. Caveat caller ;-). -// -// USAGE NOTE 2: Broadcast() frees up all waiting threads at once, -// which leads to contention for the locks they all held when they -// called Wait(). This results in POOR performance. A much better -// approach to getting a lot of threads out of Wait() is to have each -// thread (upon exiting Wait()) call Signal() to free up another -// Wait'ing thread. Look at condition_variable_unittest.cc for -// both examples. -// -// Broadcast() can be used nicely during teardown, as it gets the job -// done, and leaves no sleeping threads... and performance is less -// critical at that point. -// -// The semantics of Broadcast() are carefully crafted so that *all* -// threads that were waiting when the request was made will indeed -// get signaled. Some implementations mess up, and don't signal them -// all, while others allow the wait to be effectively turned off (for -// a while while waiting threads come around). This implementation -// appears correct, as it will not "lose" any signals, and will guarantee -// that all threads get signaled by Broadcast(). -// -// This implementation offers support for "performance" in its selection of -// which thread to revive. Performance, in direct contrast with "fairness," -// assures that the thread that most recently began to Wait() is selected by -// Signal to revive. Fairness would (if publicly supported) assure that the -// thread that has Wait()ed the longest is selected. The default policy -// may improve performance, as the selected thread may have a greater chance of -// having some of its stack data in various CPU caches. -// -// For a discussion of the many very subtle implementation details, see the FAQ -// at the end of condition_variable_win.cc. - -#ifndef BASE_SYNCHRONIZATION_CONDITION_VARIABLE_H_ -#define BASE_SYNCHRONIZATION_CONDITION_VARIABLE_H_ - -#include "base/base_export.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/synchronization/lock.h" -#include "build/build_config.h" - -#if defined(OS_POSIX) -#include <pthread.h> -#endif - -namespace base { - -class ConditionVarImpl; -class TimeDelta; - -class BASE_EXPORT ConditionVariable { - public: - // Construct a cv for use with ONLY one user lock. - explicit ConditionVariable(Lock* user_lock); - - ~ConditionVariable(); - - // Wait() releases the caller's critical section atomically as it starts to - // sleep, and the reacquires it when it is signaled. - void Wait(); - void TimedWait(const TimeDelta& max_time); - - // Broadcast() revives all waiting threads. - void Broadcast(); - // Signal() revives one waiting thread. - void Signal(); - - private: - -#if defined(OS_WIN) - ConditionVarImpl* impl_; -#elif defined(OS_POSIX) - pthread_cond_t condition_; - pthread_mutex_t* user_mutex_; -#if DCHECK_IS_ON() - base::Lock* user_lock_; // Needed to adjust shadow lock state on wait. -#endif - -#endif - - DISALLOW_COPY_AND_ASSIGN(ConditionVariable); -}; - -} // namespace base - -#endif // BASE_SYNCHRONIZATION_CONDITION_VARIABLE_H_ diff --git a/security/sandbox/chromium/base/synchronization/condition_variable_posix.cc b/security/sandbox/chromium/base/synchronization/condition_variable_posix.cc deleted file mode 100644 index d86fd180e..000000000 --- a/security/sandbox/chromium/base/synchronization/condition_variable_posix.cc +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (c) 2011 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. - -#include "base/synchronization/condition_variable.h" - -#include <errno.h> -#include <stdint.h> -#include <sys/time.h> - -#include "base/synchronization/lock.h" -#include "base/threading/thread_restrictions.h" -#include "base/time/time.h" -#include "build/build_config.h" - -namespace base { - -ConditionVariable::ConditionVariable(Lock* user_lock) - : user_mutex_(user_lock->lock_.native_handle()) -#if DCHECK_IS_ON() - , user_lock_(user_lock) -#endif -{ - int rv = 0; - // http://crbug.com/293736 - // NaCl doesn't support monotonic clock based absolute deadlines. - // On older Android platform versions, it's supported through the - // non-standard pthread_cond_timedwait_monotonic_np. Newer platform - // versions have pthread_condattr_setclock. - // Mac can use relative time deadlines. -#if !defined(OS_MACOSX) && !defined(OS_NACL) && \ - !(defined(OS_ANDROID) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC)) - pthread_condattr_t attrs; - rv = pthread_condattr_init(&attrs); - DCHECK_EQ(0, rv); - pthread_condattr_setclock(&attrs, CLOCK_MONOTONIC); - rv = pthread_cond_init(&condition_, &attrs); - pthread_condattr_destroy(&attrs); -#else - rv = pthread_cond_init(&condition_, NULL); -#endif - DCHECK_EQ(0, rv); -} - -ConditionVariable::~ConditionVariable() { -#if defined(OS_MACOSX) - // This hack is necessary to avoid a fatal pthreads subsystem bug in the - // Darwin kernel. http://crbug.com/517681. - { - base::Lock lock; - base::AutoLock l(lock); - struct timespec ts; - ts.tv_sec = 0; - ts.tv_nsec = 1; - pthread_cond_timedwait_relative_np(&condition_, lock.lock_.native_handle(), - &ts); - } -#endif - - int rv = pthread_cond_destroy(&condition_); - DCHECK_EQ(0, rv); -} - -void ConditionVariable::Wait() { - base::ThreadRestrictions::AssertWaitAllowed(); -#if DCHECK_IS_ON() - user_lock_->CheckHeldAndUnmark(); -#endif - int rv = pthread_cond_wait(&condition_, user_mutex_); - DCHECK_EQ(0, rv); -#if DCHECK_IS_ON() - user_lock_->CheckUnheldAndMark(); -#endif -} - -void ConditionVariable::TimedWait(const TimeDelta& max_time) { - base::ThreadRestrictions::AssertWaitAllowed(); - int64_t usecs = max_time.InMicroseconds(); - struct timespec relative_time; - relative_time.tv_sec = usecs / Time::kMicrosecondsPerSecond; - relative_time.tv_nsec = - (usecs % Time::kMicrosecondsPerSecond) * Time::kNanosecondsPerMicrosecond; - -#if DCHECK_IS_ON() - user_lock_->CheckHeldAndUnmark(); -#endif - -#if defined(OS_MACOSX) - int rv = pthread_cond_timedwait_relative_np( - &condition_, user_mutex_, &relative_time); -#else - // The timeout argument to pthread_cond_timedwait is in absolute time. - struct timespec absolute_time; -#if defined(OS_NACL) - // See comment in constructor for why this is different in NaCl. - struct timeval now; - gettimeofday(&now, NULL); - absolute_time.tv_sec = now.tv_sec; - absolute_time.tv_nsec = now.tv_usec * Time::kNanosecondsPerMicrosecond; -#else - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - absolute_time.tv_sec = now.tv_sec; - absolute_time.tv_nsec = now.tv_nsec; -#endif - - absolute_time.tv_sec += relative_time.tv_sec; - absolute_time.tv_nsec += relative_time.tv_nsec; - absolute_time.tv_sec += absolute_time.tv_nsec / Time::kNanosecondsPerSecond; - absolute_time.tv_nsec %= Time::kNanosecondsPerSecond; - DCHECK_GE(absolute_time.tv_sec, now.tv_sec); // Overflow paranoia - -#if defined(OS_ANDROID) && defined(HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC) - int rv = pthread_cond_timedwait_monotonic_np( - &condition_, user_mutex_, &absolute_time); -#else - int rv = pthread_cond_timedwait(&condition_, user_mutex_, &absolute_time); -#endif // OS_ANDROID && HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC -#endif // OS_MACOSX - - DCHECK(rv == 0 || rv == ETIMEDOUT); -#if DCHECK_IS_ON() - user_lock_->CheckUnheldAndMark(); -#endif -} - -void ConditionVariable::Broadcast() { - int rv = pthread_cond_broadcast(&condition_); - DCHECK_EQ(0, rv); -} - -void ConditionVariable::Signal() { - int rv = pthread_cond_signal(&condition_); - DCHECK_EQ(0, rv); -} - -} // namespace base diff --git a/security/sandbox/chromium/base/synchronization/lock.cc b/security/sandbox/chromium/base/synchronization/lock.cc deleted file mode 100644 index 03297ada5..000000000 --- a/security/sandbox/chromium/base/synchronization/lock.cc +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2011 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. - -// This file is used for debugging assertion support. The Lock class -// is functionally a wrapper around the LockImpl class, so the only -// real intelligence in the class is in the debugging logic. - -#include "base/synchronization/lock.h" - -#if DCHECK_IS_ON() - -namespace base { - -Lock::Lock() : lock_() { -} - -Lock::~Lock() { - DCHECK(owning_thread_ref_.is_null()); -} - -void Lock::AssertAcquired() const { - DCHECK(owning_thread_ref_ == PlatformThread::CurrentRef()); -} - -void Lock::CheckHeldAndUnmark() { - DCHECK(owning_thread_ref_ == PlatformThread::CurrentRef()); - owning_thread_ref_ = PlatformThreadRef(); -} - -void Lock::CheckUnheldAndMark() { - DCHECK(owning_thread_ref_.is_null()); - owning_thread_ref_ = PlatformThread::CurrentRef(); -} - -} // namespace base - -#endif // DCHECK_IS_ON() diff --git a/security/sandbox/chromium/base/synchronization/lock.h b/security/sandbox/chromium/base/synchronization/lock.h deleted file mode 100644 index f7dd35dcc..000000000 --- a/security/sandbox/chromium/base/synchronization/lock.h +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef BASE_SYNCHRONIZATION_LOCK_H_ -#define BASE_SYNCHRONIZATION_LOCK_H_ - -#include "base/base_export.h" -#include "base/logging.h" -#include "base/macros.h" -#include "base/synchronization/lock_impl.h" -#include "base/threading/platform_thread.h" -#include "build/build_config.h" - -namespace base { - -// A convenient wrapper for an OS specific critical section. The only real -// intelligence in this class is in debug mode for the support for the -// AssertAcquired() method. -class BASE_EXPORT Lock { - public: -#if !DCHECK_IS_ON() - // Optimized wrapper implementation - Lock() : lock_() {} - ~Lock() {} - void Acquire() { lock_.Lock(); } - void Release() { lock_.Unlock(); } - - // If the lock is not held, take it and return true. If the lock is already - // held by another thread, immediately return false. This must not be called - // by a thread already holding the lock (what happens is undefined and an - // assertion may fail). - bool Try() { return lock_.Try(); } - - // Null implementation if not debug. - void AssertAcquired() const {} -#else - Lock(); - ~Lock(); - - // NOTE: Although windows critical sections support recursive locks, we do not - // allow this, and we will commonly fire a DCHECK() if a thread attempts to - // acquire the lock a second time (while already holding it). - void Acquire() { - lock_.Lock(); - CheckUnheldAndMark(); - } - void Release() { - CheckHeldAndUnmark(); - lock_.Unlock(); - } - - bool Try() { - bool rv = lock_.Try(); - if (rv) { - CheckUnheldAndMark(); - } - return rv; - } - - void AssertAcquired() const; -#endif // DCHECK_IS_ON() - -#if defined(OS_POSIX) - // The posix implementation of ConditionVariable needs to be able - // to see our lock and tweak our debugging counters, as it releases - // and acquires locks inside of pthread_cond_{timed,}wait. - friend class ConditionVariable; -#elif defined(OS_WIN) - // The Windows Vista implementation of ConditionVariable needs the - // native handle of the critical section. - friend class WinVistaCondVar; -#endif - - private: -#if DCHECK_IS_ON() - // Members and routines taking care of locks assertions. - // Note that this checks for recursive locks and allows them - // if the variable is set. This is allowed by the underlying implementation - // on windows but not on Posix, so we're doing unneeded checks on Posix. - // It's worth it to share the code. - void CheckHeldAndUnmark(); - void CheckUnheldAndMark(); - - // All private data is implicitly protected by lock_. - // Be VERY careful to only access members under that lock. - base::PlatformThreadRef owning_thread_ref_; -#endif // DCHECK_IS_ON() - - // Platform specific underlying lock implementation. - internal::LockImpl lock_; - - DISALLOW_COPY_AND_ASSIGN(Lock); -}; - -// A helper class that acquires the given Lock while the AutoLock is in scope. -class AutoLock { - public: - struct AlreadyAcquired {}; - - explicit AutoLock(Lock& lock) : lock_(lock) { - lock_.Acquire(); - } - - AutoLock(Lock& lock, const AlreadyAcquired&) : lock_(lock) { - lock_.AssertAcquired(); - } - - ~AutoLock() { - lock_.AssertAcquired(); - lock_.Release(); - } - - private: - Lock& lock_; - DISALLOW_COPY_AND_ASSIGN(AutoLock); -}; - -// AutoUnlock is a helper that will Release() the |lock| argument in the -// constructor, and re-Acquire() it in the destructor. -class AutoUnlock { - public: - explicit AutoUnlock(Lock& lock) : lock_(lock) { - // We require our caller to have the lock. - lock_.AssertAcquired(); - lock_.Release(); - } - - ~AutoUnlock() { - lock_.Acquire(); - } - - private: - Lock& lock_; - DISALLOW_COPY_AND_ASSIGN(AutoUnlock); -}; - -} // namespace base - -#endif // BASE_SYNCHRONIZATION_LOCK_H_ diff --git a/security/sandbox/chromium/base/synchronization/lock_impl.h b/security/sandbox/chromium/base/synchronization/lock_impl.h deleted file mode 100644 index ed85987b3..000000000 --- a/security/sandbox/chromium/base/synchronization/lock_impl.h +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2011 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. - -#ifndef BASE_SYNCHRONIZATION_LOCK_IMPL_H_ -#define BASE_SYNCHRONIZATION_LOCK_IMPL_H_ - -#include "base/base_export.h" -#include "base/macros.h" -#include "build/build_config.h" - -#if defined(OS_WIN) -#include <windows.h> -#elif defined(OS_POSIX) -#include <pthread.h> -#endif - -namespace base { -namespace internal { - -// This class implements the underlying platform-specific spin-lock mechanism -// used for the Lock class. Most users should not use LockImpl directly, but -// should instead use Lock. -class BASE_EXPORT LockImpl { - public: -#if defined(OS_WIN) - typedef CRITICAL_SECTION NativeHandle; -#elif defined(OS_POSIX) - typedef pthread_mutex_t NativeHandle; -#endif - - LockImpl(); - ~LockImpl(); - - // If the lock is not held, take it and return true. If the lock is already - // held by something else, immediately return false. - bool Try(); - - // Take the lock, blocking until it is available if necessary. - void Lock(); - - // Release the lock. This must only be called by the lock's holder: after - // a successful call to Try, or a call to Lock. - void Unlock(); - - // Return the native underlying lock. - // TODO(awalker): refactor lock and condition variables so that this is - // unnecessary. - NativeHandle* native_handle() { return &native_handle_; } - - private: - NativeHandle native_handle_; - - DISALLOW_COPY_AND_ASSIGN(LockImpl); -}; - -} // namespace internal -} // namespace base - -#endif // BASE_SYNCHRONIZATION_LOCK_IMPL_H_ diff --git a/security/sandbox/chromium/base/synchronization/lock_impl_posix.cc b/security/sandbox/chromium/base/synchronization/lock_impl_posix.cc deleted file mode 100644 index 5619adaf5..000000000 --- a/security/sandbox/chromium/base/synchronization/lock_impl_posix.cc +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2011 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. - -#include "base/synchronization/lock_impl.h" - -#include <errno.h> -#include <string.h> - -#include "base/logging.h" - -namespace base { -namespace internal { - -LockImpl::LockImpl() { -#ifndef NDEBUG - // In debug, setup attributes for lock error checking. - pthread_mutexattr_t mta; - int rv = pthread_mutexattr_init(&mta); - DCHECK_EQ(rv, 0) << ". " << strerror(rv); - rv = pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_ERRORCHECK); - DCHECK_EQ(rv, 0) << ". " << strerror(rv); - rv = pthread_mutex_init(&native_handle_, &mta); - DCHECK_EQ(rv, 0) << ". " << strerror(rv); - rv = pthread_mutexattr_destroy(&mta); - DCHECK_EQ(rv, 0) << ". " << strerror(rv); -#else - // In release, go with the default lock attributes. - pthread_mutex_init(&native_handle_, NULL); -#endif -} - -LockImpl::~LockImpl() { - int rv = pthread_mutex_destroy(&native_handle_); - DCHECK_EQ(rv, 0) << ". " << strerror(rv); -} - -bool LockImpl::Try() { - int rv = pthread_mutex_trylock(&native_handle_); - DCHECK(rv == 0 || rv == EBUSY) << ". " << strerror(rv); - return rv == 0; -} - -void LockImpl::Lock() { - int rv = pthread_mutex_lock(&native_handle_); - DCHECK_EQ(rv, 0) << ". " << strerror(rv); -} - -void LockImpl::Unlock() { - int rv = pthread_mutex_unlock(&native_handle_); - DCHECK_EQ(rv, 0) << ". " << strerror(rv); -} - -} // namespace internal -} // namespace base diff --git a/security/sandbox/chromium/base/synchronization/lock_impl_win.cc b/security/sandbox/chromium/base/synchronization/lock_impl_win.cc deleted file mode 100644 index fbc1bdd46..000000000 --- a/security/sandbox/chromium/base/synchronization/lock_impl_win.cc +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2011 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. - -#include "base/synchronization/lock_impl.h" - -namespace base { -namespace internal { - -LockImpl::LockImpl() { - // The second parameter is the spin count, for short-held locks it avoid the - // contending thread from going to sleep which helps performance greatly. - ::InitializeCriticalSectionAndSpinCount(&native_handle_, 2000); -} - -LockImpl::~LockImpl() { - ::DeleteCriticalSection(&native_handle_); -} - -bool LockImpl::Try() { - if (::TryEnterCriticalSection(&native_handle_) != FALSE) { - return true; - } - return false; -} - -void LockImpl::Lock() { - ::EnterCriticalSection(&native_handle_); -} - -void LockImpl::Unlock() { - ::LeaveCriticalSection(&native_handle_); -} - -} // namespace internal -} // namespace base diff --git a/security/sandbox/chromium/base/synchronization/waitable_event.h b/security/sandbox/chromium/base/synchronization/waitable_event.h deleted file mode 100644 index b5d91d00b..000000000 --- a/security/sandbox/chromium/base/synchronization/waitable_event.h +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright (c) 2012 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. - -#ifndef BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_ -#define BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_ - -#include <stddef.h> - -#include "base/base_export.h" -#include "base/macros.h" -#include "build/build_config.h" - -#if defined(OS_WIN) -#include "base/win/scoped_handle.h" -#endif - -#if defined(OS_POSIX) -#include <list> -#include <utility> -#include "base/memory/ref_counted.h" -#include "base/synchronization/lock.h" -#endif - -namespace base { - -class TimeDelta; - -// A WaitableEvent can be a useful thread synchronization tool when you want to -// allow one thread to wait for another thread to finish some work. For -// non-Windows systems, this can only be used from within a single address -// space. -// -// Use a WaitableEvent when you would otherwise use a Lock+ConditionVariable to -// protect a simple boolean value. However, if you find yourself using a -// WaitableEvent in conjunction with a Lock to wait for a more complex state -// change (e.g., for an item to be added to a queue), then you should probably -// be using a ConditionVariable instead of a WaitableEvent. -// -// NOTE: On Windows, this class provides a subset of the functionality afforded -// by a Windows event object. This is intentional. If you are writing Windows -// specific code and you need other features of a Windows event, then you might -// be better off just using an Windows event directly. -class BASE_EXPORT WaitableEvent { - public: - // If manual_reset is true, then to set the event state to non-signaled, a - // consumer must call the Reset method. If this parameter is false, then the - // system automatically resets the event state to non-signaled after a single - // waiting thread has been released. - WaitableEvent(bool manual_reset, bool initially_signaled); - -#if defined(OS_WIN) - // Create a WaitableEvent from an Event HANDLE which has already been - // created. This objects takes ownership of the HANDLE and will close it when - // deleted. - explicit WaitableEvent(win::ScopedHandle event_handle); -#endif - - ~WaitableEvent(); - - // Put the event in the un-signaled state. - void Reset(); - - // Put the event in the signaled state. Causing any thread blocked on Wait - // to be woken up. - void Signal(); - - // Returns true if the event is in the signaled state, else false. If this - // is not a manual reset event, then this test will cause a reset. - bool IsSignaled(); - - // Wait indefinitely for the event to be signaled. Wait's return "happens - // after" |Signal| has completed. This means that it's safe for a - // WaitableEvent to synchronise its own destruction, like this: - // - // WaitableEvent *e = new WaitableEvent; - // SendToOtherThread(e); - // e->Wait(); - // delete e; - void Wait(); - - // Wait up until max_time has passed for the event to be signaled. Returns - // true if the event was signaled. If this method returns false, then it - // does not necessarily mean that max_time was exceeded. - // - // TimedWait can synchronise its own destruction like |Wait|. - bool TimedWait(const TimeDelta& max_time); - -#if defined(OS_WIN) - HANDLE handle() const { return handle_.Get(); } -#endif - - // Wait, synchronously, on multiple events. - // waitables: an array of WaitableEvent pointers - // count: the number of elements in @waitables - // - // returns: the index of a WaitableEvent which has been signaled. - // - // You MUST NOT delete any of the WaitableEvent objects while this wait is - // happening, however WaitMany's return "happens after" the |Signal| call - // that caused it has completed, like |Wait|. - static size_t WaitMany(WaitableEvent** waitables, size_t count); - - // For asynchronous waiting, see WaitableEventWatcher - - // This is a private helper class. It's here because it's used by friends of - // this class (such as WaitableEventWatcher) to be able to enqueue elements - // of the wait-list - class Waiter { - public: - // Signal the waiter to wake up. - // - // Consider the case of a Waiter which is in multiple WaitableEvent's - // wait-lists. Each WaitableEvent is automatic-reset and two of them are - // signaled at the same time. Now, each will wake only the first waiter in - // the wake-list before resetting. However, if those two waiters happen to - // be the same object (as can happen if another thread didn't have a chance - // to dequeue the waiter from the other wait-list in time), two auto-resets - // will have happened, but only one waiter has been signaled! - // - // Because of this, a Waiter may "reject" a wake by returning false. In - // this case, the auto-reset WaitableEvent shouldn't act as if anything has - // been notified. - virtual bool Fire(WaitableEvent* signaling_event) = 0; - - // Waiters may implement this in order to provide an extra condition for - // two Waiters to be considered equal. In WaitableEvent::Dequeue, if the - // pointers match then this function is called as a final check. See the - // comments in ~Handle for why. - virtual bool Compare(void* tag) = 0; - - protected: - virtual ~Waiter() {} - }; - - private: - friend class WaitableEventWatcher; - -#if defined(OS_WIN) - win::ScopedHandle handle_; -#else - // On Windows, one can close a HANDLE which is currently being waited on. The - // MSDN documentation says that the resulting behaviour is 'undefined', but - // it doesn't crash. However, if we were to include the following members - // directly then, on POSIX, one couldn't use WaitableEventWatcher to watch an - // event which gets deleted. This mismatch has bitten us several times now, - // so we have a kernel of the WaitableEvent, which is reference counted. - // WaitableEventWatchers may then take a reference and thus match the Windows - // behaviour. - struct WaitableEventKernel : - public RefCountedThreadSafe<WaitableEventKernel> { - public: - WaitableEventKernel(bool manual_reset, bool initially_signaled); - - bool Dequeue(Waiter* waiter, void* tag); - - base::Lock lock_; - const bool manual_reset_; - bool signaled_; - std::list<Waiter*> waiters_; - - private: - friend class RefCountedThreadSafe<WaitableEventKernel>; - ~WaitableEventKernel(); - }; - - typedef std::pair<WaitableEvent*, size_t> WaiterAndIndex; - - // When dealing with arrays of WaitableEvent*, we want to sort by the address - // of the WaitableEvent in order to have a globally consistent locking order. - // In that case we keep them, in sorted order, in an array of pairs where the - // second element is the index of the WaitableEvent in the original, - // unsorted, array. - static size_t EnqueueMany(WaiterAndIndex* waitables, - size_t count, Waiter* waiter); - - bool SignalAll(); - bool SignalOne(); - void Enqueue(Waiter* waiter); - - scoped_refptr<WaitableEventKernel> kernel_; -#endif - - DISALLOW_COPY_AND_ASSIGN(WaitableEvent); -}; - -} // namespace base - -#endif // BASE_SYNCHRONIZATION_WAITABLE_EVENT_H_ diff --git a/security/sandbox/chromium/base/synchronization/waitable_event_posix.cc b/security/sandbox/chromium/base/synchronization/waitable_event_posix.cc deleted file mode 100644 index 64d4376fe..000000000 --- a/security/sandbox/chromium/base/synchronization/waitable_event_posix.cc +++ /dev/null @@ -1,417 +0,0 @@ -// Copyright (c) 2012 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. - -#include <stddef.h> - -#include <algorithm> -#include <vector> - -#include "base/logging.h" -#include "base/synchronization/condition_variable.h" -#include "base/synchronization/lock.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread_restrictions.h" - -// ----------------------------------------------------------------------------- -// A WaitableEvent on POSIX is implemented as a wait-list. Currently we don't -// support cross-process events (where one process can signal an event which -// others are waiting on). Because of this, we can avoid having one thread per -// listener in several cases. -// -// The WaitableEvent maintains a list of waiters, protected by a lock. Each -// waiter is either an async wait, in which case we have a Task and the -// MessageLoop to run it on, or a blocking wait, in which case we have the -// condition variable to signal. -// -// Waiting involves grabbing the lock and adding oneself to the wait list. Async -// waits can be canceled, which means grabbing the lock and removing oneself -// from the list. -// -// Waiting on multiple events is handled by adding a single, synchronous wait to -// the wait-list of many events. An event passes a pointer to itself when -// firing a waiter and so we can store that pointer to find out which event -// triggered. -// ----------------------------------------------------------------------------- - -namespace base { - -// ----------------------------------------------------------------------------- -// This is just an abstract base class for waking the two types of waiters -// ----------------------------------------------------------------------------- -WaitableEvent::WaitableEvent(bool manual_reset, bool initially_signaled) - : kernel_(new WaitableEventKernel(manual_reset, initially_signaled)) { -} - -WaitableEvent::~WaitableEvent() { -} - -void WaitableEvent::Reset() { - base::AutoLock locked(kernel_->lock_); - kernel_->signaled_ = false; -} - -void WaitableEvent::Signal() { - base::AutoLock locked(kernel_->lock_); - - if (kernel_->signaled_) - return; - - if (kernel_->manual_reset_) { - SignalAll(); - kernel_->signaled_ = true; - } else { - // In the case of auto reset, if no waiters were woken, we remain - // signaled. - if (!SignalOne()) - kernel_->signaled_ = true; - } -} - -bool WaitableEvent::IsSignaled() { - base::AutoLock locked(kernel_->lock_); - - const bool result = kernel_->signaled_; - if (result && !kernel_->manual_reset_) - kernel_->signaled_ = false; - return result; -} - -// ----------------------------------------------------------------------------- -// Synchronous waits - -// ----------------------------------------------------------------------------- -// This is a synchronous waiter. The thread is waiting on the given condition -// variable and the fired flag in this object. -// ----------------------------------------------------------------------------- -class SyncWaiter : public WaitableEvent::Waiter { - public: - SyncWaiter() - : fired_(false), - signaling_event_(NULL), - lock_(), - cv_(&lock_) { - } - - bool Fire(WaitableEvent* signaling_event) override { - base::AutoLock locked(lock_); - - if (fired_) - return false; - - fired_ = true; - signaling_event_ = signaling_event; - - cv_.Broadcast(); - - // Unlike AsyncWaiter objects, SyncWaiter objects are stack-allocated on - // the blocking thread's stack. There is no |delete this;| in Fire. The - // SyncWaiter object is destroyed when it goes out of scope. - - return true; - } - - WaitableEvent* signaling_event() const { - return signaling_event_; - } - - // --------------------------------------------------------------------------- - // These waiters are always stack allocated and don't delete themselves. Thus - // there's no problem and the ABA tag is the same as the object pointer. - // --------------------------------------------------------------------------- - bool Compare(void* tag) override { return this == tag; } - - // --------------------------------------------------------------------------- - // Called with lock held. - // --------------------------------------------------------------------------- - bool fired() const { - return fired_; - } - - // --------------------------------------------------------------------------- - // During a TimedWait, we need a way to make sure that an auto-reset - // WaitableEvent doesn't think that this event has been signaled between - // unlocking it and removing it from the wait-list. Called with lock held. - // --------------------------------------------------------------------------- - void Disable() { - fired_ = true; - } - - base::Lock* lock() { - return &lock_; - } - - base::ConditionVariable* cv() { - return &cv_; - } - - private: - bool fired_; - WaitableEvent* signaling_event_; // The WaitableEvent which woke us - base::Lock lock_; - base::ConditionVariable cv_; -}; - -void WaitableEvent::Wait() { - bool result = TimedWait(TimeDelta::FromSeconds(-1)); - DCHECK(result) << "TimedWait() should never fail with infinite timeout"; -} - -bool WaitableEvent::TimedWait(const TimeDelta& max_time) { - base::ThreadRestrictions::AssertWaitAllowed(); - const TimeTicks end_time(TimeTicks::Now() + max_time); - const bool finite_time = max_time.ToInternalValue() >= 0; - - kernel_->lock_.Acquire(); - if (kernel_->signaled_) { - if (!kernel_->manual_reset_) { - // In this case we were signaled when we had no waiters. Now that - // someone has waited upon us, we can automatically reset. - kernel_->signaled_ = false; - } - - kernel_->lock_.Release(); - return true; - } - - SyncWaiter sw; - sw.lock()->Acquire(); - - Enqueue(&sw); - kernel_->lock_.Release(); - // We are violating locking order here by holding the SyncWaiter lock but not - // the WaitableEvent lock. However, this is safe because we don't lock @lock_ - // again before unlocking it. - - for (;;) { - const TimeTicks current_time(TimeTicks::Now()); - - if (sw.fired() || (finite_time && current_time >= end_time)) { - const bool return_value = sw.fired(); - - // We can't acquire @lock_ before releasing the SyncWaiter lock (because - // of locking order), however, in between the two a signal could be fired - // and @sw would accept it, however we will still return false, so the - // signal would be lost on an auto-reset WaitableEvent. Thus we call - // Disable which makes sw::Fire return false. - sw.Disable(); - sw.lock()->Release(); - - // This is a bug that has been enshrined in the interface of - // WaitableEvent now: |Dequeue| is called even when |sw.fired()| is true, - // even though it'll always return false in that case. However, taking - // the lock ensures that |Signal| has completed before we return and - // means that a WaitableEvent can synchronise its own destruction. - kernel_->lock_.Acquire(); - kernel_->Dequeue(&sw, &sw); - kernel_->lock_.Release(); - - return return_value; - } - - if (finite_time) { - const TimeDelta max_wait(end_time - current_time); - sw.cv()->TimedWait(max_wait); - } else { - sw.cv()->Wait(); - } - } -} - -// ----------------------------------------------------------------------------- -// Synchronous waiting on multiple objects. - -static bool // StrictWeakOrdering -cmp_fst_addr(const std::pair<WaitableEvent*, unsigned> &a, - const std::pair<WaitableEvent*, unsigned> &b) { - return a.first < b.first; -} - -// static -size_t WaitableEvent::WaitMany(WaitableEvent** raw_waitables, - size_t count) { - base::ThreadRestrictions::AssertWaitAllowed(); - DCHECK(count) << "Cannot wait on no events"; - - // We need to acquire the locks in a globally consistent order. Thus we sort - // the array of waitables by address. We actually sort a pairs so that we can - // map back to the original index values later. - std::vector<std::pair<WaitableEvent*, size_t> > waitables; - waitables.reserve(count); - for (size_t i = 0; i < count; ++i) - waitables.push_back(std::make_pair(raw_waitables[i], i)); - - DCHECK_EQ(count, waitables.size()); - - sort(waitables.begin(), waitables.end(), cmp_fst_addr); - - // The set of waitables must be distinct. Since we have just sorted by - // address, we can check this cheaply by comparing pairs of consecutive - // elements. - for (size_t i = 0; i < waitables.size() - 1; ++i) { - DCHECK(waitables[i].first != waitables[i+1].first); - } - - SyncWaiter sw; - - const size_t r = EnqueueMany(&waitables[0], count, &sw); - if (r) { - // One of the events is already signaled. The SyncWaiter has not been - // enqueued anywhere. EnqueueMany returns the count of remaining waitables - // when the signaled one was seen, so the index of the signaled event is - // @count - @r. - return waitables[count - r].second; - } - - // At this point, we hold the locks on all the WaitableEvents and we have - // enqueued our waiter in them all. - sw.lock()->Acquire(); - // Release the WaitableEvent locks in the reverse order - for (size_t i = 0; i < count; ++i) { - waitables[count - (1 + i)].first->kernel_->lock_.Release(); - } - - for (;;) { - if (sw.fired()) - break; - - sw.cv()->Wait(); - } - sw.lock()->Release(); - - // The address of the WaitableEvent which fired is stored in the SyncWaiter. - WaitableEvent *const signaled_event = sw.signaling_event(); - // This will store the index of the raw_waitables which fired. - size_t signaled_index = 0; - - // Take the locks of each WaitableEvent in turn (except the signaled one) and - // remove our SyncWaiter from the wait-list - for (size_t i = 0; i < count; ++i) { - if (raw_waitables[i] != signaled_event) { - raw_waitables[i]->kernel_->lock_.Acquire(); - // There's no possible ABA issue with the address of the SyncWaiter here - // because it lives on the stack. Thus the tag value is just the pointer - // value again. - raw_waitables[i]->kernel_->Dequeue(&sw, &sw); - raw_waitables[i]->kernel_->lock_.Release(); - } else { - // By taking this lock here we ensure that |Signal| has completed by the - // time we return, because |Signal| holds this lock. This matches the - // behaviour of |Wait| and |TimedWait|. - raw_waitables[i]->kernel_->lock_.Acquire(); - raw_waitables[i]->kernel_->lock_.Release(); - signaled_index = i; - } - } - - return signaled_index; -} - -// ----------------------------------------------------------------------------- -// If return value == 0: -// The locks of the WaitableEvents have been taken in order and the Waiter has -// been enqueued in the wait-list of each. None of the WaitableEvents are -// currently signaled -// else: -// None of the WaitableEvent locks are held. The Waiter has not been enqueued -// in any of them and the return value is the index of the first WaitableEvent -// which was signaled, from the end of the array. -// ----------------------------------------------------------------------------- -// static -size_t WaitableEvent::EnqueueMany - (std::pair<WaitableEvent*, size_t>* waitables, - size_t count, Waiter* waiter) { - if (!count) - return 0; - - waitables[0].first->kernel_->lock_.Acquire(); - if (waitables[0].first->kernel_->signaled_) { - if (!waitables[0].first->kernel_->manual_reset_) - waitables[0].first->kernel_->signaled_ = false; - waitables[0].first->kernel_->lock_.Release(); - return count; - } - - const size_t r = EnqueueMany(waitables + 1, count - 1, waiter); - if (r) { - waitables[0].first->kernel_->lock_.Release(); - } else { - waitables[0].first->Enqueue(waiter); - } - - return r; -} - -// ----------------------------------------------------------------------------- - - -// ----------------------------------------------------------------------------- -// Private functions... - -WaitableEvent::WaitableEventKernel::WaitableEventKernel(bool manual_reset, - bool initially_signaled) - : manual_reset_(manual_reset), - signaled_(initially_signaled) { -} - -WaitableEvent::WaitableEventKernel::~WaitableEventKernel() { -} - -// ----------------------------------------------------------------------------- -// Wake all waiting waiters. Called with lock held. -// ----------------------------------------------------------------------------- -bool WaitableEvent::SignalAll() { - bool signaled_at_least_one = false; - - for (std::list<Waiter*>::iterator - i = kernel_->waiters_.begin(); i != kernel_->waiters_.end(); ++i) { - if ((*i)->Fire(this)) - signaled_at_least_one = true; - } - - kernel_->waiters_.clear(); - return signaled_at_least_one; -} - -// --------------------------------------------------------------------------- -// Try to wake a single waiter. Return true if one was woken. Called with lock -// held. -// --------------------------------------------------------------------------- -bool WaitableEvent::SignalOne() { - for (;;) { - if (kernel_->waiters_.empty()) - return false; - - const bool r = (*kernel_->waiters_.begin())->Fire(this); - kernel_->waiters_.pop_front(); - if (r) - return true; - } -} - -// ----------------------------------------------------------------------------- -// Add a waiter to the list of those waiting. Called with lock held. -// ----------------------------------------------------------------------------- -void WaitableEvent::Enqueue(Waiter* waiter) { - kernel_->waiters_.push_back(waiter); -} - -// ----------------------------------------------------------------------------- -// Remove a waiter from the list of those waiting. Return true if the waiter was -// actually removed. Called with lock held. -// ----------------------------------------------------------------------------- -bool WaitableEvent::WaitableEventKernel::Dequeue(Waiter* waiter, void* tag) { - for (std::list<Waiter*>::iterator - i = waiters_.begin(); i != waiters_.end(); ++i) { - if (*i == waiter && (*i)->Compare(tag)) { - waiters_.erase(i); - return true; - } - } - - return false; -} - -// ----------------------------------------------------------------------------- - -} // namespace base |