Bug 884281 - use mozilla::Atomic in xpcom/; r=bsmedberg,jlebar
authorNathan Froyd <froydnj@mozilla.com>
Thu, 22 Aug 2013 11:14:42 -0400
changeset 143984 b3070fcb40c9ebd6f82460e4ad15f7e6959c46e2
parent 143983 b4b8ecfae683096feb9b624bfc1a606d70762fef
child 143985 3a76d832921985e67af7744562276d128b12699b
push id32833
push usernfroyd@mozilla.com
push dateFri, 23 Aug 2013 00:48:44 +0000
treeherdermozilla-inbound@c40ac8b1df0a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbsmedberg, jlebar
bugs884281
milestone26.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 884281 - use mozilla::Atomic in xpcom/; r=bsmedberg,jlebar
xpcom/base/AvailableMemoryTracker.cpp
xpcom/base/nsDebugImpl.cpp
xpcom/base/nsExceptionService.cpp
xpcom/base/nsExceptionService.h
xpcom/base/nsMemoryImpl.cpp
xpcom/base/nsMemoryImpl.h
xpcom/base/nsMemoryInfoDumper.cpp
xpcom/string/public/nsStringBuffer.h
xpcom/string/src/nsSubstring.cpp
xpcom/threads/TimerThread.cpp
xpcom/threads/TimerThread.h
xpcom/threads/nsTimerImpl.cpp
--- a/xpcom/base/AvailableMemoryTracker.cpp
+++ b/xpcom/base/AvailableMemoryTracker.cpp
@@ -2,28 +2,28 @@
 /* vim:set ts=2 sw=2 sts=2 ci et: */
 /* 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 "mozilla/AvailableMemoryTracker.h"
 
 #include "prinrval.h"
-#include "pratom.h"
 #include "prenv.h"
 
 #include "nsIMemoryReporter.h"
 #include "nsIObserver.h"
 #include "nsIObserverService.h"
 #include "nsIRunnable.h"
 #include "nsISupports.h"
 #include "nsMemoryPressure.h"
 #include "nsPrintfCString.h"
 #include "nsThread.h"
 
+#include "mozilla/Atomics.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 
 #if defined(XP_WIN)
 #   include "nsWindowsDllInterceptor.h"
 #   include <windows.h>
 #endif
 
@@ -123,19 +123,19 @@ void safe_write(uint64_t x)
 #define DEBUG_WARN_IF_FALSE(cond, msg)
 #endif
 
 uint32_t sLowVirtualMemoryThreshold = 0;
 uint32_t sLowCommitSpaceThreshold = 0;
 uint32_t sLowPhysicalMemoryThreshold = 0;
 uint32_t sLowMemoryNotificationIntervalMS = 0;
 
-uint32_t sNumLowVirtualMemEvents = 0;
-uint32_t sNumLowCommitSpaceEvents = 0;
-uint32_t sNumLowPhysicalMemEvents = 0;
+Atomic<uint32_t> sNumLowVirtualMemEvents;
+Atomic<uint32_t> sNumLowCommitSpaceEvents;
+Atomic<uint32_t> sNumLowPhysicalMemEvents;
 
 WindowsDllInterceptor sKernel32Intercept;
 WindowsDllInterceptor sGdi32Intercept;
 
 // Has Init() been called?
 bool sInitialized = false;
 
 // Has Activate() been called?  The hooks don't do anything until this happens.
@@ -207,29 +207,29 @@ void CheckMemAvailable()
   if (success)
   {
     // sLowVirtualMemoryThreshold is in MB, but ullAvailVirtual is in bytes.
     if (stat.ullAvailVirtual < sLowVirtualMemoryThreshold * 1024 * 1024) {
       // If we're running low on virtual memory, unconditionally schedule the
       // notification.  We'll probably crash if we run out of virtual memory,
       // so don't worry about firing this notification too often.
       LOG("Detected low virtual memory.");
-      PR_ATOMIC_INCREMENT(&sNumLowVirtualMemEvents);
+      ++sNumLowVirtualMemEvents;
       NS_DispatchEventualMemoryPressure(MemPressure_New);
     }
     else if (stat.ullAvailPageFile < sLowCommitSpaceThreshold * 1024 * 1024) {
       LOG("Detected low available page file space.");
       if (MaybeScheduleMemoryPressureEvent()) {
-        PR_ATOMIC_INCREMENT(&sNumLowCommitSpaceEvents);
+        ++sNumLowCommitSpaceEvents;
       }
     }
     else if (stat.ullAvailPhys < sLowPhysicalMemoryThreshold * 1024 * 1024) {
       LOG("Detected low physical memory.");
       if (MaybeScheduleMemoryPressureEvent()) {
-        PR_ATOMIC_INCREMENT(&sNumLowPhysicalMemEvents);
+        ++sNumLowPhysicalMemEvents;
       }
     }
   }
 }
 
 LPVOID WINAPI
 VirtualAllocHook(LPVOID aAddress, SIZE_T aSize,
                  DWORD aAllocationType,
--- a/xpcom/base/nsDebugImpl.cpp
+++ b/xpcom/base/nsDebugImpl.cpp
@@ -1,31 +1,32 @@
 /* -*- Mode: C++; tab-width: 4; 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/. */
 
 // Chromium headers must come before Mozilla headers.
 #include "base/process_util.h"
 
+#include "mozilla/Atomics.h"
+
 #include "nsDebugImpl.h"
 #include "nsDebug.h"
 #ifdef MOZ_CRASHREPORTER
 # include "nsExceptionHandler.h"
 #endif
 #include "nsStringGlue.h"
 #include "prprf.h"
 #include "prlog.h"
 #include "prinit.h"
 #include "plstr.h"
 #include "nsError.h"
 #include "prerror.h"
 #include "prerr.h"
 #include "prenv.h"
-#include "pratom.h"
 
 #ifdef ANDROID
 #include <android/log.h>
 #endif
 
 #if defined(XP_UNIX) || defined(_WIN32) || defined(XP_OS2)
 /* for abort() and getenv() */
 #include <stdlib.h>
@@ -78,17 +79,17 @@ Break(const char *aMsg);
 #include <stdlib.h>
 #endif
 
 using namespace mozilla;
 
 static bool sIsMultiprocess = false;
 static const char *sMultiprocessDescription = NULL;
 
-static int32_t gAssertionCount = 0;
+static Atomic<int32_t> gAssertionCount;
 
 NS_IMPL_QUERY_INTERFACE2(nsDebugImpl, nsIDebug, nsIDebug2)
 
 NS_IMETHODIMP_(nsrefcnt)
 nsDebugImpl::AddRef()
 {
   return 2;
 }
@@ -385,17 +386,17 @@ NS_DebugBreak(uint32_t aSeverity, const 
      nsTraceRefcntImpl::WalkTheStack(stderr);
 #endif
      Abort(buf.buffer);
      return;
    }
    }
 
    // Now we deal with assertions
-   PR_ATOMIC_INCREMENT(&gAssertionCount);
+   gAssertionCount++;
 
    switch (GetAssertBehavior()) {
    case NS_ASSERT_WARN:
      return;
 
    case NS_ASSERT_SUSPEND:
 #ifdef XP_UNIX
       fprintf(stderr, "Suspending process; attach with the debugger.\n");
--- a/xpcom/base/nsExceptionService.cpp
+++ b/xpcom/base/nsExceptionService.cpp
@@ -31,49 +31,49 @@ public:
   NS_DECL_NSIEXCEPTIONMANAGER
 
   nsExceptionManager(nsExceptionService *svc);
   /* additional members */
   nsCOMPtr<nsIException> mCurrentException;
   nsExceptionManager *mNextThread; // not ref-counted.
   nsExceptionService *mService; // not ref-counted
 #ifdef DEBUG
-  static int32_t totalInstances;
+  static Atomic<int32_t> totalInstances;
 #endif
 
 private:
   ~nsExceptionManager();
 };
 
 
 #ifdef DEBUG
-int32_t nsExceptionManager::totalInstances = 0;
+Atomic<int32_t> nsExceptionManager::totalInstances;
 #endif
 
 // Note this object is single threaded - the service itself ensures
 // one per thread.
 // An exception if the destructor, which may be called on
 // the thread shutting down xpcom
 NS_IMPL_ISUPPORTS1(nsExceptionManager, nsIExceptionManager)
 
 nsExceptionManager::nsExceptionManager(nsExceptionService *svc) :
   mNextThread(nullptr),
   mService(svc)
 {
   /* member initializers and constructor code */
 #ifdef DEBUG
-  PR_ATOMIC_INCREMENT(&totalInstances);
+  ++totalInstances;
 #endif
 }
 
 nsExceptionManager::~nsExceptionManager()
 {
   /* destructor code */
 #ifdef DEBUG
-  PR_ATOMIC_DECREMENT(&totalInstances);
+  --totalInstances;
 #endif // DEBUG
 }
 
 /* void setCurrentException (in nsIException error); */
 NS_IMETHODIMP nsExceptionManager::SetCurrentException(nsIException *error)
 {
     CHECK_MANAGER_USE_OK();
     mCurrentException = error;
@@ -99,28 +99,28 @@ NS_IMETHODIMP nsExceptionManager::GetExc
 
 /* The Exception Service */
 
 unsigned nsExceptionService::tlsIndex = BAD_TLS_INDEX;
 Mutex *nsExceptionService::sLock = nullptr;
 nsExceptionManager *nsExceptionService::firstThread = nullptr;
 
 #ifdef DEBUG
-int32_t nsExceptionService::totalInstances = 0;
+Atomic<int32_t> nsExceptionService::totalInstances;
 #endif
 
 NS_IMPL_ISUPPORTS3(nsExceptionService,
                    nsIExceptionService,
                    nsIExceptionManager,
                    nsIObserver)
 
 nsExceptionService::nsExceptionService()
 {
 #ifdef DEBUG
-  if (PR_ATOMIC_INCREMENT(&totalInstances)!=1) {
+  if (++totalInstances != 1) {
     NS_ERROR("The nsExceptionService is a singleton!");
   }
 #endif
   /* member initializers and constructor code */
   if (tlsIndex == BAD_TLS_INDEX) {
     DebugOnly<PRStatus> status;
     status = PR_NewThreadPrivateIndex( &tlsIndex, ThreadDestruct );
     NS_ASSERTION(status==0, "ScriptErrorService could not allocate TLS storage.");
@@ -135,17 +135,17 @@ nsExceptionService::nsExceptionService()
     observerService->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
 }
 
 nsExceptionService::~nsExceptionService()
 {
   Shutdown();
   /* destructor code */
 #ifdef DEBUG
-  PR_ATOMIC_DECREMENT(&totalInstances);
+  --totalInstances;
 #endif
 }
 
 /*static*/
 void nsExceptionService::ThreadDestruct( void *data )
 {
   if (!sLock) {
     NS_WARNING("nsExceptionService ignoring thread destruction after shutdown");
--- a/xpcom/base/nsExceptionService.h
+++ b/xpcom/base/nsExceptionService.h
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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 nsExceptionService_h__
 #define nsExceptionService_h__
 
+#include "mozilla/Atomics.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Mutex.h"
 
 #include "nsIException.h"
 #include "nsIExceptionService.h"
 #include "nsIObserverService.h"
 #include "nsHashtable.h"
 #include "nsIObserver.h"
@@ -44,17 +45,17 @@ public:
   static nsExceptionManager *firstThread;
 
   /* Protects the thread list. */
   static mozilla::Mutex* sLock;
 
   static unsigned tlsIndex;
   static void ThreadDestruct( void *data );
 #ifdef DEBUG
-  static int32_t totalInstances;
+  static mozilla::Atomic<int32_t> totalInstances;
 #endif
 
 private:
   ~nsExceptionService();
 };
 
 
 #endif // nsExceptionService_h__
--- a/xpcom/base/nsMemoryImpl.cpp
+++ b/xpcom/base/nsMemoryImpl.cpp
@@ -109,17 +109,17 @@ nsMemoryImpl::FlushMemory(const PRUnicha
         // got to be on the UI main thread for us to be able to do
         // that...are we?
         if (!NS_IsMainThread()) {
             NS_ERROR("can't synchronously flush memory: not on UI thread");
             return NS_ERROR_FAILURE;
         }
     }
 
-    int32_t lastVal = PR_ATOMIC_SET(&sIsFlushing, 1);
+    int32_t lastVal = sIsFlushing.exchange(1);
     if (lastVal)
         return NS_OK;
 
     PRIntervalTime now = PR_IntervalNow();
 
     // Run the flushers immediately if we can; otherwise, proxy to the
     // UI thread an run 'em asynchronously.
     if (aImmediate) {
@@ -178,18 +178,18 @@ NS_IMPL_QUERY_INTERFACE1(nsMemoryImpl::F
 
 NS_IMETHODIMP
 nsMemoryImpl::FlushEvent::Run()
 {
     sGlobalMemory.RunFlushers(mReason);
     return NS_OK;
 }
 
-int32_t
-nsMemoryImpl::sIsFlushing = 0;
+mozilla::Atomic<int32_t>
+nsMemoryImpl::sIsFlushing;
 
 PRIntervalTime
 nsMemoryImpl::sLastFlushTime = 0;
 
 nsMemoryImpl::FlushEvent
 nsMemoryImpl::sFlushEvent;
 
 XPCOM_API(void*)
--- a/xpcom/base/nsMemoryImpl.h
+++ b/xpcom/base/nsMemoryImpl.h
@@ -1,16 +1,18 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* 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 nsMemoryImpl_h__
 #define nsMemoryImpl_h__
 
+#include "mozilla/Atomics.h"
+
 #include "nsIMemory.h"
 #include "nsIRunnable.h"
 #include "prtime.h"
 
 // nsMemoryImpl is a static object. We can do this because it doesn't have
 // a constructor/destructor or any instance members. Please don't add
 // instance member variables, only static member variables.
 
@@ -32,14 +34,14 @@ public:
 
 protected:
     struct FlushEvent : public nsIRunnable {
         NS_DECL_ISUPPORTS_INHERITED
         NS_DECL_NSIRUNNABLE
         const PRUnichar* mReason;
     };
 
-    static int32_t    sIsFlushing;
+    static mozilla::Atomic<int32_t> sIsFlushing;
     static FlushEvent sFlushEvent;
     static PRIntervalTime sLastFlushTime;
 };
 
 #endif // nsMemoryImpl_h__
--- a/xpcom/base/nsMemoryInfoDumper.cpp
+++ b/xpcom/base/nsMemoryInfoDumper.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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 "mozilla/nsMemoryInfoDumper.h"
 
+#include "mozilla/Atomics.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/FileUtils.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/unused.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/ContentChild.h"
 #include "nsIConsoleService.h"
@@ -137,17 +138,17 @@ namespace {
 // It turns out that at least on some systems, SIGRTMIN is not a compile-time
 // constant, so these have to be set at runtime.
 static int sDumpAboutMemorySignum;         // SIGRTMIN
 static int sDumpAboutMemoryAfterMMUSignum; // SIGRTMIN + 1
 static int sGCAndCCDumpSignum;             // SIGRTMIN + 2
 
 // This is the write-end of a pipe that we use to notice when a
 // dump-about-memory signal occurs.
-static int sDumpAboutMemoryPipeWriteFd = -1;
+static Atomic<int> sDumpAboutMemoryPipeWriteFd(-1);
 
 void
 DumpAboutMemorySignalHandler(int aSignum)
 {
   // This is a signal handler, so everything in here needs to be
   // async-signal-safe.  Be careful!
 
   if (sDumpAboutMemoryPipeWriteFd != -1) {
@@ -324,18 +325,17 @@ public:
 
     // Close sDumpAboutMemoryPipeWriteFd /after/ setting the fd to -1.
     // Otherwise we have the (admittedly far-fetched) race where we
     //
     //  1) close sDumpAboutMemoryPipeWriteFd
     //  2) open a new fd with the same number as sDumpAboutMemoryPipeWriteFd
     //     had.
     //  3) receive a signal, then write to the fd.
-    int pipeWriteFd = sDumpAboutMemoryPipeWriteFd;
-    PR_ATOMIC_SET(&sDumpAboutMemoryPipeWriteFd, -1);
+    int pipeWriteFd = sDumpAboutMemoryPipeWriteFd.exchange(-1);
     close(pipeWriteFd);
 
     FdWatcher::StopWatching();
   }
 
   virtual void OnFileCanReadWithoutBlocking(int aFd)
   {
     MOZ_ASSERT(XRE_GetIOMessageLoop() == MessageLoopForIO::current());
--- a/xpcom/string/public/nsStringBuffer.h
+++ b/xpcom/string/public/nsStringBuffer.h
@@ -2,16 +2,17 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 nsStringBuffer_h__
 #define nsStringBuffer_h__
 
+#include "mozilla/Atomics.h"
 #include "mozilla/MemoryReporting.h"
 
 template<class T> struct already_AddRefed;
 
 /**
  * This structure precedes the string buffers "we" allocate.  It may be the
  * case that nsTAString::mData does not point to one of these special
  * buffers.  The mFlags member variable distinguishes the buffer type.
@@ -20,17 +21,17 @@ template<class T> struct already_AddRefe
  * tracking.  NOTE: A string buffer can be modified only if its reference
  * count is 1.
  */
 class nsStringBuffer
   {
     private:
       friend class CheckStaticAtomSizes;
 
-      int32_t  mRefCount;
+      mozilla::Atomic<int32_t> mRefCount;
       uint32_t mStorageSize;
 
     public:
       
       /**
        * Allocates a new string buffer, with given size in bytes and a
        * reference count of one.  When the string buffer is no longer needed,
        * it should be released via Release.
--- a/xpcom/string/src/nsSubstring.cpp
+++ b/xpcom/string/src/nsSubstring.cpp
@@ -3,33 +3,35 @@
 /* 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/. */
 
 #ifdef DEBUG
 #define ENABLE_STRING_STATS
 #endif
 
+#include "mozilla/Atomics.h"
 #include "mozilla/MemoryReporting.h"
 
 #ifdef ENABLE_STRING_STATS
 #include <stdio.h>
 #endif
 
 #include <stdlib.h>
 #include "nsSubstring.h"
 #include "nsString.h"
 #include "nsStringBuffer.h"
 #include "nsDependentString.h"
 #include "nsMemory.h"
-#include "pratom.h"
 #include "prprf.h"
 #include "nsStaticAtom.h"
 #include "nsCOMPtr.h"
 
+using mozilla::Atomic;
+
 // ---------------------------------------------------------------------------
 
 static PRUnichar gNullChar = 0;
 
 char*      nsCharTraits<char>     ::sEmptyBuffer = (char*) &gNullChar;
 PRUnichar* nsCharTraits<PRUnichar>::sEmptyBuffer =         &gNullChar;
 
 // ---------------------------------------------------------------------------
@@ -45,41 +47,41 @@ class nsStringStats
         {
           // this is a hack to suppress duplicate string stats printing
           // in seamonkey as a result of the string code being linked
           // into seamonkey and libxpcom! :-(
           if (!mAllocCount && !mAdoptCount)
             return;
 
           printf("nsStringStats\n");
-          printf(" => mAllocCount:     % 10d\n", mAllocCount);
-          printf(" => mReallocCount:   % 10d\n", mReallocCount);
-          printf(" => mFreeCount:      % 10d", mFreeCount);
+          printf(" => mAllocCount:     % 10d\n", int(mAllocCount));
+          printf(" => mReallocCount:   % 10d\n", int(mReallocCount));
+          printf(" => mFreeCount:      % 10d", int(mFreeCount));
           if (mAllocCount > mFreeCount)
             printf("  --  LEAKED %d !!!\n", mAllocCount - mFreeCount);
           else
             printf("\n");
-          printf(" => mShareCount:     % 10d\n", mShareCount);
-          printf(" => mAdoptCount:     % 10d\n", mAdoptCount);
-          printf(" => mAdoptFreeCount: % 10d", mAdoptFreeCount);
+          printf(" => mShareCount:     % 10d\n", int(mShareCount));
+          printf(" => mAdoptCount:     % 10d\n", int(mAdoptCount));
+          printf(" => mAdoptFreeCount: % 10d", int(mAdoptFreeCount));
           if (mAdoptCount > mAdoptFreeCount)
             printf("  --  LEAKED %d !!!\n", mAdoptCount - mAdoptFreeCount);
           else
             printf("\n");
         }
 
-      int32_t mAllocCount;
-      int32_t mReallocCount;
-      int32_t mFreeCount;
-      int32_t mShareCount;
-      int32_t mAdoptCount;
-      int32_t mAdoptFreeCount;
+      Atomic<int32_t> mAllocCount;
+      Atomic<int32_t> mReallocCount;
+      Atomic<int32_t> mFreeCount;
+      Atomic<int32_t> mShareCount;
+      Atomic<int32_t> mAdoptCount;
+      Atomic<int32_t> mAdoptFreeCount;
   };
 static nsStringStats gStringStats;
-#define STRING_STAT_INCREMENT(_s) PR_ATOMIC_INCREMENT(&gStringStats.m ## _s ## Count)
+#define STRING_STAT_INCREMENT(_s) (gStringStats.m ## _s ## Count)++
 #else
 #define STRING_STAT_INCREMENT(_s)
 #endif
 
 // ---------------------------------------------------------------------------
 
 inline void
 ReleaseData( void* data, uint32_t flags )
@@ -143,25 +145,25 @@ class nsACStringAccessor : public nsACSt
         }
   };
 
 // ---------------------------------------------------------------------------
 
 void
 nsStringBuffer::AddRef()
   {
-    PR_ATOMIC_INCREMENT(&mRefCount);
+    ++mRefCount;
     STRING_STAT_INCREMENT(Share);
     NS_LOG_ADDREF(this, mRefCount, "nsStringBuffer", sizeof(*this));
   }
 
 void
 nsStringBuffer::Release()
   {
-    int32_t count = PR_ATOMIC_DECREMENT(&mRefCount);
+    int32_t count = --mRefCount;
     NS_LOG_RELEASE(this, count, "nsStringBuffer");
     if (count == 0)
       {
         STRING_STAT_INCREMENT(Free);
         free(this); // we were allocated with |malloc|
       }
   }
 
--- a/xpcom/threads/TimerThread.cpp
+++ b/xpcom/threads/TimerThread.cpp
@@ -79,17 +79,17 @@ nsresult TimerThread::Init()
 
   if (mInitialized) {
     if (!mThread)
       return NS_ERROR_FAILURE;
 
     return NS_OK;
   }
 
-  if (PR_ATOMIC_SET(&mInitInProgress, 1) == 0) {
+  if (mInitInProgress.exchange(1) == 0) {
     // We hold on to mThread to keep the thread alive.
     nsresult rv = NS_NewThread(getter_AddRefs(mThread), this);
     if (NS_FAILED(rv)) {
       mThread = nullptr;
     }
     else {
       nsRefPtr<TimerObserverRunnable> r = new TimerObserverRunnable(this);
       if (NS_IsMainThread()) {
--- a/xpcom/threads/TimerThread.h
+++ b/xpcom/threads/TimerThread.h
@@ -10,16 +10,17 @@
 #include "nsIRunnable.h"
 #include "nsIThread.h"
 
 #include "nsTimerImpl.h"
 #include "nsThreadUtils.h"
 
 #include "nsTArray.h"
 
+#include "mozilla/Atomics.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Monitor.h"
 #include "mozilla/TimeStamp.h"
 
 class TimerThread MOZ_FINAL : public nsIRunnable,
                               public nsIObserver
 {
 public:
@@ -47,17 +48,17 @@ public:
   bool IsOnTimerThread() const
   {
     return mThread == NS_GetCurrentThread();
   }
 
 private:
   ~TimerThread();
 
-  int32_t mInitInProgress;
+  mozilla::Atomic<int32_t> mInitInProgress;
   bool    mInitialized;
 
   // These two internal helper methods must be called while mLock is held.
   // AddTimerInternal returns the position where the timer was added in the
   // list, or -1 if it failed.
   int32_t AddTimerInternal(nsTimerImpl *aTimer);
   bool    RemoveTimerInternal(nsTimerImpl *aTimer);
   void    ReleaseTimerInternal(nsTimerImpl *aTimer);
--- a/xpcom/threads/nsTimerImpl.cpp
+++ b/xpcom/threads/nsTimerImpl.cpp
@@ -7,21 +7,23 @@
 #include "nsTimerImpl.h"
 #include "TimerThread.h"
 #include "nsAutoPtr.h"
 #include "nsThreadManager.h"
 #include "nsThreadUtils.h"
 #include "plarena.h"
 #include "pratom.h"
 #include "GeckoProfiler.h"
+#include "mozilla/Atomics.h"
 
+using mozilla::Atomic;
 using mozilla::TimeDuration;
 using mozilla::TimeStamp;
 
-static int32_t          gGenerator = 0;
+static Atomic<int32_t>  gGenerator;
 static TimerThread*     gThread = nullptr;
 
 #ifdef DEBUG_TIMERS
 
 PRLogModuleInfo*
 GetTimerLog()
 {
   static PRLogModuleInfo *sLog;
@@ -109,17 +111,17 @@ public:
   nsTimerEvent(nsTimerImpl *timer, int32_t generation)
     : mTimer(dont_AddRef(timer)), mGeneration(generation) {
     // timer is already addref'd for us
     MOZ_COUNT_CTOR(nsTimerEvent);
 
     MOZ_ASSERT(gThread->IsOnTimerThread(),
                "nsTimer must always be allocated on the timer thread");
 
-    PR_ATOMIC_INCREMENT(&sAllocatorUsers);
+    sAllocatorUsers++;
   }
 
 #ifdef DEBUG_TIMERS
   TimeStamp mInitTime;
 #endif
 
   static void Init();
   static void Shutdown();
@@ -135,29 +137,29 @@ public:
 
 private:
   nsTimerEvent(); // Not implemented
   ~nsTimerEvent() {
     MOZ_COUNT_DTOR(nsTimerEvent);
 
     MOZ_ASSERT(!sCanDeleteAllocator || sAllocatorUsers > 0,
                "This will result in us attempting to deallocate the nsTimerEvent allocator twice");
-    PR_ATOMIC_DECREMENT(&sAllocatorUsers);
+    sAllocatorUsers--;
   }
 
   nsRefPtr<nsTimerImpl> mTimer;
   int32_t      mGeneration;
 
   static TimerEventAllocator* sAllocator;
-  static int32_t sAllocatorUsers;
+  static Atomic<int32_t> sAllocatorUsers;
   static bool sCanDeleteAllocator;
 };
 
 TimerEventAllocator* nsTimerEvent::sAllocator = nullptr;
-int32_t nsTimerEvent::sAllocatorUsers = 0;
+Atomic<int32_t> nsTimerEvent::sAllocatorUsers;
 bool nsTimerEvent::sCanDeleteAllocator = false;
 
 namespace {
 
 void* TimerEventAllocator::Alloc(size_t aSize)
 {
   MOZ_ASSERT(aSize == sizeof(nsTimerEvent));
 
@@ -337,17 +339,17 @@ nsresult nsTimerImpl::InitCommon(uint32_
    * it might be cleared on another thread in the next cycle (or even already
    * be cleared by another CPU whose store hasn't reached our CPU's cache),
    * because RemoveTimer is idempotent.
    */
   if (mArmed)
     gThread->RemoveTimer(this);
   mCanceled = false;
   mTimeout = TimeStamp();
-  mGeneration = PR_ATOMIC_INCREMENT(&gGenerator);
+  mGeneration = gGenerator++;
 
   mType = (uint8_t)aType;
   SetDelayInternal(aDelay);
 
   return gThread->AddTimer(this);
 }
 
 NS_IMETHODIMP nsTimerImpl::InitWithFuncCallback(nsTimerCallbackFunc aFunc,