haikuwebkit/Source/WTF/wtf/ThreadAssertions.h

105 lines
3.9 KiB
C
Raw Permalink Normal View History

Asserting that function or variable is accessed in a certain thread should be simpler and more robust https://bugs.webkit.org/show_bug.cgi?id=224971 Patch by Kimmo Kinnunen <kkinnunen@apple.com> on 2021-04-28 Reviewed by Darin Adler. Source/WebKit: Use ThreadAssertions in RemoteGraphicsContextGL implementations as an example. * GPUProcess/graphics/RemoteGraphicsContextGL.cpp: (WebKit::RemoteGraphicsContextGL::RemoteGraphicsContextGL): (WebKit::RemoteGraphicsContextGL::~RemoteGraphicsContextGL): (WebKit::RemoteGraphicsContextGL::initialize): (WebKit::RemoteGraphicsContextGL::stopListeningForIPC): (WebKit::RemoteGraphicsContextGL::displayWasReconfigured): (WebKit::RemoteGraphicsContextGL::workQueueInitialize): (WebKit::RemoteGraphicsContextGL::workQueueUninitialize): (WebKit::RemoteGraphicsContextGL::didComposite): (WebKit::RemoteGraphicsContextGL::forceContextLost): (WebKit::RemoteGraphicsContextGL::dispatchContextChangedNotification): (WebKit::RemoteGraphicsContextGL::reshape): (WebKit::RemoteGraphicsContextGL::prepareForDisplay): (WebKit::RemoteGraphicsContextGL::synthesizeGLError): (WebKit::RemoteGraphicsContextGL::getError): (WebKit::RemoteGraphicsContextGL::ensureExtensionEnabled): (WebKit::RemoteGraphicsContextGL::notifyMarkContextChanged): (WebKit::RemoteGraphicsContextGL::paintRenderingResultsToCanvas): (WebKit::RemoteGraphicsContextGL::paintCompositedResultsToCanvas): (WebKit::RemoteGraphicsContextGL::paintImageDataToImageBuffer): (WebKit::RemoteGraphicsContextGL::copyTextureFromMedia): (WebKit::RemoteGraphicsContextGL::simulateEventForTesting): * GPUProcess/graphics/RemoteGraphicsContextGL.h: * GPUProcess/graphics/RemoteGraphicsContextGLCocoa.cpp: (WebKit::RemoteGraphicsContextGLCocoa::platformWorkQueueInitialize): (WebKit::RemoteGraphicsContextGLCocoa::prepareForDisplay): * GPUProcess/graphics/RemoteGraphicsContextGLFunctionsGenerated.h: Source/WTF: Adds support for more fine-grained thread assertion than ASSERT(isMainThread()) / ASSERT(!isMainThread()) * WTF.xcodeproj/project.pbxproj: * wtf/CMakeLists.txt: * wtf/Compiler.h: Add NO_UNIQUE_ADDRESS which can be used to declare members that are empty in RELEASE builds. The declaration avoids increasing the size of the enclosing type. This should be used with ThreadAssertion: class MyThreadAware { .... NO_UNIQUE_ADDRESS ThreadAssertion m_ownerThread; }; * wtf/ThreadAssertions.h: Added. Add ThreadAssertion class that can be held as a member of a type. This allows consistent assertions that the code in the type runs in the expected thread. Add NamedAssertion& WTF::mainThread. Add NamedAssertion& WTF::mainRunLoop. These are only to be used in thread safety analysis phase. These are undefined symbols, it is an error to reference them. Adds functions assertIsMainThread() and assertIsMainRunLoop() to replace patterns of ASSERT(isMainThread()), ASSERT(isMainRunLoop(). In addition to behaving as the direct ASSERT behaves, the functions enable compile-time thread safety analysis to know that the calling scope has the assertions. These can be optionally then used in the function and member signatures to require the assertions. Tools: Add simple tests to make sure code in ThreadAssertions.h compiles. * Scripts/generate-gpup-webgl: Use ThreadAssertions in RemoteGraphicsContextGL implementation as an example. * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: * TestWebKitAPI/Tests/WTF/ThreadAssertionsTest.cpp: Added. (TestWebKitAPI::TEST): (TestWebKitAPI::WTF_REQUIRES_LOCK): Canonical link: https://commits.webkit.org/237115@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@276706 268f45cc-cd09-0410-ab3c-d52691b4dbfc
2021-04-28 13:30:15 +00:00
/*
* Copyright (C) 2021 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#pragma once
#include <wtf/Compiler.h>
#include <wtf/MainThread.h>
#include <wtf/ThreadSafetyAnalysis.h>
#include <wtf/Threading.h>
namespace WTF {
// A type to use for asserting that private member functions or private member variables
// of a class are accessed from correct threads.
// Supports run-time checking with assertion enabled builds.
// Supports compile-time declaration and checking.
// Example:
// struct MyClass {
// void doTask() { assertIsCurrent(m_ownerThread); doTaskImpl(); }
// template<typename> void doTaskCompileFailure() { doTaskImpl(); }
// private:
// void doTaskImpl() WTF_REQUIRES_LOCK(m_ownerThread);
// int m_value WTF_GUARDED_BY_LOCK(m_ownerThread) { 0 };
// NO_UNIQUE_ADDRESS ThreadAssertion m_ownerThread;
// };
class WTF_CAPABILITY_LOCK ThreadAssertion {
public:
ThreadAssertion() = default;
enum UninitializedTag { Uninitialized };
constexpr ThreadAssertion(UninitializedTag)
#if ASSERT_ENABLED
: m_uid(0) // Thread::uid() does not return this.
#endif
{
}
~ThreadAssertion() { assertIsCurrent(*this); }
void reset() { *this = ThreadAssertion { }; }
private:
#if ASSERT_ENABLED
uint32_t m_uid { Thread::current().uid() };
#endif
friend void assertIsCurrent(const ThreadAssertion&);
};
inline void assertIsCurrent(const ThreadAssertion& threadAssertion) WTF_ASSERTS_ACQUIRED_LOCK(threadAssertion)
{
ASSERT_UNUSED(threadAssertion, Thread::current().uid() == threadAssertion.m_uid);
}
// Type for globally named assertions for describing access requirements.
// Can be used, for example, to require that a variable is accessed only in
// a known named thread.
// Example:
// extern NamedAssertion& mainThread;
// inline void assertIsMainThread() WTF_ASSERTS_ACQUIRED_LOCK(mainThread);
// void myTask() WTF_REQUIRES_LOCK(mainThread) { printf("my task is running"); }
// void runner() {
// assertIsMainThread();
// myTask();
// }
// template<typename> runnerCompileFailure() {
// myTask();
// }
class WTF_CAPABILITY_LOCK NamedAssertion { };
// To be used with WTF_REQUIRES_LOCK(mainThread). Symbol is undefined.
extern NamedAssertion& mainThread;
inline void assertIsMainThread() WTF_ASSERTS_ACQUIRED_LOCK(mainThread) { ASSERT(isMainThread()); }
// To be used with WTF_REQUIRES_LOCK(mainRunLoop). Symbol is undefined.
extern NamedAssertion& mainRunLoop;
inline void assertIsMainRunLoop() WTF_ASSERTS_ACQUIRED_LOCK(mainRunLoop) { ASSERT(isMainRunLoop()); }
}
using WTF::ThreadAssertion;
using WTF::assertIsCurrent;
using WTF::NamedAssertion;
using WTF::assertIsMainThread;
using WTF::assertIsMainRunLoop;
using WTF::mainThread;
using WTF::mainRunLoop;