Bug 832609 - Make memory reporter for blobs threadsafe. r=khuey
authorJustin Lebar <justin.lebar@gmail.com>
Fri, 24 May 2013 13:10:48 -0400
changeset 132940 8d0ac9d38a1b31768f5bb340228fb4a6271a7d53
parent 132939 bfe1d6ce6f3ecb3db8f1f82b9fc0fb13d0ce77fd
child 132941 bcc149a59ceb93edc962085ea0cc08f3f83bf224
push id24727
push userphilringnalda@gmail.com
push dateSun, 26 May 2013 04:02:45 +0000
treeherdermozilla-central@0fed3377c839 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhuey
bugs832609
milestone24.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 832609 - Make memory reporter for blobs threadsafe. r=khuey
content/base/public/nsDOMFile.h
content/base/src/nsDOMFile.cpp
--- a/content/base/public/nsDOMFile.h
+++ b/content/base/public/nsDOMFile.h
@@ -17,16 +17,17 @@
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsIXMLHttpRequest.h"
 #include "nsAutoPtr.h"
 
 #include "mozilla/GuardObjects.h"
 #include "mozilla/LinkedList.h"
 #include "mozilla/StandardInteger.h"
+#include "mozilla/StaticMutex.h"
 #include "mozilla/StaticPtr.h"
 #include "mozilla/dom/DOMError.h"
 #include "mozilla/dom/indexedDB/FileInfo.h"
 #include "mozilla/dom/indexedDB/FileManager.h"
 #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
 #include "nsWrapperCache.h"
 #include "nsCycleCollectionParticipant.h"
 
@@ -338,16 +339,20 @@ protected:
     return mWholeFile;
   }
 
   nsCOMPtr<nsIFile> mFile;
   bool mWholeFile;
   bool mStoredFile;
 };
 
+/**
+ * This class may be used off the main thread, and in particular, its
+ * constructor and destructor may not run on the same thread.  Be careful!
+ */
 class nsDOMMemoryFile : public nsDOMFile
 {
 public:
   // Create as file
   nsDOMMemoryFile(void *aMemoryBuffer,
                   uint64_t aLength,
                   const nsAString& aName,
                   const nsAString& aContentType)
@@ -389,37 +394,46 @@ protected:
 
   class DataOwner : public mozilla::LinkedListElement<DataOwner> {
   public:
     NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DataOwner)
     DataOwner(void* aMemoryBuffer, uint64_t aLength)
       : mData(aMemoryBuffer)
       , mLength(aLength)
     {
+      mozilla::StaticMutexAutoLock lock(sDataOwnerMutex);
+
       if (!sDataOwners) {
         sDataOwners = new mozilla::LinkedList<DataOwner>();
         EnsureMemoryReporterRegistered();
       }
       sDataOwners->insertBack(this);
     }
 
     ~DataOwner() {
+      mozilla::StaticMutexAutoLock lock(sDataOwnerMutex);
+
       remove();
       if (sDataOwners->isEmpty()) {
         // Free the linked list if it's empty.
         sDataOwners = nullptr;
       }
 
       moz_free(mData);
     }
 
     static void EnsureMemoryReporterRegistered();
 
+    // sDataOwners and sMemoryReporterRegistered may only be accessed while
+    // holding sDataOwnerMutex!  You also must hold the mutex while touching
+    // elements of the linked list that DataOwner inherits from.
+    static mozilla::StaticMutex sDataOwnerMutex;
+    static mozilla::StaticAutoPtr<mozilla::LinkedList<DataOwner> > sDataOwners;
     static bool sMemoryReporterRegistered;
-    static mozilla::StaticAutoPtr<mozilla::LinkedList<DataOwner> > sDataOwners;
+
     void* mData;
     uint64_t mLength;
   };
 
   // Used when backed by a memory store
   nsRefPtr<DataOwner> mDataOwner;
 };
 
--- a/content/base/src/nsDOMFile.cpp
+++ b/content/base/src/nsDOMFile.cpp
@@ -606,16 +606,19 @@ NS_IMETHODIMP
 nsDOMMemoryFile::GetInternalStream(nsIInputStream **aStream)
 {
   if (mLength > INT32_MAX)
     return NS_ERROR_FAILURE;
 
   return DataOwnerAdapter::Create(mDataOwner, mStart, mLength, aStream);
 }
 
+/* static */ StaticMutex
+nsDOMMemoryFile::DataOwner::sDataOwnerMutex;
+
 /* static */ StaticAutoPtr<LinkedList<nsDOMMemoryFile::DataOwner> >
 nsDOMMemoryFile::DataOwner::sDataOwners;
 
 /* static */ bool
 nsDOMMemoryFile::DataOwner::sMemoryReporterRegistered;
 
 NS_MEMORY_REPORTER_MALLOC_SIZEOF_FUN(DOMMemoryFileDataOwnerMallocSizeOf)
 
@@ -630,16 +633,18 @@ class nsDOMMemoryFileDataOwnerMemoryRepo
     return NS_OK;
   }
 
   NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *aCallback,
                             nsISupports *aClosure)
   {
     typedef nsDOMMemoryFile::DataOwner DataOwner;
 
+    StaticMutexAutoLock lock(DataOwner::sDataOwnerMutex);
+
     if (!DataOwner::sDataOwners) {
       return NS_OK;
     }
 
     const size_t LARGE_OBJECT_MIN_SIZE = 8 * 1024;
     size_t smallObjectsTotal = 0;
 
     for (DataOwner *owner = DataOwner::sDataOwners->getFirst();