Bug 1418918. P2 - add thread/monitor assertions. draft
authorJW Wang <jwwang@mozilla.com>
Mon, 20 Nov 2017 16:30:05 +0800
changeset 703559 9b78c00c938f4411a7e3895be843a491e4bfce4a
parent 703558 bfe3ac4738ae5b1d283ec124e72be6cdd891fc10
child 703560 5bc5e667c12559ab417d0d2884ad56feb2d964fa
push id90857
push userjwwang@mozilla.com
push dateMon, 27 Nov 2017 02:57:51 +0000
bugs1418918
milestone59.0a1
Bug 1418918. P2 - add thread/monitor assertions. MozReview-Commit-ID: 3J8pRFnpm77
dom/media/MediaCache.cpp
--- a/dom/media/MediaCache.cpp
+++ b/dom/media/MediaCache.cpp
@@ -828,16 +828,17 @@ OffsetInBlock(int64_t aOffset)
   return int32_t(aOffset % MediaCache::BLOCK_SIZE);
 }
 
 int32_t
 MediaCache::FindBlockForIncomingData(TimeStamp aNow,
                                      MediaCacheStream* aStream,
                                      int32_t aStreamBlockIndex)
 {
+  MOZ_ASSERT(sThread->IsOnCurrentThread());
   mReentrantMonitor.AssertCurrentThreadIn();
 
   int32_t blockIndex =
     FindReusableBlock(aNow, aStream, aStreamBlockIndex, INT32_MAX);
 
   if (blockIndex < 0 || !IsBlockFree(blockIndex)) {
     // The block returned is already allocated.
     // Don't reuse it if a) there's room to expand the cache or
@@ -858,16 +859,18 @@ MediaCache::FindBlockForIncomingData(Tim
   }
 
   return blockIndex;
 }
 
 bool
 MediaCache::BlockIsReusable(int32_t aBlockIndex)
 {
+  mReentrantMonitor.AssertCurrentThreadIn();
+
   Block* block = &mIndex[aBlockIndex];
   for (uint32_t i = 0; i < block->mOwners.Length(); ++i) {
     MediaCacheStream* stream = block->mOwners[i].mStream;
     if (stream->mPinCount > 0 ||
         uint32_t(OffsetToBlockIndex(stream->mStreamOffset)) ==
           block->mOwners[i].mStreamBlock) {
       return false;
     }
@@ -899,16 +902,17 @@ MediaCache::AppendMostReusableBlock(Bloc
 }
 
 int32_t
 MediaCache::FindReusableBlock(TimeStamp aNow,
                                 MediaCacheStream* aForStream,
                                 int32_t aForStreamBlock,
                                 int32_t aMaxSearchBlockIndex)
 {
+  MOZ_ASSERT(sThread->IsOnCurrentThread());
   mReentrantMonitor.AssertCurrentThreadIn();
 
   uint32_t length = std::min(uint32_t(aMaxSearchBlockIndex), uint32_t(mIndex.Length()));
 
   if (aForStream && aForStreamBlock > 0 &&
       uint32_t(aForStreamBlock) <= aForStream->mBlocks.Length()) {
     int32_t prevCacheBlock = aForStream->mBlocks[aForStreamBlock - 1];
     if (prevCacheBlock >= 0) {
@@ -963,16 +967,18 @@ MediaCache::FindReusableBlock(TimeStamp 
   }
 
   return latestUseBlock;
 }
 
 MediaCache::BlockList*
 MediaCache::GetListForBlock(BlockOwner* aBlock)
 {
+  mReentrantMonitor.AssertCurrentThreadIn();
+
   switch (aBlock->mClass) {
   case METADATA_BLOCK:
     NS_ASSERTION(aBlock->mStream, "Metadata block has no stream?");
     return &aBlock->mStream->mMetadataBlocks;
   case PLAYED_BLOCK:
     NS_ASSERTION(aBlock->mStream, "Metadata block has no stream?");
     return &aBlock->mStream->mPlayedBlocks;
   case READAHEAD_BLOCK:
@@ -982,16 +988,18 @@ MediaCache::GetListForBlock(BlockOwner* 
     NS_ERROR("Invalid block class");
     return nullptr;
   }
 }
 
 MediaCache::BlockOwner*
 MediaCache::GetBlockOwner(int32_t aBlockIndex, MediaCacheStream* aStream)
 {
+  mReentrantMonitor.AssertCurrentThreadIn();
+
   Block* block = &mIndex[aBlockIndex];
   for (uint32_t i = 0; i < block->mOwners.Length(); ++i) {
     if (block->mOwners[i].mStream == aStream)
       return &block->mOwners[i];
   }
   return nullptr;
 }
 
@@ -1037,16 +1045,18 @@ MediaCache::SwapBlocks(int32_t aBlockInd
   }
 
   Verify();
 }
 
 void
 MediaCache::RemoveBlockOwner(int32_t aBlockIndex, MediaCacheStream* aStream)
 {
+  mReentrantMonitor.AssertCurrentThreadIn();
+
   Block* block = &mIndex[aBlockIndex];
   for (uint32_t i = 0; i < block->mOwners.Length(); ++i) {
     BlockOwner* bo = &block->mOwners[i];
     if (bo->mStream == aStream) {
       GetListForBlock(bo)->RemoveBlock(aBlockIndex);
       bo->mStream->mBlocks[bo->mStreamBlock] = -1;
       block->mOwners.RemoveElementAt(i);
       if (block->mOwners.IsEmpty()) {
@@ -1057,16 +1067,18 @@ MediaCache::RemoveBlockOwner(int32_t aBl
   }
 }
 
 void
 MediaCache::AddBlockOwnerAsReadahead(int32_t aBlockIndex,
                                        MediaCacheStream* aStream,
                                        int32_t aStreamBlockIndex)
 {
+  mReentrantMonitor.AssertCurrentThreadIn();
+
   Block* block = &mIndex[aBlockIndex];
   if (block->mOwners.IsEmpty()) {
     mFreeBlocks.RemoveBlock(aBlockIndex);
   }
   BlockOwner* bo = block->mOwners.AppendElement();
   mBlockOwnersWatermark =
     std::max(mBlockOwnersWatermark, uint32_t(block->mOwners.Length()));
   bo->mStream = aStream;
@@ -1097,16 +1109,17 @@ MediaCache::FreeBlock(int32_t aBlock)
   block->mOwners.Clear();
   mFreeBlocks.AddFirstBlock(aBlock);
   Verify();
 }
 
 TimeDuration
 MediaCache::PredictNextUse(TimeStamp aNow, int32_t aBlock)
 {
+  MOZ_ASSERT(sThread->IsOnCurrentThread());
   mReentrantMonitor.AssertCurrentThreadIn();
   NS_ASSERTION(!IsBlockFree(aBlock), "aBlock is free");
 
   Block* block = &mIndex[aBlock];
   // Blocks can be belong to multiple streams. The predicted next use
   // time is the earliest time predicted by any of the streams.
   TimeDuration result;
   for (uint32_t i = 0; i < block->mOwners.Length(); ++i) {
@@ -1152,16 +1165,17 @@ MediaCache::PredictNextUse(TimeStamp aNo
     }
   }
   return result;
 }
 
 TimeDuration
 MediaCache::PredictNextUseForIncomingData(MediaCacheStream* aStream)
 {
+  MOZ_ASSERT(sThread->IsOnCurrentThread());
   mReentrantMonitor.AssertCurrentThreadIn();
 
   int64_t bytesAhead = aStream->mChannelOffset - aStream->mStreamOffset;
   if (bytesAhead <= -BLOCK_SIZE) {
     // Hmm, no idea when data behind us will be used. Guess 24 hours.
     return TimeDuration::FromSeconds(24*60*60);
   }
   if (bytesAhead <= 0)
@@ -1622,18 +1636,17 @@ MediaCache::Verify()
       lastStreamBlock = nextStreamBlock;
       block = stream->mReadaheadBlocks.GetNextBlock(block);
     }
   }
 }
 #endif
 
 void
-MediaCache::InsertReadaheadBlock(BlockOwner* aBlockOwner,
-                                   int32_t aBlockIndex)
+MediaCache::InsertReadaheadBlock(BlockOwner* aBlockOwner, int32_t aBlockIndex)
 {
   mReentrantMonitor.AssertCurrentThreadIn();
 
   // Find the last block whose stream block is before aBlockIndex's
   // stream block, and insert after it
   MediaCacheStream* stream = aBlockOwner->mStream;
   int32_t readaheadIndex = stream->mReadaheadBlocks.GetLastBlock();
   while (readaheadIndex >= 0) {
@@ -1654,16 +1667,17 @@ MediaCache::InsertReadaheadBlock(BlockOw
 
 void
 MediaCache::AllocateAndWriteBlock(MediaCacheStream* aStream,
                                   int32_t aStreamBlockIndex,
                                   MediaCacheStream::ReadMode aMode,
                                   Span<const uint8_t> aData1,
                                   Span<const uint8_t> aData2)
 {
+  MOZ_ASSERT(sThread->IsOnCurrentThread());
   mReentrantMonitor.AssertCurrentThreadIn();
 
   // Remove all cached copies of this block
   ResourceStreamIterator iter(this, aStream->mResourceID);
   while (MediaCacheStream* stream = iter.Next()) {
     while (aStreamBlockIndex >= int32_t(stream->mBlocks.Length())) {
       stream->mBlocks.AppendElement(-1);
     }
@@ -2100,16 +2114,18 @@ MediaCacheStream::NotifyDataReceived(uin
   // avoid waking up reader threads unnecessarily
   mon.NotifyAll();
 }
 
 void
 MediaCacheStream::FlushPartialBlockInternal(bool aNotifyAll,
                                             ReentrantMonitorAutoEnter& aReentrantMonitor)
 {
+  MOZ_ASSERT(OwnerThread()->IsOnCurrentThread());
+
   int32_t blockIndex = OffsetToBlockIndexUnchecked(mChannelOffset);
   int32_t blockOffset = OffsetInBlock(mChannelOffset);
   if (blockOffset > 0) {
     LOG("Stream %p writing partial block: [%d] bytes; "
         "mStreamOffset [%" PRId64 "] mChannelOffset[%"
         PRId64 "] mStreamLength [%" PRId64 "] notifying: [%s]",
         this, blockOffset, mStreamOffset, mChannelOffset, mStreamLength,
         aNotifyAll ? "yes" : "no");
@@ -2133,16 +2149,17 @@ MediaCacheStream::FlushPartialBlockInter
   }
 }
 
 void
 MediaCacheStream::NotifyDataEndedInternal(uint32_t aLoadID,
                                           nsresult aStatus,
                                           bool aReopenOnError)
 {
+  MOZ_ASSERT(OwnerThread()->IsOnCurrentThread());
   ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
 
   if (mClosed || aLoadID != mLoadID) {
     // Nothing to do if the stream is closed or a new load has begun.
     return;
   }
 
   // Note that aStatus might have succeeded --- this might be a normal close
@@ -2268,17 +2285,19 @@ MediaCacheStream::~MediaCacheStream()
       lengthKb);
   Telemetry::Accumulate(Telemetry::HistogramID::MEDIACACHESTREAM_LENGTH_KB,
                         lengthKb);
 }
 
 bool
 MediaCacheStream::AreAllStreamsForResourceSuspended()
 {
+  MOZ_ASSERT(!NS_IsMainThread());
   ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
+
   MediaCache::ResourceStreamIterator iter(mMediaCache, mResourceID);
   // Look for a stream that's able to read the data we need
   int64_t dataOffset = -1;
   while (MediaCacheStream* stream = iter.Next()) {
     if (stream->mCacheSuspended || stream->mChannelEnded || stream->mClosed) {
       continue;
     }
     if (dataOffset < 0) {
@@ -2319,65 +2338,72 @@ MediaCacheStream::Close()
   // it from CloseInternal since that gets called by Update() itself
   // sometimes, and we try to not to queue updates from Update().
   mMediaCache->QueueUpdate();
 }
 
 void
 MediaCacheStream::Pin()
 {
+  // TODO: Assert non-main thread.
   ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   ++mPinCount;
   // Queue an Update since we may no longer want to read more into the
   // cache, if this stream's block have become non-evictable
   mMediaCache->QueueUpdate();
 }
 
 void
 MediaCacheStream::Unpin()
 {
+  // TODO: Assert non-main thread.
   ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   NS_ASSERTION(mPinCount > 0, "Unbalanced Unpin");
   --mPinCount;
   // Queue an Update since we may be able to read more into the
   // cache, if this stream's block have become evictable
   mMediaCache->QueueUpdate();
 }
 
 int64_t
 MediaCacheStream::GetLength()
 {
+  // TODO: Assert non-main thread.
   ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   return mStreamLength;
 }
 
 int64_t
 MediaCacheStream::GetOffset() const
 {
+  // TODO: Assert non-main thread.
   ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   return mChannelOffset;
 }
 
 int64_t
 MediaCacheStream::GetNextCachedData(int64_t aOffset)
 {
+  MOZ_ASSERT(!NS_IsMainThread());
   ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   return GetNextCachedDataInternal(aOffset);
 }
 
 int64_t
 MediaCacheStream::GetCachedDataEnd(int64_t aOffset)
 {
+  // TODO: Assert non-main thread.
   ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   return GetCachedDataEndInternal(aOffset);
 }
 
 bool
 MediaCacheStream::IsDataCachedToEndOfStream(int64_t aOffset)
 {
+  MOZ_ASSERT(!NS_IsMainThread());
   ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   if (mStreamLength < 0)
     return false;
   return GetCachedDataEndInternal(aOffset) >= mStreamLength;
 }
 
 int64_t
 MediaCacheStream::GetCachedDataEndInternal(int64_t aOffset)
@@ -2452,16 +2478,17 @@ MediaCacheStream::GetNextCachedDataInter
 
   NS_NOTREACHED("Should return in loop");
   return -1;
 }
 
 void
 MediaCacheStream::SetReadMode(ReadMode aMode)
 {
+  // TODO: Assert non-main thread.
   ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   if (aMode == mCurrentMode)
     return;
   mCurrentMode = aMode;
   mMediaCache->QueueUpdate();
 }
 
 void
@@ -2591,18 +2618,17 @@ MediaCacheStream::ReadBlockFromCache(int
   }
 
   return bytesRead;
 }
 
 nsresult
 MediaCacheStream::Read(char* aBuffer, uint32_t aCount, uint32_t* aBytes)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
-
+  MOZ_ASSERT(!NS_IsMainThread());
   ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
 
   // Cache the offset in case it is changed again when we are waiting for the
   // monitor to be notified to avoid reading at the wrong position.
   auto streamOffset = mStreamOffset;
 
   // The buffer we are about to fill.
   auto buffer = MakeSpan<char>(aBuffer, aCount);
@@ -2689,27 +2715,27 @@ MediaCacheStream::Read(char* aBuffer, ui
   mStreamOffset = streamOffset;
   return NS_OK;
 }
 
 nsresult
 MediaCacheStream::ReadAt(int64_t aOffset, char* aBuffer,
                          uint32_t aCount, uint32_t* aBytes)
 {
-  NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
-
+  MOZ_ASSERT(!NS_IsMainThread());
   ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   nsresult rv = Seek(aOffset);
   if (NS_FAILED(rv)) return rv;
   return Read(aBuffer, aCount, aBytes);
 }
 
 nsresult
 MediaCacheStream::ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount)
 {
+  MOZ_ASSERT(!NS_IsMainThread());
   ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
 
   // The buffer we are about to fill.
   auto buffer = MakeSpan<char>(aBuffer, aCount);
 
   // Read one block (or part of a block) at a time
   int64_t streamOffset = aOffset;
   while (!buffer.IsEmpty()) {
@@ -2837,16 +2863,17 @@ MediaCacheStream::InitAsClone(MediaCache
 nsIEventTarget*
 MediaCacheStream::OwnerThread() const
 {
   return mMediaCache->OwnerThread();
 }
 
 nsresult MediaCacheStream::GetCachedRanges(MediaByteRangeSet& aRanges)
 {
+  MOZ_ASSERT(!NS_IsMainThread());
   // Take the monitor, so that the cached data ranges can't grow while we're
   // trying to loop over them.
   ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
 
   // We must be pinned while running this, otherwise the cached data ranges may
   // shrink while we're trying to loop over them.
   NS_ASSERTION(mPinCount > 0, "Must be pinned");