Changeset 139514 in webkit
- Timestamp:
- Jan 11, 2013, 4:01:56 PM (12 years ago)
- Location:
- trunk/Source/WebKit2
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit2/ChangeLog
r139500 r139514 1 2013-01-11 Alexey Proskuryakov <ap@apple.com> 2 3 [WK2] Make it possible to send sync messages from secondary threads 4 https://bugs.webkit.org/show_bug.cgi?id=106708 5 6 Reviewed by Anders Carlsson. 7 8 It is hugely beneficial to implement sync messages at Connection level, because 9 ad hoc code that blocks a thread and wakes it up when a reply arrives on main 10 thread can't be made equally performant. A CoreOPC MessageDecoder can be moved across 11 threads, which can't be done with a decoded argument passed by reference to client code. 12 13 Sync messages from secondary threads are tracked in much simpler data structure 14 than client thread ones, because we don't need to be concerned with incoming messages. 15 16 * Platform/CoreIPC/Connection.cpp: 17 (Connection::SecondaryThreadPendingSyncReply): 18 (CoreIPC::Connection::SecondaryThreadPendingSyncReply::SecondaryThreadPendingSyncReply): 19 (CoreIPC::Connection::createSyncMessageEncoder): 20 (CoreIPC::Connection::sendSyncMessage): 21 (CoreIPC::Connection::sendSyncMessageFromSecondaryThread): 22 (CoreIPC::Connection::processIncomingSyncReply): 23 (CoreIPC::Connection::connectionDidClose): 24 25 * Platform/CoreIPC/Connection.h: Also corrected a misleading comment. 26 1 27 2013-01-11 Dan Bernstein <mitz@apple.com> 2 28 -
trunk/Source/WebKit2/Platform/CoreIPC/Connection.cpp
r139464 r139514 94 94 }; 95 95 96 class Connection::SecondaryThreadPendingSyncReply { 97 WTF_MAKE_NONCOPYABLE(SecondaryThreadPendingSyncReply); 98 public: 99 SecondaryThreadPendingSyncReply() : replyDecoder(0) { } 100 101 // The reply decoder, will be null if there was an error processing the sync message on the other side. 102 MessageDecoder* replyDecoder; 103 104 BinarySemaphore semaphore; 105 }; 106 107 96 108 PassRefPtr<Connection::SyncMessageState> Connection::SyncMessageState::getOrCreate(RunLoop* runLoop) 97 109 { … … 298 310 299 311 // Encode the sync request ID. 300 syncRequestID = ++m_syncRequestID; 312 COMPILE_ASSERT(sizeof(m_syncRequestID) == sizeof(int64_t), CanUseAtomicIncrement); 313 syncRequestID = atomicIncrement(reinterpret_cast<int64_t volatile*>(&m_syncRequestID)); 301 314 encoder->encode(syncRequestID); 302 315 … … 387 400 PassOwnPtr<MessageDecoder> Connection::sendSyncMessage(MessageID messageID, uint64_t syncRequestID, PassOwnPtr<MessageEncoder> encoder, double timeout, unsigned syncSendFlags) 388 401 { 389 // We only allow sending sync messages from the client run loop. 390 ASSERT(RunLoop::current() == m_clientRunLoop); 402 if (RunLoop::current() != m_clientRunLoop) { 403 // No flags are supported for synchronous messages sent from secondary threads. 404 ASSERT(!syncSendFlags); 405 return sendSyncMessageFromSecondaryThread(messageID, syncRequestID, encoder, timeout); 406 } 391 407 392 408 if (!isValid()) { … … 421 437 } 422 438 423 if (!reply) 439 // FIXME: Should we call didFailToSendSyncMessage()? It may be unexpected to get in on a background thread. 440 441 return reply.release(); 442 } 443 444 PassOwnPtr<MessageDecoder> Connection::sendSyncMessageFromSecondaryThread(MessageID messageID, uint64_t syncRequestID, PassOwnPtr<MessageEncoder> encoder, double timeout) 445 { 446 ASSERT(RunLoop::current() != m_clientRunLoop); 447 448 if (!isValid()) { 424 449 didFailToSendSyncMessage(); 425 426 return reply.release(); 450 return nullptr; 451 } 452 453 SecondaryThreadPendingSyncReply pendingReply; 454 455 // Push the pending sync reply information on our stack. 456 { 457 MutexLocker locker(m_syncReplyStateMutex); 458 if (!m_shouldWaitForSyncReplies) { 459 didFailToSendSyncMessage(); 460 return nullptr; 461 } 462 463 ASSERT(!m_secondaryThreadPendingSyncReplyMap.contains(syncRequestID)); 464 m_secondaryThreadPendingSyncReplyMap.add(syncRequestID, &pendingReply); 465 } 466 467 sendMessage(messageID.messageIDWithAddedFlags(MessageID::SyncMessage), encoder, 0); 468 469 // Use a really long timeout. 470 if (timeout == NoTimeout) 471 timeout = 1e10; 472 473 pendingReply.semaphore.wait(timeout); 474 475 // Finally, pop the pending sync reply information. 476 { 477 MutexLocker locker(m_syncReplyStateMutex); 478 ASSERT(m_secondaryThreadPendingSyncReplyMap.contains(syncRequestID)); 479 m_secondaryThreadPendingSyncReplyMap.remove(syncRequestID); 480 } 481 482 if (!pendingReply.replyDecoder) 483 didFailToSendSyncMessage(); 484 485 return adoptPtr(pendingReply.replyDecoder); 427 486 } 428 487 … … 503 562 } 504 563 505 // If we get here, it means we got a reply for a message that wasn't in the sync request stack. 564 // If it's not a reply to any primary thread message, check if it is a reply to a secondary thread one. 565 SecondaryThreadPendingSyncReplyMap::iterator secondaryThreadReplyMapItem = m_secondaryThreadPendingSyncReplyMap.find(decoder->destinationID()); 566 if (secondaryThreadReplyMapItem != m_secondaryThreadPendingSyncReplyMap.end()) { 567 SecondaryThreadPendingSyncReply* reply = secondaryThreadReplyMapItem->value; 568 ASSERT(!reply->replyDecoder); 569 reply->replyDecoder = decoder.leakPtr(); 570 reply->semaphore.signal(); 571 } 572 573 // If we get here, it means we got a reply for a message that wasn't in the sync request stack or map. 506 574 // This can happen if the send timed out, so it's fine to ignore. 507 575 } … … 571 639 if (!m_pendingSyncReplies.isEmpty()) 572 640 m_syncMessageState->wakeUpClientRunLoop(); 641 642 for (SecondaryThreadPendingSyncReplyMap::iterator iter = m_secondaryThreadPendingSyncReplyMap.begin(); iter != m_secondaryThreadPendingSyncReplyMap.end(); ++iter) 643 iter->value->semaphore.signal(); 573 644 } 574 645 -
trunk/Source/WebKit2/Platform/CoreIPC/Connection.h
r139023 r139514 183 183 bool sendMessage(MessageID, PassOwnPtr<MessageEncoder>, unsigned messageSendFlags = 0); 184 184 PassOwnPtr<MessageDecoder> sendSyncMessage(MessageID, uint64_t syncRequestID, PassOwnPtr<MessageEncoder>, double timeout, unsigned syncSendFlags = 0); 185 PassOwnPtr<MessageDecoder> sendSyncMessageFromSecondaryThread(MessageID, uint64_t syncRequestID, PassOwnPtr<MessageEncoder>, double timeout); 185 186 bool sendSyncReply(PassOwnPtr<MessageEncoder>); 186 187 … … 306 307 MessageDecoder* replyDecoder; 307 308 308 // Will be set to true once a reply has been received or an error occurred.309 // Will be set to true once a reply has been received. 309 310 bool didReceiveReply; 310 311 … … 331 332 } 332 333 }; 333 334 334 335 class SyncMessageState; 335 336 friend class SyncMessageState; … … 339 340 bool m_shouldWaitForSyncReplies; 340 341 Vector<PendingSyncReply> m_pendingSyncReplies; 342 343 class SecondaryThreadPendingSyncReply; 344 typedef HashMap<uint64_t, SecondaryThreadPendingSyncReply*> SecondaryThreadPendingSyncReplyMap; 345 SecondaryThreadPendingSyncReplyMap m_secondaryThreadPendingSyncReplyMap; 341 346 342 347 #if OS(DARWIN)
Note:
See TracChangeset
for help on using the changeset viewer.