From c5917ed65a314f67a6df0eba15effe66c3bbbd51 Mon Sep 17 00:00:00 2001 From: Randell Jesup Date: Thu, 17 Mar 2022 18:39:15 +0000 Subject: [PATCH] Bug 1207753: Basic thread-safety annotations to quiet errors until real annotations land r=nika Differential Revision: https://phabricator.services.mozilla.com/D141062 --- dom/base/BodyStream.cpp | 3 +++ dom/media/AudioStream.cpp | 1 + dom/media/doctor/MultiWriterQueue.h | 2 ++ dom/media/gmp/GMPPlatform.cpp | 2 ++ .../android_video_capture/device_info_android.h | 3 ++- .../systemservices/objc_video_capture/device_info.h | 3 ++- dom/workers/Queue.h | 2 ++ dom/workers/WorkerPrivate.h | 8 +++++--- gfx/2d/2D.h | 2 ++ gfx/2d/Factory.cpp | 2 ++ gfx/2d/SourceSurfaceSkia.cpp | 5 +++-- gfx/layers/apz/src/APZCTreeManager.cpp | 2 ++ ipc/glue/DataPipe.cpp | 2 ++ ipc/glue/MessageLink.cpp | 1 + js/xpconnect/loader/ScriptPreloader.cpp | 1 + netwerk/base/nsProtocolProxyService.cpp | 2 ++ netwerk/cache2/CacheFile.h | 2 ++ netwerk/cache2/CacheIOThread.cpp | 1 + netwerk/cache2/CacheIndex.cpp | 3 +++ netwerk/dns/nsIDNService.cpp | 2 +- netwerk/protocol/http/nsHttpRequestHead.h | 3 +++ netwerk/protocol/http/nsHttpResponseHead.h | 2 ++ netwerk/sctp/datachannel/DataChannel.cpp | 6 +++--- startupcache/StartupCache.cpp | 9 ++++++--- toolkit/crashreporter/nsExceptionHandler.cpp | 10 +++++----- widget/android/jni/Natives.h | 2 ++ widget/cocoa/nsChildView.mm | 6 ++++-- widget/gtk/MozContainerWayland.cpp | 12 ++++++++---- widget/gtk/WaylandVsyncSource.cpp | 1 + xpcom/components/nsComponentManager.cpp | 2 ++ xpcom/io/nsMultiplexInputStream.cpp | 2 ++ xpcom/tests/gtest/TestSynchronization.cpp | 2 +- xpcom/threads/TaskController.cpp | 3 +++ 33 files changed, 83 insertions(+), 26 deletions(-) diff --git a/dom/base/BodyStream.cpp b/dom/base/BodyStream.cpp index 0d2a809d2ad0..c0f3e359551f 100644 --- a/dom/base/BodyStream.cpp +++ b/dom/base/BodyStream.cpp @@ -505,6 +505,7 @@ void BodyStream::ErrorPropagation(JSContext* aCx, JS::HandleObject aStream, nsresult aError) { #endif AssertIsOnOwningThread(); + mMutex.AssertCurrentThreadOwns(); // Nothing to do. if (mState == eClosed) { @@ -752,6 +753,7 @@ void BodyStream::CloseAndReleaseObjects(JSContext* aCx, const MutexAutoLock& aProofOfLock, ReadableStream* aStream) { AssertIsOnOwningThread(); + mMutex.AssertCurrentThreadOwns(); MOZ_DIAGNOSTIC_ASSERT(mState != eClosed); ReleaseObjects(aProofOfLock); @@ -769,6 +771,7 @@ void BodyStream::CloseAndReleaseObjects(JSContext* aCx, const MutexAutoLock& aProofOfLock, JS::HandleObject aStream) { AssertIsOnOwningThread(); + mMutex.AssertCurrentThreadOwns(); MOZ_DIAGNOSTIC_ASSERT(mState != eClosed); ReleaseObjects(aProofOfLock); diff --git a/dom/media/AudioStream.cpp b/dom/media/AudioStream.cpp index 34588101299f..211615ec6565 100644 --- a/dom/media/AudioStream.cpp +++ b/dom/media/AudioStream.cpp @@ -231,6 +231,7 @@ struct ToCubebFormat { template int AudioStream::InvokeCubeb(Function aFunction, Args&&... aArgs) { + mMonitor.AssertCurrentThreadOwns(); MonitorAutoUnlock mon(mMonitor); return aFunction(mCubebStream.get(), std::forward(aArgs)...); } diff --git a/dom/media/doctor/MultiWriterQueue.h b/dom/media/doctor/MultiWriterQueue.h index 82cc5c18b04e..3fd22332d1e1 100644 --- a/dom/media/doctor/MultiWriterQueue.h +++ b/dom/media/doctor/MultiWriterQueue.h @@ -24,8 +24,10 @@ class MultiWriterQueueReaderLocking_Mutex { public: MultiWriterQueueReaderLocking_Mutex() : mMutex("MultiWriterQueueReaderLocking_Mutex") {} + PUSH_IGNORE_THREAD_SAFETY void Lock() { mMutex.Lock(); }; void Unlock() { mMutex.Unlock(); }; + POP_THREAD_SAFETY private: Mutex mMutex MOZ_UNANNOTATED; diff --git a/dom/media/gmp/GMPPlatform.cpp b/dom/media/gmp/GMPPlatform.cpp index fa802006a8b2..6fb5ce2e255b 100644 --- a/dom/media/gmp/GMPPlatform.cpp +++ b/dom/media/gmp/GMPPlatform.cpp @@ -257,9 +257,11 @@ GMPMutexImpl::~GMPMutexImpl() { MOZ_COUNT_DTOR(GMPMutexImpl); } void GMPMutexImpl::Destroy() { delete this; } +PUSH_IGNORE_THREAD_SAFETY void GMPMutexImpl::Acquire() { mMonitor.Enter(); } void GMPMutexImpl::Release() { mMonitor.Exit(); } +POP_THREAD_SAFETY GMPTask* NewGMPTask(std::function&& aFunction) { class Task : public GMPTask { diff --git a/dom/media/systemservices/android_video_capture/device_info_android.h b/dom/media/systemservices/android_video_capture/device_info_android.h index 33d3aae39419..ac88b2b8ba9d 100644 --- a/dom/media/systemservices/android_video_capture/device_info_android.h +++ b/dom/media/systemservices/android_video_capture/device_info_android.h @@ -46,7 +46,8 @@ class DeviceInfoAndroid : public DeviceInfoImpl { char* productUniqueIdUTF8 = 0, uint32_t productUniqueIdUTF8Length = 0, pid_t* pid = 0); - virtual int32_t CreateCapabilityMap(const char* deviceUniqueIdUTF8); + virtual int32_t CreateCapabilityMap(const char* deviceUniqueIdUTF8) + RTC_EXCLUSIVE_LOCKS_REQUIRED(_apiLock); virtual int32_t DisplayCaptureSettingsDialogBox( const char* /*deviceUniqueIdUTF8*/, const char* /*dialogTitleUTF8*/, diff --git a/dom/media/systemservices/objc_video_capture/device_info.h b/dom/media/systemservices/objc_video_capture/device_info.h index 5e84948757b8..aea3b1c2dedb 100644 --- a/dom/media/systemservices/objc_video_capture/device_info.h +++ b/dom/media/systemservices/objc_video_capture/device_info.h @@ -44,7 +44,8 @@ class DeviceInfoIos : public DeviceInfoImpl { int32_t GetOrientation(const char* deviceUniqueIdUTF8, VideoRotation& orientation) override; - int32_t CreateCapabilityMap(const char* device_unique_id_utf8) override; + int32_t CreateCapabilityMap(const char* device_unique_id_utf8) override + RTC_EXCLUSIVE_LOCKS_REQUIRED(_apiLock); private: std::map _capabilitiesMap; diff --git a/dom/workers/Queue.h b/dom/workers/Queue.h index 646ea2c43b94..a80e15378386 100644 --- a/dom/workers/Queue.h +++ b/dom/workers/Queue.h @@ -59,6 +59,7 @@ class LockingWithMutex { protected: LockingWithMutex() : mMutex("LockingWithMutex::mMutex") {} + PUSH_IGNORE_THREAD_SAFETY void Lock() { mMutex.Lock(); } void Unlock() { mMutex.Unlock(); } @@ -71,6 +72,7 @@ class LockingWithMutex { ~AutoLock() { mHost.Unlock(); } }; + POP_THREAD_SAFETY friend class AutoLock; }; diff --git a/dom/workers/WorkerPrivate.h b/dom/workers/WorkerPrivate.h index 404a0b5d10f6..91f8ac9fdbba 100644 --- a/dom/workers/WorkerPrivate.h +++ b/dom/workers/WorkerPrivate.h @@ -99,11 +99,13 @@ class SharedMutex { SharedMutex(const SharedMutex& aOther) = default; - operator Mutex&() { return *mMutex; } + operator Mutex&() RETURN_CAPABILITY(*mMutex) { return *mMutex; } - operator const Mutex&() const { return *mMutex; } + operator const Mutex&() const RETURN_CAPABILITY(*mMutex) { return *mMutex; } - void AssertCurrentThreadOwns() const { mMutex->AssertCurrentThreadOwns(); } + void AssertCurrentThreadOwns() const ASSERT_CAPABILITY(*mMutex) { + mMutex->AssertCurrentThreadOwns(); + } }; nsString ComputeWorkerPrivateId(); diff --git a/gfx/2d/2D.h b/gfx/2d/2D.h index 1de0c1bdfb82..e728cbf440a5 100644 --- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -980,11 +980,13 @@ class SharedFTFace : public external::AtomicRefCounted { * If no owner is given, then the user should avoid modifying any state on * the face so as not to invalidate the prior owner's modification. */ + PUSH_IGNORE_THREAD_SAFETY bool Lock(void* aOwner = nullptr) { mLock.Lock(); return !aOwner || mLastLockOwner.exchange(aOwner) == aOwner; } void Unlock() { mLock.Unlock(); } + POP_THREAD_SAFETY /** Should be called when a lock owner is destroyed so that we don't have * a dangling pointer to a destroyed owner. diff --git a/gfx/2d/Factory.cpp b/gfx/2d/Factory.cpp index e8ad6fb12186..038da4f35c1c 100644 --- a/gfx/2d/Factory.cpp +++ b/gfx/2d/Factory.cpp @@ -630,9 +630,11 @@ void Factory::ReleaseFTLibrary(FT_Library aFTLibrary) { FT_Done_FreeType(aFTLibrary); } +PUSH_IGNORE_THREAD_SAFETY void Factory::LockFTLibrary(FT_Library aFTLibrary) { mFTLock.Lock(); } void Factory::UnlockFTLibrary(FT_Library aFTLibrary) { mFTLock.Unlock(); } +POP_THREAD_SAFETY FT_Face Factory::NewFTFace(FT_Library aFTLibrary, const char* aFileName, int aFaceIndex) { diff --git a/gfx/2d/SourceSurfaceSkia.cpp b/gfx/2d/SourceSurfaceSkia.cpp index e5ca3c83a181..0ef782335e15 100644 --- a/gfx/2d/SourceSurfaceSkia.cpp +++ b/gfx/2d/SourceSurfaceSkia.cpp @@ -159,7 +159,8 @@ uint8_t* SourceSurfaceSkia::GetData() { return reinterpret_cast(pixmap.writable_addr()); } -bool SourceSurfaceSkia::Map(MapType, MappedSurface* aMappedSurface) { +bool SourceSurfaceSkia::Map(MapType, MappedSurface* aMappedSurface) + NO_THREAD_SAFETY_ANALYSIS { mChangeMutex.Lock(); aMappedSurface->mData = GetData(); aMappedSurface->mStride = Stride(); @@ -171,7 +172,7 @@ bool SourceSurfaceSkia::Map(MapType, MappedSurface* aMappedSurface) { return isMapped; } -void SourceSurfaceSkia::Unmap() { +void SourceSurfaceSkia::Unmap() NO_THREAD_SAFETY_ANALYSIS { MOZ_ASSERT(mIsMapped); mIsMapped = false; mChangeMutex.Unlock(); diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index 83c9037733e7..a60db1ea3560 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -3610,6 +3610,7 @@ void APZCTreeManager::AssertOnUpdaterThread() { GetUpdater()->AssertOnUpdaterThread(); } +PUSH_IGNORE_THREAD_SAFETY void APZCTreeManager::LockTree() { AssertOnUpdaterThread(); mTreeLock.Lock(); @@ -3619,6 +3620,7 @@ void APZCTreeManager::UnlockTree() { AssertOnUpdaterThread(); mTreeLock.Unlock(); } +POP_THREAD_SAFETY void APZCTreeManager::SetDPI(float aDpiValue) { if (!APZThreadUtils::IsControllerThread()) { diff --git a/ipc/glue/DataPipe.cpp b/ipc/glue/DataPipe.cpp index a91855184720..7a713243b35c 100644 --- a/ipc/glue/DataPipe.cpp +++ b/ipc/glue/DataPipe.cpp @@ -290,6 +290,8 @@ nsresult DataPipeBase::ProcessSegmentsInternal( while (*aProcessedCount < aCount) { DataPipeAutoLock lock(*mMutex); + mMutex->AssertCurrentThreadOwns(); + MOZ_LOG(gDataPipeLog, LogLevel::Verbose, ("ProcessSegments(%u of %u) %s", *aProcessedCount, aCount, Describe(lock).get())); diff --git a/ipc/glue/MessageLink.cpp b/ipc/glue/MessageLink.cpp index 83a65dcc7b07..eaa5ffe388de 100644 --- a/ipc/glue/MessageLink.cpp +++ b/ipc/glue/MessageLink.cpp @@ -117,6 +117,7 @@ void PortLink::SendMessage(UniquePtr aMessage) { PortRef port = mPort; bool ok = false; + monitor->AssertCurrentThreadOwns(); { MonitorAutoUnlock guard(*monitor); ok = node->SendUserMessage(port, std::move(aMessage)); diff --git a/js/xpconnect/loader/ScriptPreloader.cpp b/js/xpconnect/loader/ScriptPreloader.cpp index 83d5e042888a..f1efab936f56 100644 --- a/js/xpconnect/loader/ScriptPreloader.cpp +++ b/js/xpconnect/loader/ScriptPreloader.cpp @@ -661,6 +661,7 @@ void ScriptPreloader::PrepareCacheWrite() { // an offset from the start of the block, as specified above. Result ScriptPreloader::WriteCache() { MOZ_ASSERT(!NS_IsMainThread()); + mSaveMonitor.AssertCurrentThreadOwns(); if (!mDataPrepared && !mSaveComplete) { MonitorAutoUnlock mau(mSaveMonitor); diff --git a/netwerk/base/nsProtocolProxyService.cpp b/netwerk/base/nsProtocolProxyService.cpp index d81ec1fb797a..ce513778c129 100644 --- a/netwerk/base/nsProtocolProxyService.cpp +++ b/netwerk/base/nsProtocolProxyService.cpp @@ -1513,8 +1513,10 @@ class nsAsyncBridgeRequest final : public nsPACManCallback { mCondVar.Notify(); } + PUSH_IGNORE_THREAD_SAFETY void Lock() { mMutex.Lock(); } void Unlock() { mMutex.Unlock(); } + POP_THREAD_SAFETY void Wait() { mCondVar.Wait(TimeDuration::FromSeconds(3)); } private: diff --git a/netwerk/cache2/CacheFile.h b/netwerk/cache2/CacheFile.h index b1c931788060..1369801efc00 100644 --- a/netwerk/cache2/CacheFile.h +++ b/netwerk/cache2/CacheFile.h @@ -140,6 +140,7 @@ class CacheFile final : public CacheFileChunkListener, virtual ~CacheFile(); + PUSH_IGNORE_THREAD_SAFETY void Lock() { mLock->Lock().Lock(); } void Unlock() { // move the elements out of mObjsToRelease @@ -148,6 +149,7 @@ class CacheFile final : public CacheFileChunkListener, mLock->Lock().Unlock(); } + POP_THREAD_SAFETY void AssertOwnsLock() const { mLock->Lock().AssertCurrentThreadOwns(); } void ReleaseOutsideLock(RefPtr aObject); diff --git a/netwerk/cache2/CacheIOThread.cpp b/netwerk/cache2/CacheIOThread.cpp index 53db33e3caaa..da3052f212eb 100644 --- a/netwerk/cache2/CacheIOThread.cpp +++ b/netwerk/cache2/CacheIOThread.cpp @@ -493,6 +493,7 @@ void CacheIOThread::ThreadFunc() { } void CacheIOThread::LoopOneLevel(uint32_t aLevel) { + mMonitor.AssertCurrentThreadOwns(); EventQueue events = std::move(mEventQueue[aLevel]); EventQueue::size_type length = events.Length(); diff --git a/netwerk/cache2/CacheIndex.cpp b/netwerk/cache2/CacheIndex.cpp index 4a07d8f08ccb..a0de065572d2 100644 --- a/netwerk/cache2/CacheIndex.cpp +++ b/netwerk/cache2/CacheIndex.cpp @@ -2692,6 +2692,7 @@ void CacheIndex::BuildIndex(const StaticMutexAutoLock& aProofOfLock) { if (!mDirEnumerator) { { // Do not do IO under the lock. + sLock.AssertCurrentThreadOwns(); StaticMutexAutoUnlock unlock(sLock); rv = SetupDirectoryEnumerator(); } @@ -2719,6 +2720,7 @@ void CacheIndex::BuildIndex(const StaticMutexAutoLock& aProofOfLock) { nsCOMPtr file; { // Do not do IO under the lock. + sLock.AssertCurrentThreadOwns(); StaticMutexAutoUnlock unlock(sLock); rv = mDirEnumerator->GetNextFile(getter_AddRefs(file)); @@ -2926,6 +2928,7 @@ void CacheIndex::UpdateIndex(const StaticMutexAutoLock& aProofOfLock) { LOG(("CacheIndex::UpdateIndex()")); MOZ_ASSERT(mPendingUpdates.Count() == 0); + sLock.AssertCurrentThreadOwns(); nsresult rv; diff --git a/netwerk/dns/nsIDNService.cpp b/netwerk/dns/nsIDNService.cpp index 676b83d7b6d0..f92d4a82e848 100644 --- a/netwerk/dns/nsIDNService.cpp +++ b/netwerk/dns/nsIDNService.cpp @@ -399,7 +399,7 @@ class MOZ_STACK_CLASS MutexSettableAutoUnlock final { public: MutexSettableAutoUnlock() = default; - void Acquire(mozilla::Mutex& aMutex) { + void Acquire(mozilla::Mutex& aMutex) NO_THREAD_SAFETY_ANALYSIS { MOZ_ASSERT(!mMutex); mMutex = &aMutex; mMutex->Lock(); diff --git a/netwerk/protocol/http/nsHttpRequestHead.h b/netwerk/protocol/http/nsHttpRequestHead.h index 3d8dc2f88b97..2a884a146d12 100644 --- a/netwerk/protocol/http/nsHttpRequestHead.h +++ b/netwerk/protocol/http/nsHttpRequestHead.h @@ -40,8 +40,11 @@ class nsHttpRequestHead { // copying headers. If you use it be careful to do it only under // nsHttpRequestHead lock!!! const nsHttpHeaderArray& Headers() const; + + PUSH_IGNORE_THREAD_SAFETY void Enter() const { mRecursiveMutex.Lock(); } void Exit() const { mRecursiveMutex.Unlock(); } + POP_THREAD_SAFETY void SetHeaders(const nsHttpHeaderArray& aHeaders); diff --git a/netwerk/protocol/http/nsHttpResponseHead.h b/netwerk/protocol/http/nsHttpResponseHead.h index 8dab39ecdacc..f29a282db58f 100644 --- a/netwerk/protocol/http/nsHttpResponseHead.h +++ b/netwerk/protocol/http/nsHttpResponseHead.h @@ -43,8 +43,10 @@ class nsHttpResponseHead { nsHttpResponseHead(const nsHttpResponseHead& aOther); nsHttpResponseHead& operator=(const nsHttpResponseHead& aOther); + PUSH_IGNORE_THREAD_SAFETY void Enter() const { mRecursiveMutex.Lock(); } void Exit() const { mRecursiveMutex.Unlock(); } + POP_THREAD_SAFETY HttpVersion Version(); uint16_t Status() const; diff --git a/netwerk/sctp/datachannel/DataChannel.cpp b/netwerk/sctp/datachannel/DataChannel.cpp index a628c2ba6ef8..177c09766e93 100644 --- a/netwerk/sctp/datachannel/DataChannel.cpp +++ b/netwerk/sctp/datachannel/DataChannel.cpp @@ -2365,9 +2365,9 @@ void DataChannelConnection::HandleNotification( } } -int DataChannelConnection::ReceiveCallback(struct socket* sock, void* data, - size_t datalen, - struct sctp_rcvinfo rcv, int flags) { +int DataChannelConnection::ReceiveCallback( + struct socket* sock, void* data, size_t datalen, struct sctp_rcvinfo rcv, + int flags) NO_THREAD_SAFETY_ANALYSIS { ASSERT_WEBRTC(!NS_IsMainThread()); DC_DEBUG(("In ReceiveCallback")); diff --git a/startupcache/StartupCache.cpp b/startupcache/StartupCache.cpp index 50ce9d8e4b2c..f82ea68ea8b6 100644 --- a/startupcache/StartupCache.cpp +++ b/startupcache/StartupCache.cpp @@ -363,7 +363,7 @@ bool StartupCache::HasEntry(const char* id) { } nsresult StartupCache::GetBuffer(const char* id, const char** outbuf, - uint32_t* length) { + uint32_t* length) NO_THREAD_SAFETY_ANALYSIS { AUTO_PROFILER_LABEL("StartupCache::GetBuffer", OTHER); NS_ASSERTION(NS_IsMainThread(), @@ -450,7 +450,7 @@ nsresult StartupCache::GetBuffer(const char* id, const char** outbuf, // Makes a copy of the buffer, client retains ownership of inbuf. nsresult StartupCache::PutBuffer(const char* id, UniquePtr&& inbuf, - uint32_t len) { + uint32_t len) NO_THREAD_SAFETY_ANALYSIS { NS_ASSERTION(NS_IsMainThread(), "Startup cache only available on main thread"); if (StartupCache::gShutdownInitiated) { @@ -469,7 +469,10 @@ nsresult StartupCache::PutBuffer(const char* id, UniquePtr&& inbuf, if (!mTableLock.TryLock()) { return NS_ERROR_NOT_AVAILABLE; } - auto lockGuard = MakeScopeExit([&] { mTableLock.Unlock(); }); + auto lockGuard = MakeScopeExit([&] { + mTableLock.AssertCurrentThreadOwns(); + mTableLock.Unlock(); + }); // putNew returns false on alloc failure - in the very unlikely event we hit // that and aren't going to crash elsewhere, there's no reason we need to diff --git a/toolkit/crashreporter/nsExceptionHandler.cpp b/toolkit/crashreporter/nsExceptionHandler.cpp index b50e86651f7a..a7c91db04544 100644 --- a/toolkit/crashreporter/nsExceptionHandler.cpp +++ b/toolkit/crashreporter/nsExceptionHandler.cpp @@ -3256,9 +3256,9 @@ static void MaybeAnnotateDumperError(const ClientInfo& aClientInfo, #endif } -static void OnChildProcessDumpRequested(void* aContext, - const ClientInfo& aClientInfo, - const xpstring& aFilePath) { +static void OnChildProcessDumpRequested( + void* aContext, const ClientInfo& aClientInfo, + const xpstring& aFilePath) NO_THREAD_SAFETY_ANALYSIS { nsCOMPtr minidump; // Hold the mutex until the current dump request is complete, to @@ -3303,8 +3303,8 @@ static void OnChildProcessDumpRequested(void* aContext, } } -static void OnChildProcessDumpWritten(void* aContext, - const ClientInfo& aClientInfo) { +static void OnChildProcessDumpWritten( + void* aContext, const ClientInfo& aClientInfo) NO_THREAD_SAFETY_ANALYSIS { ProcessId pid = aClientInfo.pid(); ChildProcessData* pd = pidToMinidump->GetEntry(pid); MOZ_ASSERT(pd); diff --git a/widget/android/jni/Natives.h b/widget/android/jni/Natives.h index 5fab5c62c098..4a349aacf895 100644 --- a/widget/android/jni/Natives.h +++ b/widget/android/jni/Natives.h @@ -599,9 +599,11 @@ class MOZ_HEAP_CLASS NativeWeakPtrControlBlock final { return nativeImpl; } + PUSH_IGNORE_THREAD_SAFETY void Lock() const { mLock.ReadLock(); } void Unlock() const { mLock.ReadUnlock(); } + POP_THREAD_SAFETY #if defined(DEBUG) // This is kind of expensive, so we only support it in debug builds. diff --git a/widget/cocoa/nsChildView.mm b/widget/cocoa/nsChildView.mm index 710b604a0890..25b9e82ec2fd 100644 --- a/widget/cocoa/nsChildView.mm +++ b/widget/cocoa/nsChildView.mm @@ -1615,7 +1615,7 @@ void nsChildView::ConfigureAPZCTreeManager() { nsBaseWidget::ConfigureAPZCTreeMa void nsChildView::ConfigureAPZControllerThread() { nsBaseWidget::ConfigureAPZControllerThread(); } -bool nsChildView::PreRender(WidgetRenderingContext* aContext) { +bool nsChildView::PreRender(WidgetRenderingContext* aContext) NO_THREAD_SAFETY_ANALYSIS { // The lock makes sure that we don't attempt to tear down the view while // compositing. That would make us unable to call postRender on it when the // composition is done, thus keeping the GL context locked forever. @@ -1628,7 +1628,9 @@ bool nsChildView::PreRender(WidgetRenderingContext* aContext) { return true; } -void nsChildView::PostRender(WidgetRenderingContext* aContext) { mCompositingLock.Unlock(); } +void nsChildView::PostRender(WidgetRenderingContext* aContext) NO_THREAD_SAFETY_ANALYSIS { + mCompositingLock.Unlock(); +} RefPtr nsChildView::GetNativeLayerRoot() { return mNativeLayerRoot; } diff --git a/widget/gtk/MozContainerWayland.cpp b/widget/gtk/MozContainerWayland.cpp index b86fa655def3..3e84b3a691a8 100644 --- a/widget/gtk/MozContainerWayland.cpp +++ b/widget/gtk/MozContainerWayland.cpp @@ -606,7 +606,8 @@ static bool moz_container_wayland_surface_create_locked( return true; } -struct wl_surface* moz_container_wayland_surface_lock(MozContainer* container) { +struct wl_surface* moz_container_wayland_surface_lock(MozContainer* container) + NO_THREAD_SAFETY_ANALYSIS { // LOGWAYLAND("%s [%p] surface %p ready_to_draw %d\n", __FUNCTION__, // (void*)container, (void*)container->wl_container.surface, // container->wl_container.ready_to_draw); @@ -619,7 +620,8 @@ struct wl_surface* moz_container_wayland_surface_lock(MozContainer* container) { } void moz_container_wayland_surface_unlock(MozContainer* container, - struct wl_surface** surface) { + struct wl_surface** surface) + NO_THREAD_SAFETY_ANALYSIS { // Temporarily disabled to avoid log noise // LOGWAYLAND("%s [%p] surface %p\n", __FUNCTION__, (void*)container, // (void*)container->wl_container.surface); @@ -643,11 +645,13 @@ struct wl_surface* moz_container_wayland_get_surface_locked( return container->wl_container.surface; } -void moz_container_wayland_lock(MozContainer* container) { +void moz_container_wayland_lock(MozContainer* container) + NO_THREAD_SAFETY_ANALYSIS { container->wl_container.container_lock->Lock(); } -void moz_container_wayland_unlock(MozContainer* container) { +void moz_container_wayland_unlock(MozContainer* container) + NO_THREAD_SAFETY_ANALYSIS { container->wl_container.container_lock->Unlock(); } diff --git a/widget/gtk/WaylandVsyncSource.cpp b/widget/gtk/WaylandVsyncSource.cpp index 0b6ceca96ee3..2f9aa6cee59a 100644 --- a/widget/gtk/WaylandVsyncSource.cpp +++ b/widget/gtk/WaylandVsyncSource.cpp @@ -131,6 +131,7 @@ void WaylandVsyncSource::MaybeUpdateSource( void WaylandVsyncSource::Refresh(const MutexAutoLock& aProofOfLock) { LOG("WaylandVsyncSource::Refresh fps %f\n", GetFPS(mVsyncRate)); + mMutex.AssertCurrentThreadOwns(); if (!(mContainer || mNativeLayerRoot) || !mMonitorEnabled || !mVsyncEnabled || mCallbackRequested) { diff --git a/xpcom/components/nsComponentManager.cpp b/xpcom/components/nsComponentManager.cpp index 2726b4273807..246179080437 100644 --- a/xpcom/components/nsComponentManager.cpp +++ b/xpcom/components/nsComponentManager.cpp @@ -613,6 +613,7 @@ void nsComponentManagerImpl::RegisterCIDEntryLocked( #endif mFactories.WithEntryHandle(aEntry->cid, [&](auto&& entry) { + mLock.AssertCurrentThreadOwns(); if (entry) { nsFactoryEntry* f = entry.Data(); NS_WARNING("Re-registering a CID?"); @@ -1285,6 +1286,7 @@ nsresult nsComponentManagerImpl::GetServiceLocked(Maybe& aLock, } }); nsresult rv; + mLock.AssertCurrentThreadOwns(); { MonitorAutoUnlock unlock(mLock); AUTO_PROFILER_MARKER_TEXT( diff --git a/xpcom/io/nsMultiplexInputStream.cpp b/xpcom/io/nsMultiplexInputStream.cpp index f27d52d59a7d..66a4d695cb55 100644 --- a/xpcom/io/nsMultiplexInputStream.cpp +++ b/xpcom/io/nsMultiplexInputStream.cpp @@ -1390,6 +1390,8 @@ nsMultiplexInputStream::AsyncLengthWait(nsIInputStreamLengthCallback* aCallback, void nsMultiplexInputStream::AsyncWaitCompleted( int64_t aLength, const MutexAutoLock& aProofOfLock) { + mLock.AssertCurrentThreadOwns(); + nsCOMPtr callback; callback.swap(mAsyncWaitLengthCallback); diff --git a/xpcom/tests/gtest/TestSynchronization.cpp b/xpcom/tests/gtest/TestSynchronization.cpp index b1c08163c61b..327f5bfe3fa3 100644 --- a/xpcom/tests/gtest/TestSynchronization.cpp +++ b/xpcom/tests/gtest/TestSynchronization.cpp @@ -238,7 +238,7 @@ TEST(Synchronization, AutoLock) // AutoTryLock tests // TEST(Synchronization, AutoTryLock) -{ +NO_THREAD_SAFETY_ANALYSIS { Mutex l1 MOZ_UNANNOTATED("autotrylock"); MutexAutoTryLock autol1(l1); diff --git a/xpcom/threads/TaskController.cpp b/xpcom/threads/TaskController.cpp index 1aaecc4147df..f7e5b9cb1219 100644 --- a/xpcom/threads/TaskController.cpp +++ b/xpcom/threads/TaskController.cpp @@ -605,6 +605,7 @@ uint64_t TaskController::PendingMainthreadTaskCountIncludingSuspended() { bool TaskController::ExecuteNextTaskOnlyMainThreadInternal( const MutexAutoLock& aProofOfLock) { + mGraphMutex.AssertCurrentThreadOwns(); // Block to make it easier to jump to our cleanup. bool taskRan = false; do { @@ -674,6 +675,8 @@ bool TaskController::ExecuteNextTaskOnlyMainThreadInternal( bool TaskController::DoExecuteNextTaskOnlyMainThreadInternal( const MutexAutoLock& aProofOfLock) { + mGraphMutex.AssertCurrentThreadOwns(); + nsCOMPtr mainIThread; NS_GetMainThread(getter_AddRefs(mainIThread));