Bug 1083101 - rename gfx::Mutex into gfx::CriticalSection and move it to its own file. r=jrmuizel
authorNicolas Silva <nsilva@mozilla.com>
Fri, 04 Sep 2015 14:28:20 +0200
changeset 260926 fc0ab17babda077710d61a0102ed494818065337
parent 260925 051166e3d6e4fd7413dee59206f0d64d93a569f3
child 260927 c8de1f3f0bf3ff750a4cb8abddf26d3986ebeaa6
push id29329
push userkwierso@gmail.com
push dateFri, 04 Sep 2015 22:34:50 +0000
treeherdermozilla-central@e816a7a854a3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1083101
milestone43.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1083101 - rename gfx::Mutex into gfx::CriticalSection and move it to its own file. r=jrmuizel
gfx/2d/CriticalSection.h
gfx/2d/TaskScheduler.cpp
gfx/2d/TaskScheduler.h
gfx/2d/TaskScheduler_posix.h
gfx/2d/TaskScheduler_win32.cpp
gfx/2d/TaskScheduler_win32.h
gfx/2d/moz.build
gfx/tests/gtest/TestTaskScheduler.cpp
new file mode 100644
--- /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 <windows.h>
+#else
+#include <pthread.h>
+#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<int> err = pthread_mutex_init(&mMutex, nullptr);
+    MOZ_ASSERT(!err);
+  }
+
+  ~CriticalSection() {
+    DebugOnly<int> err = pthread_mutex_destroy(&mMutex);
+    MOZ_ASSERT(!err);
+  }
+
+  void Enter() {
+    DebugOnly<int> err = pthread_mutex_lock(&mMutex);
+    MOZ_ASSERT(!err);
+  }
+
+  void Leave() {
+    DebugOnly<int> 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
--- a/gfx/2d/TaskScheduler.cpp
+++ b/gfx/2d/TaskScheduler.cpp
@@ -170,32 +170,32 @@ SyncObject::Signal()
   if (hasSubmittedSubsequent && signals == 0) {
     SubmitWaitingTasks();
   }
 }
 
 void
 SyncObject::AddWaitingTask(Task* aTask)
 {
-  MutexAutoLock lock(&mMutex);
+  CriticalSectionAutoEnter lock(&mWaitingTasksSection);
   mWaitingTasks.push_back(aTask);
 }
 
 void SyncObject::SubmitWaitingTasks()
 {
   std::vector<Task*> tasksToSubmit;
   {
     // Scheduling the tasks can cause code that modifies <this>'s reference
     // count to run concurrently, and cause the caller of this function to
     // be owned by another thread. We need to make sure the reference count
     // does not reach 0 on another thread before mWaitingTasks.clear(), so
     // hold a strong ref to prevent that!
     RefPtr<SyncObject> kungFuDeathGrip(this);
 
-    MutexAutoLock lock(&mMutex);
+    CriticalSectionAutoEnter lock(&mWaitingTasksSection);
     tasksToSubmit = Move(mWaitingTasks);
     mWaitingTasks.clear();
   }
 
   for (Task* task : tasksToSubmit) {
     task->GetTaskQueue()->SubmitTask(task);
   }
 }
--- a/gfx/2d/TaskScheduler.h
+++ b/gfx/2d/TaskScheduler.h
@@ -190,33 +190,24 @@ private:
 
 #ifdef DEBUG
   // For debugging purposes only.
   std::vector<Task*> mPrerequisites;
   std::vector<Task*> mSubsequents;
 #endif
 
   std::vector<Task*> mWaitingTasks;
-  Mutex mMutex; // for concurrent access to mWaintingTasks
+  CriticalSection mWaitingTasksSection; // for concurrent access to mWaintingTasks
   Atomic<uint32_t> mSignals;
   Atomic<bool> mHasSubmittedSubsequent;
 
   friend class Task;
   friend class TaskScheduler;
 };
 
-
-/// RAII helper.
-struct MutexAutoLock {
-    MutexAutoLock(Mutex* aMutex) : mMutex(aMutex) { mMutex->Lock(); }
-    ~MutexAutoLock() { mMutex->Unlock(); }
-protected:
-    Mutex* mMutex;
-};
-
 /// Base class for worker threads.
 class WorkerThread
 {
 public:
   static WorkerThread* Create(MultiThreadedTaskQueue* aTaskQueue);
 
   virtual ~WorkerThread() {}
 
--- a/gfx/2d/TaskScheduler_posix.h
+++ b/gfx/2d/TaskScheduler_posix.h
@@ -11,50 +11,27 @@
 #include <vector>
 #include <list>
 #include <pthread.h>
 #include <stdint.h>
 #include <stdio.h>
 
 #include "mozilla/RefPtr.h"
 #include "mozilla/DebugOnly.h"
+#include "mozilla/gfx/CriticalSection.h"
 
 namespace mozilla {
 namespace gfx {
 
 class Task;
 class PosixCondVar;
 class WorkerThread;
 
-class Mutex {
-public:
-  Mutex() {
-    DebugOnly<int> err = pthread_mutex_init(&mMutex, nullptr);
-    MOZ_ASSERT(!err);
-  }
-
-  ~Mutex() {
-    DebugOnly<int> err = pthread_mutex_destroy(&mMutex);
-    MOZ_ASSERT(!err);
-  }
-
-  void Lock() {
-    DebugOnly<int> err = pthread_mutex_lock(&mMutex);
-    MOZ_ASSERT(!err);
-  }
-
-  void Unlock() {
-    DebugOnly<int> 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 {
 public:
   PosixCondVar() {
     DebugOnly<int> err = pthread_cond_init(&mCond, nullptr);
     MOZ_ASSERT(!err);
   }
--- a/gfx/2d/TaskScheduler_win32.cpp
+++ b/gfx/2d/TaskScheduler_win32.cpp
@@ -45,27 +45,27 @@ WorkerThread::Create(MultiThreadedTaskQu
 }
 
 bool
 MultiThreadedTaskQueue::PopTask(Task*& aOutTask, AccessType aAccess)
 {
   for (;;) {
     while (aAccess == BLOCKING && mTasks.empty()) {
       {
-        MutexAutoLock lock(&mMutex);
+        CriticalSectionAutoEnter lock(&mSection);
         if (mShuttingDown) {
           return false;
         }
       }
 
       HANDLE handles[] = { mAvailableEvent, mShutdownEvent };
       ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
     }
 
-    MutexAutoLock lock(&mMutex);
+    CriticalSectionAutoEnter lock(&mSection);
 
     if (mShuttingDown) {
       return false;
     }
 
     if (mTasks.empty()) {
       if (aAccess == NON_BLOCKING) {
         return false;
@@ -87,58 +87,58 @@ MultiThreadedTaskQueue::PopTask(Task*& a
   }
 }
 
 void
 MultiThreadedTaskQueue::SubmitTask(Task* aTask)
 {
   MOZ_ASSERT(aTask);
   MOZ_ASSERT(aTask->GetTaskQueue() == this);
-  MutexAutoLock lock(&mMutex);
+  CriticalSectionAutoEnter lock(&mSection);
   mTasks.push_back(aTask);
   ::SetEvent(mAvailableEvent);
 }
 
 void
 MultiThreadedTaskQueue::ShutDown()
 {
   {
-    MutexAutoLock lock(&mMutex);
+    CriticalSectionAutoEnter lock(&mSection);
     mShuttingDown = true;
   }
   while (mThreadsCount) {
     ::SetEvent(mAvailableEvent);
     ::WaitForSingleObject(mShutdownEvent, INFINITE);
   }
 }
 
 size_t
 MultiThreadedTaskQueue::NumTasks()
 {
-  MutexAutoLock lock(&mMutex);
+  CriticalSectionAutoEnter lock(&mSection);
   return mTasks.size();
 }
 
 bool
 MultiThreadedTaskQueue::IsEmpty()
 {
-  MutexAutoLock lock(&mMutex);
+  CriticalSectionAutoEnter lock(&mSection);
   return mTasks.empty();
 }
 
 void
 MultiThreadedTaskQueue::RegisterThread()
 {
   mThreadsCount += 1;
 }
 
 void
 MultiThreadedTaskQueue::UnregisterThread()
 {
-  MutexAutoLock lock(&mMutex);
+  CriticalSectionAutoEnter lock(&mSection);
   mThreadsCount -= 1;
   if (mThreadsCount == 0) {
     ::SetEvent(mShutdownEvent);
   }
 }
 
 } // namespace
 } // namespace
--- a/gfx/2d/TaskScheduler_win32.h
+++ b/gfx/2d/TaskScheduler_win32.h
@@ -5,60 +5,26 @@
 
 #ifdef WIN32
 #ifndef MOZILLA_GFX_TASKSCHEDULER_WIN32_H_
 #define MOZILLA_GFX_TASKSCHEDULER_WIN32_H_
 
 #define NOT_IMPLEMENTED MOZ_CRASH("Not implemented")
 
 #include "mozilla/RefPtr.h"
+#include "mozilla/gfx/CriticalSection.h"
 #include <windows.h>
 #include <list>
 
 namespace mozilla {
 namespace gfx {
 
 class WorkerThread;
 class Task;
 
-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 TaskScheduler_posix.h
 class MultiThreadedTaskQueue {
 public:
   enum AccessType {
     BLOCKING,
     NON_BLOCKING
   };
@@ -90,17 +56,17 @@ public:
   bool IsEmpty();
 
   void RegisterThread();
 
   void UnregisterThread();
 
 protected:
   std::list<Task*> mTasks;
-  Mutex mMutex;
+  CriticalSection mSection;
   HANDLE mAvailableEvent;
   HANDLE mShutdownEvent;
   int32_t mThreadsCount;
   bool mShuttingDown;
 
   friend class WorkerThread;
 };
 
--- a/gfx/2d/moz.build
+++ b/gfx/2d/moz.build
@@ -15,16 +15,17 @@ EXPORTS.mozilla.gfx += [
     'BasePoint.h',
     'BasePoint3D.h',
     'BasePoint4D.h',
     'BaseRect.h',
     'BaseSize.h',
     'Blur.h',
     'BorrowedContext.h',
     'Coord.h',
+    'CriticalSection.h',
     'DataSurfaceHelpers.h',
     'DrawTargetTiled.h',
     'Filters.h',
     'Helpers.h',
     'HelpersCairo.h',
     'IterableArena.h',
     'Logging.h',
     'Matrix.h',
--- a/gfx/tests/gtest/TestTaskScheduler.cpp
+++ b/gfx/tests/gtest/TestTaskScheduler.cpp
@@ -30,29 +30,29 @@ void MaybeYieldThread()
     sched_yield();
   }
 #endif
 }
 
 /// Used by the TestCommand to check that tasks are processed in the right order.
 struct SanityChecker {
   std::vector<uint64_t> mAdvancements;
-  mozilla::gfx::Mutex mMutex;
+  mozilla::gfx::CriticalSection mSection;
 
   explicit SanityChecker(uint64_t aNumCmdBuffers)
   {
     for (uint32_t i = 0; i < aNumCmdBuffers; ++i) {
       mAdvancements.push_back(0);
     }
   }
 
   virtual void Check(uint64_t aTaskId, uint64_t aCmdId)
   {
     MaybeYieldThread();
-    MutexAutoLock lock(&mMutex);
+    CriticalSectionAutoEnter lock(&mSection);
     ASSERT_EQ(mAdvancements[aTaskId], aCmdId-1);
     mAdvancements[aTaskId] = aCmdId;
   }
 };
 
 /// Run checks that are specific to TestSchulerJoin.
 struct JoinTestSanityCheck : public SanityChecker {
   bool mSpecialTaskHasRun;