diff --git a/gfx/2d/CriticalSection.h b/gfx/2d/CriticalSection.h new file mode 100644 index 000000000000..d1eb69abcf64 --- /dev/null +++ b/gfx/2d/CriticalSection.h @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef MOZILLA_GFX_CRITICALSECTION_H_ +#define MOZILLA_GFX_CRITICALSECTION_H_ + +#ifdef WIN32 +#include +#else +#include +#include "mozilla/DebugOnly.h" +#endif + +namespace mozilla { +namespace gfx { + +#ifdef WIN32 + +class CriticalSection { +public: + CriticalSection() { ::InitializeCriticalSection(&mCriticalSection); } + + ~CriticalSection() { ::DeleteCriticalSection(&mCriticalSection); } + + void Enter() { ::EnterCriticalSection(&mCriticalSection); } + + void Leave() { ::LeaveCriticalSection(&mCriticalSection); } + +protected: + CRITICAL_SECTION mCriticalSection; +}; + +#else +// posix + +class PosixCondvar; +class CriticalSection { +public: + CriticalSection() { + DebugOnly err = pthread_mutex_init(&mMutex, nullptr); + MOZ_ASSERT(!err); + } + + ~CriticalSection() { + DebugOnly err = pthread_mutex_destroy(&mMutex); + MOZ_ASSERT(!err); + } + + void Enter() { + DebugOnly err = pthread_mutex_lock(&mMutex); + MOZ_ASSERT(!err); + } + + void Leave() { + DebugOnly err = pthread_mutex_unlock(&mMutex); + MOZ_ASSERT(!err); + } + +protected: + pthread_mutex_t mMutex; + friend class PosixCondVar; +}; + +#endif + +/// RAII helper. +struct CriticalSectionAutoEnter { + explicit CriticalSectionAutoEnter(CriticalSection* aSection) : mSection(aSection) { mSection->Enter(); } + ~CriticalSectionAutoEnter() { mSection->Leave(); } +protected: + CriticalSection* mSection; +}; + + +} // namespace +} // namespace + +#endif diff --git a/gfx/2d/JobScheduler.cpp b/gfx/2d/JobScheduler.cpp index e486f3b4c74d..3845c46db443 100644 --- a/gfx/2d/JobScheduler.cpp +++ b/gfx/2d/JobScheduler.cpp @@ -184,7 +184,7 @@ SyncObject::Signal() void SyncObject::AddWaitingJob(Job* aJob) { - MutexAutoLock lock(&mMutex); + CriticalSectionAutoEnter lock(&mWaitingJobsSection); mWaitingJobs.push_back(aJob); } @@ -199,7 +199,7 @@ void SyncObject::SubmitWaitingJobs() // hold a strong ref to prevent that! RefPtr kungFuDeathGrip(this); - MutexAutoLock lock(&mMutex); + CriticalSectionAutoEnter lock(&mWaitingJobsSection); tasksToSubmit = Move(mWaitingJobs); mWaitingJobs.clear(); } diff --git a/gfx/2d/JobScheduler.h b/gfx/2d/JobScheduler.h index 50da4874d5e2..afe717596fe7 100644 --- a/gfx/2d/JobScheduler.h +++ b/gfx/2d/JobScheduler.h @@ -206,7 +206,7 @@ private: void SubmitWaitingJobs(); std::vector mWaitingJobs; - Mutex mMutex; // for concurrent access to mWaintingJobs + CriticalSection mWaitingJobsSection; // for concurrent access to mWaintingJobs Atomic mSignals; #ifdef DEBUG @@ -218,15 +218,6 @@ private: friend class JobScheduler; }; - -/// RAII helper. -struct MutexAutoLock { - MutexAutoLock(Mutex* aMutex) : mMutex(aMutex) { mMutex->Lock(); } - ~MutexAutoLock() { mMutex->Unlock(); } -protected: - Mutex* mMutex; -}; - /// Base class for worker threads. class WorkerThread { diff --git a/gfx/2d/JobScheduler_posix.h b/gfx/2d/JobScheduler_posix.h index 74cd975df224..e106f62ea288 100644 --- a/gfx/2d/JobScheduler_posix.h +++ b/gfx/2d/JobScheduler_posix.h @@ -16,6 +16,7 @@ #include "mozilla/RefPtr.h" #include "mozilla/DebugOnly.h" +#include "mozilla/gfx/CriticalSection.h" namespace mozilla { namespace gfx { @@ -24,32 +25,8 @@ class Job; class PosixCondVar; class WorkerThread; -class Mutex { -public: - Mutex() { - DebugOnly err = pthread_mutex_init(&mMutex, nullptr); - MOZ_ASSERT(!err); - } - - ~Mutex() { - DebugOnly err = pthread_mutex_destroy(&mMutex); - MOZ_ASSERT(!err); - } - - void Lock() { - DebugOnly err = pthread_mutex_lock(&mMutex); - MOZ_ASSERT(!err); - } - - void Unlock() { - DebugOnly err = pthread_mutex_unlock(&mMutex); - MOZ_ASSERT(!err); - } - -protected: - pthread_mutex_t mMutex; - friend class PosixCondVar; -}; +typedef mozilla::gfx::CriticalSection Mutex; +typedef mozilla::gfx::CriticalSectionAutoEnter MutexAutoLock; // posix platforms only! class PosixCondVar { diff --git a/gfx/2d/JobScheduler_win32.cpp b/gfx/2d/JobScheduler_win32.cpp index d5aedf012afa..9c8e925fd350 100644 --- a/gfx/2d/JobScheduler_win32.cpp +++ b/gfx/2d/JobScheduler_win32.cpp @@ -50,7 +50,7 @@ MultiThreadedJobQueue::PopJob(Job*& aOutJob, AccessType aAccess) for (;;) { while (aAccess == BLOCKING && mJobs.empty()) { { - MutexAutoLock lock(&mMutex); + CriticalSectionAutoEnter lock(&mSection); if (mShuttingDown) { return false; } @@ -60,7 +60,7 @@ MultiThreadedJobQueue::PopJob(Job*& aOutJob, AccessType aAccess) ::WaitForMultipleObjects(2, handles, FALSE, INFINITE); } - MutexAutoLock lock(&mMutex); + CriticalSectionAutoEnter lock(&mSection); if (mShuttingDown) { return false; @@ -91,7 +91,7 @@ void MultiThreadedJobQueue::SubmitJob(Job* aJob) { MOZ_ASSERT(aJob); - MutexAutoLock lock(&mMutex); + CriticalSectionAutoEnter lock(&mSection); mJobs.push_back(aJob); ::SetEvent(mAvailableEvent); } @@ -100,7 +100,7 @@ void MultiThreadedJobQueue::ShutDown() { { - MutexAutoLock lock(&mMutex); + CriticalSectionAutoEnter lock(&mSection); mShuttingDown = true; } while (mThreadsCount) { @@ -112,14 +112,14 @@ MultiThreadedJobQueue::ShutDown() size_t MultiThreadedJobQueue::NumJobs() { - MutexAutoLock lock(&mMutex); + CriticalSectionAutoEnter lock(&mSection); return mJobs.size(); } bool MultiThreadedJobQueue::IsEmpty() { - MutexAutoLock lock(&mMutex); + CriticalSectionAutoEnter lock(&mSection); return mJobs.empty(); } @@ -132,7 +132,7 @@ MultiThreadedJobQueue::RegisterThread() void MultiThreadedJobQueue::UnregisterThread() { - MutexAutoLock lock(&mMutex); + CriticalSectionAutoEnter lock(&mSection); mThreadsCount -= 1; if (mThreadsCount == 0) { ::SetEvent(mShutdownEvent); diff --git a/gfx/2d/JobScheduler_win32.h b/gfx/2d/JobScheduler_win32.h index 2ff0a4761152..4a9d7e68276a 100644 --- a/gfx/2d/JobScheduler_win32.h +++ b/gfx/2d/JobScheduler_win32.h @@ -10,6 +10,7 @@ #define NOT_IMPLEMENTED MOZ_CRASH("Not implemented") #include "mozilla/RefPtr.h" +#include "mozilla/gfx/CriticalSection.h" #include #include @@ -19,41 +20,6 @@ namespace gfx { class WorkerThread; class Job; -class Mutex { -public: - Mutex() { - ::InitializeCriticalSection(&mMutex); -#ifdef DEBUG - mOwner = 0; -#endif - } - - ~Mutex() { ::DeleteCriticalSection(&mMutex); } - - void Lock() { - ::EnterCriticalSection(&mMutex); -#ifdef DEBUG - MOZ_ASSERT(mOwner != GetCurrentThreadId(), "recursive locking"); - mOwner = GetCurrentThreadId(); -#endif - } - - void Unlock() { -#ifdef DEBUG - // GetCurrentThreadId cannot return 0: it is not a valid thread id - MOZ_ASSERT(mOwner == GetCurrentThreadId(), "mismatched lock/unlock"); - mOwner = 0; -#endif - ::LeaveCriticalSection(&mMutex); - } - -protected: - CRITICAL_SECTION mMutex; -#ifdef DEBUG - DWORD mOwner; -#endif -}; - // The public interface of this class must remain identical to its equivalent // in JobScheduler_posix.h class MultiThreadedJobQueue { @@ -95,7 +61,7 @@ public: protected: std::list mJobs; - Mutex mMutex; + CriticalSection mSection; HANDLE mAvailableEvent; HANDLE mShutdownEvent; int32_t mThreadsCount; diff --git a/gfx/2d/moz.build b/gfx/2d/moz.build index 16c1d7ad9a46..4d64a716a1f7 100644 --- a/gfx/2d/moz.build +++ b/gfx/2d/moz.build @@ -20,6 +20,7 @@ EXPORTS.mozilla.gfx += [ 'Blur.h', 'BorrowedContext.h', 'Coord.h', + 'CriticalSection.h', 'DataSurfaceHelpers.h', 'DrawTargetTiled.h', 'Filters.h', diff --git a/gfx/tests/gtest/TestJobScheduler.cpp b/gfx/tests/gtest/TestJobScheduler.cpp index b6a155fb35d1..8c18ffcaa081 100644 --- a/gfx/tests/gtest/TestJobScheduler.cpp +++ b/gfx/tests/gtest/TestJobScheduler.cpp @@ -35,7 +35,7 @@ void MaybeYieldThread() /// Used by the TestCommand to check that tasks are processed in the right order. struct SanityChecker { std::vector mAdvancements; - mozilla::gfx::Mutex mMutex; + mozilla::gfx::CriticalSection mSection; explicit SanityChecker(uint64_t aNumCmdBuffers) { @@ -47,7 +47,7 @@ struct SanityChecker { virtual void Check(uint64_t aJobId, uint64_t aCmdId) { MaybeYieldThread(); - MutexAutoLock lock(&mMutex); + CriticalSectionAutoEnter lock(&mSection); ASSERT_EQ(mAdvancements[aJobId], aCmdId-1); mAdvancements[aJobId] = aCmdId; }