Bug 1083101 - Back 5 patches out due to windows build issues, CLOSED TREE.
authorNicolas Silva <nsilva@mozilla.com>
Thu, 24 Sep 2015 19:47:20 +0200
changeset 264256 e39dfd9e05cbdead9a9b7c9120fabb2c3be98270
parent 264255 cd54e93993b49cfda169a1ddaba7b1cfdd7a2a6a
child 264257 5ce02bfa5d374e42553aa6712e7e24e4f578987d
push id29431
push userkwierso@gmail.com
push dateThu, 24 Sep 2015 23:46:41 +0000
treeherdermozilla-central@eee426604698 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1083101
milestone44.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 - Back 5 patches out due to windows build issues, CLOSED TREE.
gfx/2d/CriticalSection.h
gfx/2d/JobScheduler.cpp
gfx/2d/JobScheduler.h
gfx/2d/JobScheduler_posix.cpp
gfx/2d/JobScheduler_posix.h
gfx/2d/JobScheduler_win32.cpp
gfx/2d/JobScheduler_win32.h
gfx/2d/moz.build
gfx/tests/gtest/TestJobScheduler.cpp
deleted file mode 100644
--- a/gfx/2d/CriticalSection.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/* -*- 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/JobScheduler.cpp
+++ b/gfx/2d/JobScheduler.cpp
@@ -18,17 +18,17 @@ bool JobScheduler::Init(uint32_t aNumThr
   sSingleton = new JobScheduler();
   sSingleton->mNextQueue = 0;
 
   for (uint32_t i = 0; i < aNumQueues; ++i) {
     sSingleton->mDrawingQueues.push_back(new MultiThreadedJobQueue());
   }
 
   for (uint32_t i = 0; i < aNumThreads; ++i) {
-    sSingleton->mWorkerThreads.push_back(WorkerThread::Create(sSingleton->mDrawingQueues[i%aNumQueues]));
+    sSingleton->mWorkerThreads.push_back(new WorkerThread(sSingleton->mDrawingQueues[i%aNumQueues]));
   }
   return true;
 }
 
 void JobScheduler::ShutDown()
 {
   MOZ_ASSERT(IsEnabled());
   if (!IsEnabled()) {
@@ -79,18 +79,17 @@ JobScheduler::SubmitJob(Job* aJob)
 MultiThreadedJobQueue*
 JobScheduler::GetQueueForJob(Job* aJob)
 {
   return aJob->IsPinnedToAThread() ? aJob->GetWorkerThread()->GetJobQueue()
                                     : GetDrawingQueue();
 }
 
 Job::Job(SyncObject* aStart, SyncObject* aCompletion, WorkerThread* aThread)
-: mNextWaitingJob(nullptr)
-, mStartSync(aStart)
+: mStartSync(aStart)
 , mCompletionSync(aCompletion)
 , mPinToThread(aThread)
 {
   if (mStartSync) {
     mStartSync->AddSubsequent(this);
   }
   if (mCompletionSync) {
     mCompletionSync->AddPrerequisite(this);
@@ -120,26 +119,25 @@ SetEventJob::SetEventJob(EventObject* aE
 , mEvent(aEvent)
 {}
 
 SetEventJob::~SetEventJob()
 {}
 
 SyncObject::SyncObject(uint32_t aNumPrerequisites)
 : mSignals(aNumPrerequisites)
-, mFirstWaitingJob(nullptr)
 #ifdef DEBUG
 , mNumPrerequisites(aNumPrerequisites)
 , mAddedPrerequisites(0)
 #endif
 {}
 
 SyncObject::~SyncObject()
 {
-  MOZ_ASSERT(mFirstWaitingJob == nullptr);
+  MOZ_ASSERT(mWaitingJobs.size() == 0);
 }
 
 bool
 SyncObject::Register(Job* aJob)
 {
   MOZ_ASSERT(aJob);
 
   // For now, ensure that when we schedule the first subsequent, we have already
@@ -181,51 +179,38 @@ SyncObject::Signal()
   if (signals == 0) {
     SubmitWaitingJobs();
   }
 }
 
 void
 SyncObject::AddWaitingJob(Job* aJob)
 {
-  // Push (using atomics) the task into the list of waiting tasks.
-  for (;;) {
-    Job* first = mFirstWaitingJob;
-    aJob->mNextWaitingJob = first;
-    if (mFirstWaitingJob.compareExchange(first, aJob)) {
-      break;
-    }
-  }
+  MutexAutoLock lock(&mMutex);
+  mWaitingJobs.push_back(aJob);
 }
 
 void SyncObject::SubmitWaitingJobs()
 {
-  // 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 the end of this method, so
-  // hold a strong ref to prevent that!
-  RefPtr<SyncObject> kungFuDeathGrip(this);
+  std::vector<Job*> 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 mWaitingJobs.clear(), so
+    // hold a strong ref to prevent that!
+    RefPtr<SyncObject> kungFuDeathGrip(this);
 
-  // First atomically swap mFirstWaitingJob and waitingJobs...
-  Job* waitingJobs = nullptr;
-  for (;;) {
-    waitingJobs = mFirstWaitingJob;
-    if (mFirstWaitingJob.compareExchange(waitingJobs, nullptr)) {
-      break;
-    }
+    MutexAutoLock lock(&mMutex);
+    tasksToSubmit = Move(mWaitingJobs);
+    mWaitingJobs.clear();
   }
 
-  // ... and submit all of the waiting tasks in waitingJob now that they belong
-  // to this thread.
-  while (waitingJobs) {
-    Job* next = waitingJobs->mNextWaitingJob;
-    waitingJobs->mNextWaitingJob = nullptr;
-    JobScheduler::GetQueueForJob(waitingJobs)->SubmitJob(waitingJobs);
-    waitingJobs = next;
+  for (Job* task : tasksToSubmit) {
+    JobScheduler::GetQueueForJob(task)->SubmitJob(task);
   }
 }
 
 bool
 SyncObject::IsSignaled()
 {
   return mSignals == 0;
 }
@@ -242,38 +227,10 @@ SyncObject::AddPrerequisite(Job* aJob)
   MOZ_ASSERT(++mAddedPrerequisites <= mNumPrerequisites);
 }
 
 void
 SyncObject::AddSubsequent(Job* aJob)
 {
 }
 
-WorkerThread::WorkerThread(MultiThreadedJobQueue* aJobQueue)
-: mQueue(aJobQueue)
-{
-  aJobQueue->RegisterThread();
-}
-
-void
-WorkerThread::Run()
-{
-  SetName("gfx worker");
-
-  for (;;) {
-    Job* commands = nullptr;
-    if (!mQueue->WaitForJob(commands)) {
-      mQueue->UnregisterThread();
-      return;
-    }
-
-    JobStatus status = JobScheduler::ProcessJob(commands);
-
-    if (status == JobStatus::Error) {
-      // Don't try to handle errors for now, but that's open to discussions.
-      // I expect errors to be mostly OOM issues.
-      MOZ_CRASH();
-    }
-  }
-}
-
 } //namespace
 } //namespace
--- a/gfx/2d/JobScheduler.h
+++ b/gfx/2d/JobScheduler.h
@@ -10,24 +10,21 @@
 #include "mozilla/gfx/Types.h"
 
 #ifdef WIN32
 #include "mozilla/gfx/JobScheduler_win32.h"
 #else
 #include "mozilla/gfx/JobScheduler_posix.h"
 #endif
 
-#include <vector>
-
 namespace mozilla {
 namespace gfx {
 
 class MultiThreadedJobQueue;
 class SyncObject;
-class WorkerThread;
 
 class JobScheduler {
 public:
   /// Return one of the queues that the drawing worker threads pull from, chosen
   /// pseudo-randomly.
   static MultiThreadedJobQueue* GetDrawingQueue()
   {
     return sSingleton->mDrawingQueues[
@@ -104,26 +101,19 @@ public:
   //already_AddRefed<SyncObject> GetAndResetStartSync();
   SyncObject* GetStartSync() { return mStartSync; }
 
   bool IsPinnedToAThread() const { return !!mPinToThread; }
 
   WorkerThread* GetWorkerThread() { return mPinToThread; }
 
 protected:
-  // An intrusive linked list of tasks waiting for a sync object to enter the
-  // signaled state. When the task is not waiting for a sync object, mNextWaitingJob
-  // should be null. This is only accessed from the thread that owns the task.
-  Job* mNextWaitingJob;
-
   RefPtr<SyncObject> mStartSync;
   RefPtr<SyncObject> mCompletionSync;
   WorkerThread* mPinToThread;
-
-  friend class SyncObject;
 };
 
 class EventObject;
 
 /// This task will set an EventObject.
 ///
 /// Typically used as the final task, so that the main thread can block on the
 /// corresponfing EventObject until all of the tasks are processed.
@@ -207,44 +197,35 @@ private:
   // Called by Job's constructor
   void AddSubsequent(Job* aJob);
   void AddPrerequisite(Job* aJob);
 
   void AddWaitingJob(Job* aJob);
 
   void SubmitWaitingJobs();
 
+  std::vector<Job*> mWaitingJobs;
+  Mutex mMutex; // for concurrent access to mWaintingJobs
   Atomic<int32_t> mSignals;
-  Atomic<Job*> mFirstWaitingJob;
 
 #ifdef DEBUG
   uint32_t mNumPrerequisites;
   Atomic<uint32_t> mAddedPrerequisites;
 #endif
 
   friend class Job;
   friend class JobScheduler;
 };
 
-/// Base class for worker threads.
-class WorkerThread
-{
-public:
-  static WorkerThread* Create(MultiThreadedJobQueue* aJobQueue);
-
-  virtual ~WorkerThread() {}
-
-  void Run();
 
-  MultiThreadedJobQueue* GetJobQueue() { return mQueue; }
-
+/// RAII helper.
+struct MutexAutoLock {
+    MutexAutoLock(Mutex* aMutex) : mMutex(aMutex) { mMutex->Lock(); }
+    ~MutexAutoLock() { mMutex->Unlock(); }
 protected:
-  explicit WorkerThread(MultiThreadedJobQueue* aJobQueue);
+    Mutex* mMutex;
+};
 
-  virtual void SetName(const char* aName) {}
-
-  MultiThreadedJobQueue* mQueue;
-};
 
 } // namespace
 } // namespace
 
 #endif
\ No newline at end of file
--- a/gfx/2d/JobScheduler_posix.cpp
+++ b/gfx/2d/JobScheduler_posix.cpp
@@ -6,62 +6,16 @@
 #include "JobScheduler.h"
 #include "mozilla/gfx/Logging.h"
 
 using namespace std;
 
 namespace mozilla {
 namespace gfx {
 
-void* ThreadCallback(void* threadData);
-
-class WorkerThreadPosix : public WorkerThread {
-public:
-  explicit WorkerThreadPosix(MultiThreadedJobQueue* aJobQueue)
-  : WorkerThread(aJobQueue)
-  {
-    pthread_create(&mThread, nullptr, ThreadCallback, static_cast<WorkerThread*>(this));
-  }
-
-  ~WorkerThreadPosix()
-  {
-    pthread_join(mThread, nullptr);
-  }
-
-  virtual void SetName(const char* aName) override
-  {
-    // Call this from the thread itself because of Mac.
-#ifdef XP_MACOSX
-    pthread_setname_np(aName);
-#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
-    pthread_set_name_np(mThread, aName);
-#elif defined(__NetBSD__)
-    pthread_setname_np(mThread, "%s", (void*)aName);
-#else
-    pthread_setname_np(mThread, aName);
-#endif
-  }
-
-protected:
-  pthread_t mThread;
-};
-
-void* ThreadCallback(void* threadData)
-{
-  WorkerThread* thread = static_cast<WorkerThread*>(threadData);
-  thread->Run();
-  return nullptr;
-}
-
-WorkerThread*
-WorkerThread::Create(MultiThreadedJobQueue* aJobQueue)
-{
-  return new WorkerThreadPosix(aJobQueue);
-}
-
 MultiThreadedJobQueue::MultiThreadedJobQueue()
 : mThreadsCount(0)
 , mShuttingDown(false)
 {}
 
 MultiThreadedJobQueue::~MultiThreadedJobQueue()
 {
   MOZ_ASSERT(mJobs.empty());
@@ -149,16 +103,72 @@ MultiThreadedJobQueue::UnregisterThread(
 {
   MutexAutoLock lock(&mMutex);
   mThreadsCount -= 1;
   if (mThreadsCount == 0) {
     mShutdownCondvar.Broadcast();
   }
 }
 
+void* ThreadCallback(void* threadData)
+{
+  WorkerThread* thread = (WorkerThread*)threadData;
+  thread->Run();
+  return nullptr;
+}
+
+WorkerThread::WorkerThread(MultiThreadedJobQueue* aJobQueue)
+: mQueue(aJobQueue)
+{
+  aJobQueue->RegisterThread();
+  pthread_create(&mThread, nullptr, ThreadCallback, this);
+}
+
+WorkerThread::~WorkerThread()
+{
+  pthread_join(mThread, nullptr);
+}
+
+void
+WorkerThread::SetName(const char* aName)
+{
+  // Call this from the thread itself because of Mac.
+#ifdef XP_MACOSX
+  pthread_setname_np(aName);
+#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__OpenBSD__)
+  pthread_set_name_np(mThread, aName);
+#elif defined(__NetBSD__)
+  pthread_setname_np(mThread, "%s", (void*)aName);
+#else
+  pthread_setname_np(mThread, aName);
+#endif
+}
+
+void
+WorkerThread::Run()
+{
+  SetName("gfx worker");
+
+  for (;;) {
+    Job* commands = nullptr;
+    if (!mQueue->WaitForJob(commands)) {
+      mQueue->UnregisterThread();
+      return;
+    }
+
+    JobStatus status = JobScheduler::ProcessJob(commands);
+
+    if (status == JobStatus::Error) {
+      // Don't try to handle errors for now, but that's open to discussions.
+      // I expect errors to be mostly OOM issues.
+      MOZ_CRASH();
+    }
+  }
+}
+
 EventObject::EventObject()
 : mIsSet(false)
 {}
 
 EventObject::~EventObject()
 {}
 
 bool
--- a/gfx/2d/JobScheduler_posix.h
+++ b/gfx/2d/JobScheduler_posix.h
@@ -11,27 +11,49 @@
 #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 Job;
 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);
+  }
 
-typedef mozilla::gfx::CriticalSection Mutex;
-typedef mozilla::gfx::CriticalSectionAutoEnter MutexAutoLock;
+  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;
+};
 
 // posix platforms only!
 class PosixCondVar {
 public:
   PosixCondVar() {
     DebugOnly<int> err = pthread_cond_init(&mCond, nullptr);
     MOZ_ASSERT(!err);
   }
@@ -104,16 +126,37 @@ protected:
   PosixCondVar mAvailableCondvar;
   PosixCondVar mShutdownCondvar;
   int32_t mThreadsCount;
   bool mShuttingDown;
 
   friend class WorkerThread;
 };
 
+/// Worker thread that continuously dequeues Jobs from a MultiThreadedJobQueue
+/// and process them.
+///
+/// The public interface of this class must remain identical to its equivalent
+/// in JobScheduler_win32.h
+class WorkerThread {
+public:
+  explicit WorkerThread(MultiThreadedJobQueue* aJobQueue);
+
+  ~WorkerThread();
+
+  void Run();
+
+  MultiThreadedJobQueue* GetJobQueue() { return mQueue; }
+protected:
+  void SetName(const char* name);
+
+  MultiThreadedJobQueue* mQueue;
+  pthread_t mThread;
+};
+
 /// An object that a thread can synchronously wait on.
 /// Usually set by a SetEventJob.
 class EventObject : public external::AtomicRefCounted<EventObject>
 {
 public:
   MOZ_DECLARE_REFCOUNTED_TYPENAME(EventObject)
 
   EventObject();
deleted file mode 100644
--- a/gfx/2d/JobScheduler_win32.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-/* -*- 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/. */
-
-#include "JobScheduler.h"
-#include "mozilla/gfx/Logging.h"
-
-using namespace std;
-
-namespace mozilla {
-namespace gfx {
-
-DWORD __stdcall ThreadCallback(void* threadData);
-
-class WorkerThreadWin32 : public WorkerThread {
-public:
-  explicit WorkerThreadWin32(MultiThreadedJobQueue* aJobQueue)
-  : WorkerThread(aJobQueue)
-  {
-    mThread = ::CreateThread(nullptr, 0, ThreadCallback, static_cast<WorkerThread*>(this), 0, nullptr);
-  }
-
-  ~WorkerThreadWin32()
-  {
-    ::WaitForSingleObject(mThread, INFINITE);
-    ::CloseHandle(mThread);
-  }
-
-protected:
-  HANDLE mThread;
-};
-
-DWORD __stdcall ThreadCallback(void* threadData)
-{
-  WorkerThread* thread = static_cast<WorkerThread*>(threadData);
-  thread->Run();
-  return 0;
-}
-
-WorkerThread*
-WorkerThread::Create(MultiThreadedJobQueue* aJobQueue)
-{
-  return new WorkerThreadWin32(aJobQueue);
-}
-
-bool
-MultiThreadedJobQueue::PopJob(Job*& aOutJob, AccessType aAccess)
-{
-  for (;;) {
-    while (aAccess == BLOCKING && mJobs.empty()) {
-      {
-        CriticalSectionAutoEnter lock(&mSection);
-        if (mShuttingDown) {
-          return false;
-        }
-      }
-
-      HANDLE handles[] = { mAvailableEvent, mShutdownEvent };
-      ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);
-    }
-
-    CriticalSectionAutoEnter lock(&mSection);
-
-    if (mShuttingDown) {
-      return false;
-    }
-
-    if (mJobs.empty()) {
-      if (aAccess == NON_BLOCKING) {
-        return false;
-      }
-      continue;
-    }
-
-    Job* task = mJobs.front();
-    MOZ_ASSERT(task);
-
-    mJobs.pop_front();
-
-    if (mJobs.empty()) {
-      ::ResetEvent(mAvailableEvent);
-    }
-
-    aOutJob = task;
-    return true;
-  }
-}
-
-void
-MultiThreadedJobQueue::SubmitJob(Job* aJob)
-{
-  MOZ_ASSERT(aJob);
-  CriticalSectionAutoEnter lock(&mSection);
-  mJobs.push_back(aJob);
-  ::SetEvent(mAvailableEvent);
-}
-
-void
-MultiThreadedJobQueue::ShutDown()
-{
-  {
-    CriticalSectionAutoEnter lock(&mSection);
-    mShuttingDown = true;
-  }
-  while (mThreadsCount) {
-    ::SetEvent(mAvailableEvent);
-    ::WaitForSingleObject(mShutdownEvent, INFINITE);
-  }
-}
-
-size_t
-MultiThreadedJobQueue::NumJobs()
-{
-  CriticalSectionAutoEnter lock(&mSection);
-  return mJobs.size();
-}
-
-bool
-MultiThreadedJobQueue::IsEmpty()
-{
-  CriticalSectionAutoEnter lock(&mSection);
-  return mJobs.empty();
-}
-
-void
-MultiThreadedJobQueue::RegisterThread()
-{
-  mThreadsCount += 1;
-}
-
-void
-MultiThreadedJobQueue::UnregisterThread()
-{
-  CriticalSectionAutoEnter lock(&mSection);
-  mThreadsCount -= 1;
-  if (mThreadsCount == 0) {
-    ::SetEvent(mShutdownEvent);
-  }
-}
-
-} // namespace
-} // namespace
--- a/gfx/2d/JobScheduler_win32.h
+++ b/gfx/2d/JobScheduler_win32.h
@@ -5,96 +5,72 @@
 
 #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 <synchapi.h>
-#include <list>
 
 namespace mozilla {
 namespace gfx {
 
 class WorkerThread;
 class Job;
 
+class Mutex {
+public:
+  Mutex() { NOT_IMPLEMENTED; }
+  ~Mutex() { NOT_IMPLEMENTED; }
+  void Lock() { NOT_IMPLEMENTED; }
+  void Unlock() { NOT_IMPLEMENTED; }
+};
+
 // The public interface of this class must remain identical to its equivalent
 // in JobScheduler_posix.h
 class MultiThreadedJobQueue {
 public:
   enum AccessType {
     BLOCKING,
     NON_BLOCKING
   };
 
-  MultiThreadedJobQueue()
-  : mThreadsCount(0)
-  , mShuttingDown(false)
-  {
-    mAvailableEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
-    mShutdownEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr);
-  }
-
-  ~MultiThreadedJobQueue()
-  {
-    ::CloseHandle(mAvailableEvent);
-    ::CloseHandle(mShutdownEvent);
-  }
-
-  bool WaitForJob(Job*& aOutJob) { return PopJob(aOutJob, BLOCKING); }
-
-  bool PopJob(Job*& aOutJob, AccessType aAccess);
-
-  void SubmitJob(Job* aJob);
-
-  void ShutDown();
-
-  size_t NumJobs();
-
-  bool IsEmpty();
-
-  void RegisterThread();
-
-  void UnregisterThread();
-
-protected:
-  std::list<Job*> mJobs;
-  CriticalSection mSection;
-  HANDLE mAvailableEvent;
-  HANDLE mShutdownEvent;
-  int32_t mThreadsCount;
-  bool mShuttingDown;
+  bool WaitForJob(Job*& aOutCommands) { NOT_IMPLEMENTED; }
+  bool PopJob(Job*& aOutCommands, AccessType aAccess) { NOT_IMPLEMENTED; }
+  void SubmitJob(Job* aCommands) { NOT_IMPLEMENTED; }
+  void ShutDown() { NOT_IMPLEMENTED; }
+  size_t NumJobs() { NOT_IMPLEMENTED;  }
+  bool IsEmpty() { NOT_IMPLEMENTED; }
+  void RegisterThread() { NOT_IMPLEMENTED; }
+  void UnregisterThread() { NOT_IMPLEMENTED; }
 
   friend class WorkerThread;
 };
 
 
 // The public interface of this class must remain identical to its equivalent
 // in JobScheduler_posix.h
 class EventObject : public external::AtomicRefCounted<EventObject>
 {
 public:
   MOZ_DECLARE_REFCOUNTED_TYPENAME(EventObject)
 
-  EventObject() { mEvent = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); }
-
-  ~EventObject() { ::CloseHandle(mEvent); }
-
-  void Wait() { ::WaitForSingleObject(mEvent, INFINITE); }
+  EventObject() { NOT_IMPLEMENTED; }
+  ~EventObject() { NOT_IMPLEMENTED; }
+  void Wait() { NOT_IMPLEMENTED; }
+  bool Peak() { NOT_IMPLEMENTED; }
+  void Set() { NOT_IMPLEMENTED; }
+};
 
-  bool Peak() { return ::WaitForSingleObject(mEvent, 0) == WAIT_OBJECT_0; }
-
-  void Set() { ::SetEvent(mEvent); }
-protected:
-  // TODO: it's expensive to create events so we should try to reuse them
-  HANDLE mEvent;
+// The public interface of this class must remain identical to its equivalent
+// in JobScheduler_posix.h
+class WorkerThread {
+public:
+  explicit WorkerThread(MultiThreadedJobQueue* aJobQueue) { NOT_IMPLEMENTED; }
+  void Run();
 };
 
 } // namespace
 } // namespace
 
 #endif
 #endif
--- a/gfx/2d/moz.build
+++ b/gfx/2d/moz.build
@@ -15,17 +15,16 @@ 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',
     'JobScheduler.h',
     'JobScheduler_posix.h',
@@ -60,17 +59,16 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'coco
         'SourceSurfaceCG.cpp',
     ]
 elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     SOURCES += [
         'DrawTargetD2D.cpp',
         'DrawTargetD2D1.cpp',
         'ExtendInputEffectD2D1.cpp',
         'FilterNodeD2D1.cpp',
-        'JobScheduler_win32.cpp',
         'PathD2D.cpp',
         'RadialGradientEffectD2D1.cpp',
         'ScaledFontDWrite.cpp',
         'ScaledFontWin.cpp',
         'SourceSurfaceD2D.cpp',
         'SourceSurfaceD2D1.cpp',
         'SourceSurfaceD2DTarget.cpp',
     ]
--- a/gfx/tests/gtest/TestJobScheduler.cpp
+++ b/gfx/tests/gtest/TestJobScheduler.cpp
@@ -1,58 +1,55 @@
 /* vim:set ts=2 sw=2 sts=2 et: */
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
+#ifndef WIN32
+
 #include "gtest/gtest.h"
 #include "gmock/gmock.h"
 
 #include "mozilla/gfx/JobScheduler.h"
 
-#ifndef WIN32
 #include <pthread.h>
 #include <sched.h>
-#endif
-
 #include <stdlib.h>
 #include <time.h>
 
 namespace test_scheduler {
 
 using namespace mozilla::gfx;
 using namespace mozilla;
 
 // Artificially cause threads to yield randomly in an attempt to make racy
 // things more apparent (if any).
 void MaybeYieldThread()
 {
-#ifndef WIN32
   if (rand() % 5 == 0) {
     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::CriticalSection mSection;
+  mozilla::gfx::Mutex mMutex;
 
   explicit SanityChecker(uint64_t aNumCmdBuffers)
   {
     for (uint32_t i = 0; i < aNumCmdBuffers; ++i) {
       mAdvancements.push_back(0);
     }
   }
 
   virtual void Check(uint64_t aJobId, uint64_t aCmdId)
   {
     MaybeYieldThread();
-    CriticalSectionAutoEnter lock(&mSection);
+    MutexAutoLock lock(&mMutex);
     ASSERT_EQ(mAdvancements[aJobId], aCmdId-1);
     mAdvancements[aJobId] = aCmdId;
   }
 };
 
 /// Run checks that are specific to TestSchulerJoin.
 struct JoinTestSanityCheck : public SanityChecker {
   bool mSpecialJobHasRun;
@@ -240,8 +237,10 @@ TEST(Moz2D, JobScheduler_Chain) {
       for (uint32_t buffers = 1; buffers < 100; buffers += 3) {
         mozilla::gfx::JobScheduler::Init(threads, queues);
         test_scheduler::TestSchedulerChain(threads, buffers);
         mozilla::gfx::JobScheduler::ShutDown();
       }
     }
   }
 }
+
+#endif