⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 284695 in webkit


Ignore:
Timestamp:
Oct 22, 2021, 11:09:11 AM (5 years ago)
Author:
Wenson Hsieh
Message:

RemoteRenderingBackend::CreateImageBuffer should be an async IPC stream message
https://bugs.webkit.org/show_bug.cgi?id=231970

Reviewed by Kimmo Kinnunen.

This patch reverts the changes in r284476, which worked around a race when adding receive queues for newly
created IPC stream destinations and simultaneously dispatching IPC messages to those destinations. Rather than
making the IPC message that creates and adds the new image buffer's RemoteDisplayListRecorder synchronous, we
instead keep that message async and make adjustments to ensure that incoming out-of-stream IPC messages for
RemoteDisplayListRecorder can always be mapped to an appropriate receive queue. See below for more details.

  • GPUProcess/graphics/RemoteDisplayListRecorder.cpp:

(WebKit::RemoteDisplayListRecorder::startListeningForIPC):

Move the main runloop bounce down to StreamServerConnectionBase::startReceivingMessagesImpl() instead (to deal
with the fact that addMessageReceiveQueue currently needs to be invoked on the main runloop). This allows us
to call StreamServerConnection::startReceivingMessages() from the processing queue while creating a remote
image buffer, which (in turn) ensures that incoming out-of-stream messages from the IPC thread will be sent to
the correct RemoteDisplayListRecorder destination by the time they're dispatched on the work queue thread.

  • GPUProcess/graphics/RemoteRenderingBackend.cpp:

(WebKit::RemoteRenderingBackend::startListeningForIPC):
(WebKit::RemoteRenderingBackend::stopListeningForIPC):

Additionally register a "0-destination" receiver to ensure that all RemoteDisplayListRecorder messages (even
without pre-existing destinations) will be enqueued on the same IPC stream connection as this remote rendering
backend.

(WebKit::RemoteRenderingBackend::createImageBuffer):

  • GPUProcess/graphics/RemoteRenderingBackend.h:
  • GPUProcess/graphics/RemoteRenderingBackend.messages.in:

Make CreateImageBuffer an async stream message once again.

  • Platform/IPC/StreamConnectionWorkQueue.cpp:

(IPC::StreamConnectionWorkQueue::processStreams):

  • Platform/IPC/StreamConnectionWorkQueue.h:

Change m_connections into a HashCountedSet (from a HashSet), to ensure that the same server connection object
can be added to and removed from the work queue multiple times, without removing the connection from the map
early.

  • Platform/IPC/StreamServerConnection.cpp:

(IPC::StreamServerConnectionBase::startReceivingMessagesImpl):
(IPC::StreamServerConnectionBase::stopReceivingMessagesImpl):

  • Platform/IPC/StreamServerConnection.h:

(IPC::StreamServerConnection::startReceivingMessages):
(IPC::StreamServerConnection::stopReceivingMessages):

Add new methods to start and stop receiving all messages for a given ReceiverName, regardless of incoming
destination ID. RemoteRenderingBackend now uses this to register a "catch-all" listener for all
RemoteDisplayListRecorder messages.

  • WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp:

(WebKit::RemoteRenderingBackendProxy::createRemoteImageBuffer):

Location:
trunk/Source/WebKit
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r284692 r284695  
     12021-10-22  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        RemoteRenderingBackend::CreateImageBuffer should be an async IPC stream message
     4        https://bugs.webkit.org/show_bug.cgi?id=231970
     5
     6        Reviewed by Kimmo Kinnunen.
     7
     8        This patch reverts the changes in r284476, which worked around a race when adding receive queues for newly
     9        created IPC stream destinations and simultaneously dispatching IPC messages to those destinations. Rather than
     10        making the IPC message that creates and adds the new image buffer's RemoteDisplayListRecorder synchronous, we
     11        instead keep that message async and make adjustments to ensure that incoming out-of-stream IPC messages for
     12        RemoteDisplayListRecorder can always be mapped to an appropriate receive queue. See below for more details.
     13
     14        * GPUProcess/graphics/RemoteDisplayListRecorder.cpp:
     15        (WebKit::RemoteDisplayListRecorder::startListeningForIPC):
     16
     17        Move the main runloop bounce down to `StreamServerConnectionBase::startReceivingMessagesImpl()` instead (to deal
     18        with the fact that `addMessageReceiveQueue` currently needs to be invoked on the main runloop). This allows us
     19        to call `StreamServerConnection::startReceivingMessages()` from the processing queue while creating a remote
     20        image buffer, which (in turn) ensures that incoming out-of-stream messages from the IPC thread will be sent to
     21        the correct RemoteDisplayListRecorder destination by the time they're dispatched on the work queue thread.
     22
     23        * GPUProcess/graphics/RemoteRenderingBackend.cpp:
     24        (WebKit::RemoteRenderingBackend::startListeningForIPC):
     25        (WebKit::RemoteRenderingBackend::stopListeningForIPC):
     26
     27        Additionally register a "0-destination" receiver to ensure that all RemoteDisplayListRecorder messages (even
     28        without pre-existing destinations) will be enqueued on the same IPC stream connection as this remote rendering
     29        backend.
     30
     31        (WebKit::RemoteRenderingBackend::createImageBuffer):
     32        * GPUProcess/graphics/RemoteRenderingBackend.h:
     33        * GPUProcess/graphics/RemoteRenderingBackend.messages.in:
     34
     35        Make `CreateImageBuffer` an async stream message once again.
     36
     37        * Platform/IPC/StreamConnectionWorkQueue.cpp:
     38        (IPC::StreamConnectionWorkQueue::processStreams):
     39        * Platform/IPC/StreamConnectionWorkQueue.h:
     40
     41        Change `m_connections` into a HashCountedSet (from a HashSet), to ensure that the same server connection object
     42        can be added to and removed from the work queue multiple times, without removing the connection from the map
     43        early.
     44
     45        * Platform/IPC/StreamServerConnection.cpp:
     46        (IPC::StreamServerConnectionBase::startReceivingMessagesImpl):
     47        (IPC::StreamServerConnectionBase::stopReceivingMessagesImpl):
     48        * Platform/IPC/StreamServerConnection.h:
     49        (IPC::StreamServerConnection::startReceivingMessages):
     50        (IPC::StreamServerConnection::stopReceivingMessages):
     51
     52        Add new methods to start and stop receiving all messages for a given ReceiverName, regardless of incoming
     53        destination ID. RemoteRenderingBackend now uses this to register a "catch-all" listener for all
     54        RemoteDisplayListRecorder messages.
     55
     56        * WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp:
     57        (WebKit::RemoteRenderingBackendProxy::createRemoteImageBuffer):
     58
    1592021-10-22  Sihui Liu  <sihui_liu@apple.com>
    260
  • trunk/Source/WebKit/GPUProcess/graphics/RemoteDisplayListRecorder.cpp

    r284079 r284695  
    5656    ASSERT(!m_isListeningForIPC);
    5757    m_isListeningForIPC = true;
    58     // FIXME: Can we avoid synchronous dispatch here by adjusting the assertion in `Connection::enqueueMatchingMessagesToMessageReceiveQueue`?
    59     callOnMainRunLoopAndWait([&] {
    60         m_renderingBackend->streamConnection().startReceivingMessages(*this, Messages::RemoteDisplayListRecorder::messageReceiverName(), m_imageBufferIdentifier.object().toUInt64());
    61     });
     58    m_renderingBackend->streamConnection().startReceivingMessages(*this, Messages::RemoteDisplayListRecorder::messageReceiverName(), m_imageBufferIdentifier.object().toUInt64());
    6259}
    6360
  • trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.cpp

    r284681 r284695  
    9393{
    9494    m_streamConnection->startReceivingMessages(*this, Messages::RemoteRenderingBackend::messageReceiverName(), m_renderingBackendIdentifier.toUInt64());
     95    // RemoteDisplayListRecorder messages depend on RemoteRenderingBackend, because RemoteRenderingBackend creates RemoteDisplayListRecorder and
     96    // makes a receive queue for it. In order to guarantee correct ordering, ensure that all RemoteDisplayListRecorder messages are processed in
     97    // the same sequence as RemoteRenderingBackend messages.
     98    m_streamConnection->startReceivingMessages(Messages::RemoteDisplayListRecorder::messageReceiverName());
    9599}
    96100
     
    107111    ASSERT(RunLoop::isMain());
    108112    m_streamConnection->stopReceivingMessages(Messages::RemoteRenderingBackend::messageReceiverName(), m_renderingBackendIdentifier.toUInt64());
     113    m_streamConnection->stopReceivingMessages(Messages::RemoteDisplayListRecorder::messageReceiverName());
    109114    for (auto& remoteContext : std::exchange(m_remoteDisplayLists, { }))
    110115        remoteContext.stopListeningForIPC();
     
    139144}
    140145
    141 void RemoteRenderingBackend::createImageBuffer(const FloatSize& logicalSize, RenderingMode renderingMode, float resolutionScale, const DestinationColorSpace& colorSpace, PixelFormat pixelFormat, RenderingResourceIdentifier imageBufferResourceIdentifier, CompletionHandler<void()>&& completionHandler)
     146void RemoteRenderingBackend::createImageBuffer(const FloatSize& logicalSize, RenderingMode renderingMode, float resolutionScale, const DestinationColorSpace& colorSpace, PixelFormat pixelFormat, RenderingResourceIdentifier imageBufferResourceIdentifier)
    142147{
    143148    // Immediately turn the RenderingResourceIdentifier (which is error-prone) to a QualifiedRenderingResourceIdentifier,
    144149    // and use a helper function to make sure that don't accidentally use the RenderingResourceIdentifier (because the helper function can't see it).
    145150    createImageBufferWithQualifiedIdentifier(logicalSize, renderingMode, resolutionScale, colorSpace, pixelFormat, { imageBufferResourceIdentifier, m_gpuConnectionToWebProcess->webProcessIdentifier() });
    146     completionHandler();
    147151}
    148152
  • trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.h

    r284476 r284695  
    102102
    103103    // Messages to be received.
    104     void createImageBuffer(const WebCore::FloatSize& logicalSize, WebCore::RenderingMode, float resolutionScale, const WebCore::DestinationColorSpace&, WebCore::PixelFormat, WebCore::RenderingResourceIdentifier, CompletionHandler<void()>&&);
     104    void createImageBuffer(const WebCore::FloatSize& logicalSize, WebCore::RenderingMode, float resolutionScale, const WebCore::DestinationColorSpace&, WebCore::PixelFormat, WebCore::RenderingResourceIdentifier);
    105105    void updateSharedMemoryForGetPixelBuffer(uint32_t byteCount, CompletionHandler<void(const SharedMemory::IPCHandle&)>&&);
    106106    void semaphoreForGetPixelBuffer(CompletionHandler<void(const IPC::Semaphore&)>&&);
  • trunk/Source/WebKit/GPUProcess/graphics/RemoteRenderingBackend.messages.in

    r284476 r284695  
    2424
    2525messages -> RemoteRenderingBackend NotRefCounted Stream {
    26     CreateImageBuffer(WebCore::FloatSize logicalSize, WebCore::RenderingMode renderingMode, float resolutionScale, WebCore::DestinationColorSpace colorSpace, enum:uint8_t WebCore::PixelFormat pixelFormat, WebCore::RenderingResourceIdentifier renderingResourceIdentifier) -> () Synchronous
     26    CreateImageBuffer(WebCore::FloatSize logicalSize, WebCore::RenderingMode renderingMode, float resolutionScale, WebCore::DestinationColorSpace colorSpace, enum:uint8_t WebCore::PixelFormat pixelFormat, WebCore::RenderingResourceIdentifier renderingResourceIdentifier)
    2727    UpdateSharedMemoryForGetPixelBuffer(uint32_t byteCount) -> (WebKit::SharedMemory::IPCHandle handle) Synchronous NotStreamEncodableReply
    2828    SemaphoreForGetPixelBuffer() -> (IPC::Semaphore semaphore) Synchronous NotStreamEncodableReply
  • trunk/Source/WebKit/Platform/IPC/StreamConnectionWorkQueue.cpp

    r284681 r284695  
    122122    do {
    123123        Deque<WTF::Function<void()>> functions;
    124         HashSet<Ref<StreamServerConnectionBase>> connections;
     124        Vector<Ref<StreamServerConnectionBase>> connections;
    125125        {
    126126            Locker locker { m_lock };
    127127            functions.swap(m_functions);
    128             connections = m_connections;
     128            connections = copyToVector(m_connections.values());
    129129        }
    130130        for (auto& function : functions)
  • trunk/Source/WebKit/Platform/IPC/StreamConnectionWorkQueue.h

    r284681 r284695  
    3131#include <wtf/Deque.h>
    3232#include <wtf/FunctionDispatcher.h>
    33 #include <wtf/HashSet.h>
     33#include <wtf/HashCountedSet.h>
    3434#include <wtf/Lock.h>
    3535#include <wtf/Threading.h>
     
    6767    RefPtr<Thread> m_processingThread WTF_GUARDED_BY_LOCK(m_lock);
    6868    Deque<Function<void()>> m_functions WTF_GUARDED_BY_LOCK(m_lock);
    69     HashSet<Ref<StreamServerConnectionBase>> m_connections WTF_GUARDED_BY_LOCK(m_lock);
     69    HashCountedSet<Ref<StreamServerConnectionBase>> m_connections WTF_GUARDED_BY_LOCK(m_lock);
    7070};
    7171
  • trunk/Source/WebKit/Platform/IPC/StreamServerConnection.cpp

    r283713 r284695  
    4141void StreamServerConnectionBase::startReceivingMessagesImpl(ReceiverName receiverName, uint64_t destinationID)
    4242{
    43     m_connection->addMessageReceiveQueue(*this, receiverName, destinationID);
     43    // FIXME: Can we avoid synchronous dispatch here by adjusting the assertion in `Connection::enqueueMatchingMessagesToMessageReceiveQueue`?
     44    callOnMainRunLoopAndWait([&] {
     45        m_connection->addMessageReceiveQueue(*this, receiverName, destinationID);
     46    });
    4447    m_workQueue.addStreamConnection(*this);
     48}
     49
     50void StreamServerConnectionBase::startReceivingMessagesImpl(ReceiverName receiverName)
     51{
     52    callOnMainRunLoopAndWait([&] {
     53        m_connection->addMessageReceiveQueue(*this, receiverName);
     54    });
     55    m_workQueue.addStreamConnection(*this);
     56}
     57
     58void StreamServerConnectionBase::stopReceivingMessagesImpl(ReceiverName receiverName)
     59{
     60    m_connection->removeMessageReceiveQueue(receiverName);
     61    m_workQueue.removeStreamConnection(*this);
    4562}
    4663
  • trunk/Source/WebKit/Platform/IPC/StreamServerConnection.h

    r283713 r284695  
    6262    void startReceivingMessagesImpl(ReceiverName, uint64_t destinationID);
    6363    void stopReceivingMessagesImpl(ReceiverName, uint64_t destinationID);
     64
     65    void startReceivingMessagesImpl(ReceiverName);
     66    void stopReceivingMessagesImpl(ReceiverName);
    6467
    6568    // MessageReceiveQueue
     
    145148    void stopReceivingMessages(ReceiverName, uint64_t destinationID);
    146149
     150    inline void startReceivingMessages(ReceiverName);
     151    inline void stopReceivingMessages(ReceiverName);
     152
    147153    // StreamServerConnectionBase overrides.
    148154    DispatchResult dispatchStreamMessages(size_t messageLimit) final;
     
    162168};
    163169
     170void StreamServerConnection::startReceivingMessages(ReceiverName receiverName)
     171{
     172    StreamServerConnectionBase::startReceivingMessagesImpl(receiverName);
    164173}
     174
     175void StreamServerConnection::stopReceivingMessages(ReceiverName receiverName)
     176{
     177    StreamServerConnectionBase::stopReceivingMessagesImpl(receiverName);
     178}
     179
     180}
  • trunk/Source/WebKit/WebProcess/GPU/graphics/RemoteRenderingBackendProxy.cpp

    r284476 r284695  
    128128void RemoteRenderingBackendProxy::createRemoteImageBuffer(ImageBuffer& imageBuffer)
    129129{
    130     // FIXME: This should be an normal (async) stream message. However, doing so may cause subsequent out-of-stream messages sent to the newly created image
    131     // buffer to be dropped by the IPC connection. For the time being, work around this by using sync IPC (see <https://webkit.org/b/231681> for more details).
    132     sendSyncToStream(Messages::RemoteRenderingBackend::CreateImageBuffer(imageBuffer.logicalSize(), imageBuffer.renderingMode(), imageBuffer.resolutionScale(), imageBuffer.colorSpace(), imageBuffer.pixelFormat(), imageBuffer.renderingResourceIdentifier()), Messages::RemoteRenderingBackend::CreateImageBuffer::Reply(), 3_s);
     130    sendToStream(Messages::RemoteRenderingBackend::CreateImageBuffer(imageBuffer.logicalSize(), imageBuffer.renderingMode(), imageBuffer.resolutionScale(), imageBuffer.colorSpace(), imageBuffer.pixelFormat(), imageBuffer.renderingResourceIdentifier()));
    133131}
    134132
Note: See TracChangeset for help on using the changeset viewer.