| Index: mojo/edk/system/dispatcher.cc | 
| diff --git a/third_party/mojo/src/mojo/edk/system/dispatcher.cc b/mojo/edk/system/dispatcher.cc | 
| similarity index 84% | 
| copy from third_party/mojo/src/mojo/edk/system/dispatcher.cc | 
| copy to mojo/edk/system/dispatcher.cc | 
| index ad362fe5eacd01807a1cc3569355fff19c5ce74e..d80c9d5330499c639d5327d300bb4959467471ae 100644 | 
| --- a/third_party/mojo/src/mojo/edk/system/dispatcher.cc | 
| +++ b/mojo/edk/system/dispatcher.cc | 
| @@ -26,18 +26,24 @@ DispatcherTransport DispatcherTryStartTransport(Dispatcher* dispatcher) { | 
|  | 
| // Dispatcher ------------------------------------------------------------------ | 
|  | 
| -// TODO(vtl): The thread-safety analyzer isn't smart enough to deal with the | 
| -// fact that we give up if |TryLock()| fails. | 
| // static | 
| DispatcherTransport Dispatcher::HandleTableAccess::TryStartTransport( | 
| -    Dispatcher* dispatcher) MOJO_NO_THREAD_SAFETY_ANALYSIS { | 
| +    Dispatcher* dispatcher) { | 
| DCHECK(dispatcher); | 
|  | 
| -  if (!dispatcher->mutex_.TryLock()) | 
| -    return DispatcherTransport(); | 
| +  // if (!dispatcher->lock_.Try()) | 
| +  //   return DispatcherTransport(); | 
| +  // Our dispatcher implemetnations hop to IO thread on initialization, so it's | 
| +  // valid that while their raw channel os being initialized on IO thread, the | 
| +  // dispatcher is being sent. We handle this by just acquiring the lock. | 
| + | 
| +  // See comment in header for why we need this. | 
| +  dispatcher->TransportStarted(); | 
| + | 
| +  dispatcher->lock_.Acquire(); | 
|  | 
| // We shouldn't race with things that close dispatchers, since closing can | 
| -  // only take place either under |handle_table_mutex_| or when the handle is | 
| +  // only take place either under |handle_table_lock_| or when the handle is | 
| // marked as busy. | 
| DCHECK(!dispatcher->is_closed_); | 
|  | 
| @@ -47,28 +53,25 @@ DispatcherTransport Dispatcher::HandleTableAccess::TryStartTransport( | 
| // static | 
| void Dispatcher::TransportDataAccess::StartSerialize( | 
| Dispatcher* dispatcher, | 
| -    Channel* channel, | 
| size_t* max_size, | 
| size_t* max_platform_handles) { | 
| DCHECK(dispatcher); | 
| -  dispatcher->StartSerialize(channel, max_size, max_platform_handles); | 
| +  dispatcher->StartSerialize(max_size, max_platform_handles); | 
| } | 
|  | 
| // static | 
| bool Dispatcher::TransportDataAccess::EndSerializeAndClose( | 
| Dispatcher* dispatcher, | 
| -    Channel* channel, | 
| void* destination, | 
| size_t* actual_size, | 
| embedder::PlatformHandleVector* platform_handles) { | 
| DCHECK(dispatcher); | 
| -  return dispatcher->EndSerializeAndClose(channel, destination, actual_size, | 
| +  return dispatcher->EndSerializeAndClose(destination, actual_size, | 
| platform_handles); | 
| } | 
|  | 
| // static | 
| scoped_refptr<Dispatcher> Dispatcher::TransportDataAccess::Deserialize( | 
| -    Channel* channel, | 
| int32_t type, | 
| const void* source, | 
| size_t size, | 
| @@ -78,27 +81,29 @@ scoped_refptr<Dispatcher> Dispatcher::TransportDataAccess::Deserialize( | 
| DVLOG(2) << "Deserializing invalid handle"; | 
| return nullptr; | 
| case Type::MESSAGE_PIPE: | 
| -      return scoped_refptr<Dispatcher>( | 
| -          MessagePipeDispatcher::Deserialize(channel, source, size)); | 
| +      return scoped_refptr<Dispatcher>(MessagePipeDispatcher::Deserialize( | 
| +          source, size, platform_handles)); | 
| case Type::DATA_PIPE_PRODUCER: | 
| return scoped_refptr<Dispatcher>( | 
| -          DataPipeProducerDispatcher::Deserialize(channel, source, size)); | 
| +          DataPipeProducerDispatcher::Deserialize( | 
| +              source, size, platform_handles)); | 
| case Type::DATA_PIPE_CONSUMER: | 
| return scoped_refptr<Dispatcher>( | 
| -          DataPipeConsumerDispatcher::Deserialize(channel, source, size)); | 
| +          DataPipeConsumerDispatcher::Deserialize( | 
| +              source, size, platform_handles)); | 
| case Type::SHARED_BUFFER: | 
| return scoped_refptr<Dispatcher>(SharedBufferDispatcher::Deserialize( | 
| -          channel, source, size, platform_handles)); | 
| +          source, size, platform_handles)); | 
| case Type::PLATFORM_HANDLE: | 
| return scoped_refptr<Dispatcher>(PlatformHandleDispatcher::Deserialize( | 
| -          channel, source, size, platform_handles)); | 
| +          source, size, platform_handles)); | 
| } | 
| LOG(WARNING) << "Unknown dispatcher type " << type; | 
| return nullptr; | 
| } | 
|  | 
| MojoResult Dispatcher::Close() { | 
| -  MutexLocker locker(&mutex_); | 
| +  base::AutoLock locker(lock_); | 
| if (is_closed_) | 
| return MOJO_RESULT_INVALID_ARGUMENT; | 
|  | 
| @@ -115,7 +120,7 @@ MojoResult Dispatcher::WriteMessage( | 
| (transports->size() > 0 && | 
| transports->size() < GetConfiguration().max_message_num_handles)); | 
|  | 
| -  MutexLocker locker(&mutex_); | 
| +  base::AutoLock locker(lock_); | 
| if (is_closed_) | 
| return MOJO_RESULT_INVALID_ARGUMENT; | 
|  | 
| @@ -130,7 +135,7 @@ MojoResult Dispatcher::ReadMessage(UserPointer<void> bytes, | 
| DCHECK(!num_dispatchers || *num_dispatchers == 0 || | 
| (dispatchers && dispatchers->empty())); | 
|  | 
| -  MutexLocker locker(&mutex_); | 
| +  base::AutoLock locker(lock_); | 
| if (is_closed_) | 
| return MOJO_RESULT_INVALID_ARGUMENT; | 
|  | 
| @@ -141,7 +146,7 @@ MojoResult Dispatcher::ReadMessage(UserPointer<void> bytes, | 
| MojoResult Dispatcher::WriteData(UserPointer<const void> elements, | 
| UserPointer<uint32_t> num_bytes, | 
| MojoWriteDataFlags flags) { | 
| -  MutexLocker locker(&mutex_); | 
| +  base::AutoLock locker(lock_); | 
| if (is_closed_) | 
| return MOJO_RESULT_INVALID_ARGUMENT; | 
|  | 
| @@ -151,7 +156,7 @@ MojoResult Dispatcher::WriteData(UserPointer<const void> elements, | 
| MojoResult Dispatcher::BeginWriteData(UserPointer<void*> buffer, | 
| UserPointer<uint32_t> buffer_num_bytes, | 
| MojoWriteDataFlags flags) { | 
| -  MutexLocker locker(&mutex_); | 
| +  base::AutoLock locker(lock_); | 
| if (is_closed_) | 
| return MOJO_RESULT_INVALID_ARGUMENT; | 
|  | 
| @@ -159,7 +164,7 @@ MojoResult Dispatcher::BeginWriteData(UserPointer<void*> buffer, | 
| } | 
|  | 
| MojoResult Dispatcher::EndWriteData(uint32_t num_bytes_written) { | 
| -  MutexLocker locker(&mutex_); | 
| +  base::AutoLock locker(lock_); | 
| if (is_closed_) | 
| return MOJO_RESULT_INVALID_ARGUMENT; | 
|  | 
| @@ -169,7 +174,7 @@ MojoResult Dispatcher::EndWriteData(uint32_t num_bytes_written) { | 
| MojoResult Dispatcher::ReadData(UserPointer<void> elements, | 
| UserPointer<uint32_t> num_bytes, | 
| MojoReadDataFlags flags) { | 
| -  MutexLocker locker(&mutex_); | 
| +  base::AutoLock locker(lock_); | 
| if (is_closed_) | 
| return MOJO_RESULT_INVALID_ARGUMENT; | 
|  | 
| @@ -179,7 +184,7 @@ MojoResult Dispatcher::ReadData(UserPointer<void> elements, | 
| MojoResult Dispatcher::BeginReadData(UserPointer<const void*> buffer, | 
| UserPointer<uint32_t> buffer_num_bytes, | 
| MojoReadDataFlags flags) { | 
| -  MutexLocker locker(&mutex_); | 
| +  base::AutoLock locker(lock_); | 
| if (is_closed_) | 
| return MOJO_RESULT_INVALID_ARGUMENT; | 
|  | 
| @@ -187,7 +192,7 @@ MojoResult Dispatcher::BeginReadData(UserPointer<const void*> buffer, | 
| } | 
|  | 
| MojoResult Dispatcher::EndReadData(uint32_t num_bytes_read) { | 
| -  MutexLocker locker(&mutex_); | 
| +  base::AutoLock locker(lock_); | 
| if (is_closed_) | 
| return MOJO_RESULT_INVALID_ARGUMENT; | 
|  | 
| @@ -197,7 +202,7 @@ MojoResult Dispatcher::EndReadData(uint32_t num_bytes_read) { | 
| MojoResult Dispatcher::DuplicateBufferHandle( | 
| UserPointer<const MojoDuplicateBufferHandleOptions> options, | 
| scoped_refptr<Dispatcher>* new_dispatcher) { | 
| -  MutexLocker locker(&mutex_); | 
| +  base::AutoLock locker(lock_); | 
| if (is_closed_) | 
| return MOJO_RESULT_INVALID_ARGUMENT; | 
|  | 
| @@ -209,7 +214,7 @@ MojoResult Dispatcher::MapBuffer( | 
| uint64_t num_bytes, | 
| MojoMapBufferFlags flags, | 
| scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) { | 
| -  MutexLocker locker(&mutex_); | 
| +  base::AutoLock locker(lock_); | 
| if (is_closed_) | 
| return MOJO_RESULT_INVALID_ARGUMENT; | 
|  | 
| @@ -217,7 +222,7 @@ MojoResult Dispatcher::MapBuffer( | 
| } | 
|  | 
| HandleSignalsState Dispatcher::GetHandleSignalsState() const { | 
| -  MutexLocker locker(&mutex_); | 
| +  base::AutoLock locker(lock_); | 
| if (is_closed_) | 
| return HandleSignalsState(); | 
|  | 
| @@ -228,7 +233,7 @@ MojoResult Dispatcher::AddAwakable(Awakable* awakable, | 
| MojoHandleSignals signals, | 
| uint32_t context, | 
| HandleSignalsState* signals_state) { | 
| -  MutexLocker locker(&mutex_); | 
| +  base::AutoLock locker(lock_); | 
| if (is_closed_) { | 
| if (signals_state) | 
| *signals_state = HandleSignalsState(); | 
| @@ -240,7 +245,7 @@ MojoResult Dispatcher::AddAwakable(Awakable* awakable, | 
|  | 
| void Dispatcher::RemoveAwakable(Awakable* awakable, | 
| HandleSignalsState* handle_signals_state) { | 
| -  MutexLocker locker(&mutex_); | 
| +  base::AutoLock locker(lock_); | 
| if (is_closed_) { | 
| if (handle_signals_state) | 
| *handle_signals_state = HandleSignalsState(); | 
| @@ -259,14 +264,14 @@ Dispatcher::~Dispatcher() { | 
| } | 
|  | 
| void Dispatcher::CancelAllAwakablesNoLock() { | 
| -  mutex_.AssertHeld(); | 
| +  lock_.AssertAcquired(); | 
| DCHECK(is_closed_); | 
| // By default, waiting isn't supported. Only dispatchers that can be waited on | 
| // will do something nontrivial. | 
| } | 
|  | 
| void Dispatcher::CloseImplNoLock() { | 
| -  mutex_.AssertHeld(); | 
| +  lock_.AssertAcquired(); | 
| DCHECK(is_closed_); | 
| // This may not need to do anything. Dispatchers should override this to do | 
| // any actual close-time cleanup necessary. | 
| @@ -277,7 +282,7 @@ MojoResult Dispatcher::WriteMessageImplNoLock( | 
| uint32_t /*num_bytes*/, | 
| std::vector<DispatcherTransport>* /*transports*/, | 
| MojoWriteMessageFlags /*flags*/) { | 
| -  mutex_.AssertHeld(); | 
| +  lock_.AssertAcquired(); | 
| DCHECK(!is_closed_); | 
| // By default, not supported. Only needed for message pipe dispatchers. | 
| return MOJO_RESULT_INVALID_ARGUMENT; | 
| @@ -289,7 +294,7 @@ MojoResult Dispatcher::ReadMessageImplNoLock( | 
| DispatcherVector* /*dispatchers*/, | 
| uint32_t* /*num_dispatchers*/, | 
| MojoReadMessageFlags /*flags*/) { | 
| -  mutex_.AssertHeld(); | 
| +  lock_.AssertAcquired(); | 
| DCHECK(!is_closed_); | 
| // By default, not supported. Only needed for message pipe dispatchers. | 
| return MOJO_RESULT_INVALID_ARGUMENT; | 
| @@ -298,7 +303,7 @@ MojoResult Dispatcher::ReadMessageImplNoLock( | 
| MojoResult Dispatcher::WriteDataImplNoLock(UserPointer<const void> /*elements*/, | 
| UserPointer<uint32_t> /*num_bytes*/, | 
| MojoWriteDataFlags /*flags*/) { | 
| -  mutex_.AssertHeld(); | 
| +  lock_.AssertAcquired(); | 
| DCHECK(!is_closed_); | 
| // By default, not supported. Only needed for data pipe dispatchers. | 
| return MOJO_RESULT_INVALID_ARGUMENT; | 
| @@ -308,14 +313,14 @@ MojoResult Dispatcher::BeginWriteDataImplNoLock( | 
| UserPointer<void*> /*buffer*/, | 
| UserPointer<uint32_t> /*buffer_num_bytes*/, | 
| MojoWriteDataFlags /*flags*/) { | 
| -  mutex_.AssertHeld(); | 
| +  lock_.AssertAcquired(); | 
| DCHECK(!is_closed_); | 
| // By default, not supported. Only needed for data pipe dispatchers. | 
| return MOJO_RESULT_INVALID_ARGUMENT; | 
| } | 
|  | 
| MojoResult Dispatcher::EndWriteDataImplNoLock(uint32_t /*num_bytes_written*/) { | 
| -  mutex_.AssertHeld(); | 
| +  lock_.AssertAcquired(); | 
| DCHECK(!is_closed_); | 
| // By default, not supported. Only needed for data pipe dispatchers. | 
| return MOJO_RESULT_INVALID_ARGUMENT; | 
| @@ -324,7 +329,7 @@ MojoResult Dispatcher::EndWriteDataImplNoLock(uint32_t /*num_bytes_written*/) { | 
| MojoResult Dispatcher::ReadDataImplNoLock(UserPointer<void> /*elements*/, | 
| UserPointer<uint32_t> /*num_bytes*/, | 
| MojoReadDataFlags /*flags*/) { | 
| -  mutex_.AssertHeld(); | 
| +  lock_.AssertAcquired(); | 
| DCHECK(!is_closed_); | 
| // By default, not supported. Only needed for data pipe dispatchers. | 
| return MOJO_RESULT_INVALID_ARGUMENT; | 
| @@ -334,14 +339,14 @@ MojoResult Dispatcher::BeginReadDataImplNoLock( | 
| UserPointer<const void*> /*buffer*/, | 
| UserPointer<uint32_t> /*buffer_num_bytes*/, | 
| MojoReadDataFlags /*flags*/) { | 
| -  mutex_.AssertHeld(); | 
| +  lock_.AssertAcquired(); | 
| DCHECK(!is_closed_); | 
| // By default, not supported. Only needed for data pipe dispatchers. | 
| return MOJO_RESULT_INVALID_ARGUMENT; | 
| } | 
|  | 
| MojoResult Dispatcher::EndReadDataImplNoLock(uint32_t /*num_bytes_read*/) { | 
| -  mutex_.AssertHeld(); | 
| +  lock_.AssertAcquired(); | 
| DCHECK(!is_closed_); | 
| // By default, not supported. Only needed for data pipe dispatchers. | 
| return MOJO_RESULT_INVALID_ARGUMENT; | 
| @@ -350,7 +355,7 @@ MojoResult Dispatcher::EndReadDataImplNoLock(uint32_t /*num_bytes_read*/) { | 
| MojoResult Dispatcher::DuplicateBufferHandleImplNoLock( | 
| UserPointer<const MojoDuplicateBufferHandleOptions> /*options*/, | 
| scoped_refptr<Dispatcher>* /*new_dispatcher*/) { | 
| -  mutex_.AssertHeld(); | 
| +  lock_.AssertAcquired(); | 
| DCHECK(!is_closed_); | 
| // By default, not supported. Only needed for buffer dispatchers. | 
| return MOJO_RESULT_INVALID_ARGUMENT; | 
| @@ -361,14 +366,14 @@ MojoResult Dispatcher::MapBufferImplNoLock( | 
| uint64_t /*num_bytes*/, | 
| MojoMapBufferFlags /*flags*/, | 
| scoped_ptr<embedder::PlatformSharedBufferMapping>* /*mapping*/) { | 
| -  mutex_.AssertHeld(); | 
| +  lock_.AssertAcquired(); | 
| DCHECK(!is_closed_); | 
| // By default, not supported. Only needed for buffer dispatchers. | 
| return MOJO_RESULT_INVALID_ARGUMENT; | 
| } | 
|  | 
| HandleSignalsState Dispatcher::GetHandleSignalsStateImplNoLock() const { | 
| -  mutex_.AssertHeld(); | 
| +  lock_.AssertAcquired(); | 
| DCHECK(!is_closed_); | 
| // By default, waiting isn't supported. Only dispatchers that can be waited on | 
| // will do something nontrivial. | 
| @@ -380,7 +385,7 @@ MojoResult Dispatcher::AddAwakableImplNoLock( | 
| MojoHandleSignals /*signals*/, | 
| uint32_t /*context*/, | 
| HandleSignalsState* signals_state) { | 
| -  mutex_.AssertHeld(); | 
| +  lock_.AssertAcquired(); | 
| DCHECK(!is_closed_); | 
| // By default, waiting isn't supported. Only dispatchers that can be waited on | 
| // will do something nontrivial. | 
| @@ -391,7 +396,7 @@ MojoResult Dispatcher::AddAwakableImplNoLock( | 
|  | 
| void Dispatcher::RemoveAwakableImplNoLock(Awakable* /*awakable*/, | 
| HandleSignalsState* signals_state) { | 
| -  mutex_.AssertHeld(); | 
| +  lock_.AssertAcquired(); | 
| DCHECK(!is_closed_); | 
| // By default, waiting isn't supported. Only dispatchers that can be waited on | 
| // will do something nontrivial. | 
| @@ -399,8 +404,7 @@ void Dispatcher::RemoveAwakableImplNoLock(Awakable* /*awakable*/, | 
| *signals_state = HandleSignalsState(); | 
| } | 
|  | 
| -void Dispatcher::StartSerializeImplNoLock(Channel* /*channel*/, | 
| -                                          size_t* max_size, | 
| +void Dispatcher::StartSerializeImplNoLock(size_t* max_size, | 
| size_t* max_platform_handles) { | 
| DCHECK(HasOneRef());  // Only one ref => no need to take the lock. | 
| DCHECK(!is_closed_); | 
| @@ -409,7 +413,6 @@ void Dispatcher::StartSerializeImplNoLock(Channel* /*channel*/, | 
| } | 
|  | 
| bool Dispatcher::EndSerializeAndCloseImplNoLock( | 
| -    Channel* /*channel*/, | 
| void* /*destination*/, | 
| size_t* /*actual_size*/, | 
| embedder::PlatformHandleVector* /*platform_handles*/) { | 
| @@ -421,7 +424,7 @@ bool Dispatcher::EndSerializeAndCloseImplNoLock( | 
| } | 
|  | 
| bool Dispatcher::IsBusyNoLock() const { | 
| -  mutex_.AssertHeld(); | 
| +  lock_.AssertAcquired(); | 
| DCHECK(!is_closed_); | 
| // Most dispatchers support only "atomic" operations, so they are never busy | 
| // (in this sense). | 
| @@ -429,7 +432,7 @@ bool Dispatcher::IsBusyNoLock() const { | 
| } | 
|  | 
| void Dispatcher::CloseNoLock() { | 
| -  mutex_.AssertHeld(); | 
| +  lock_.AssertAcquired(); | 
| DCHECK(!is_closed_); | 
|  | 
| is_closed_ = true; | 
| @@ -439,7 +442,7 @@ void Dispatcher::CloseNoLock() { | 
|  | 
| scoped_refptr<Dispatcher> | 
| Dispatcher::CreateEquivalentDispatcherAndCloseNoLock() { | 
| -  mutex_.AssertHeld(); | 
| +  lock_.AssertAcquired(); | 
| DCHECK(!is_closed_); | 
|  | 
| is_closed_ = true; | 
| @@ -447,25 +450,24 @@ Dispatcher::CreateEquivalentDispatcherAndCloseNoLock() { | 
| return CreateEquivalentDispatcherAndCloseImplNoLock(); | 
| } | 
|  | 
| -void Dispatcher::StartSerialize(Channel* channel, | 
| -                                size_t* max_size, | 
| +void Dispatcher::StartSerialize(size_t* max_size, | 
| size_t* max_platform_handles) { | 
| -  DCHECK(channel); | 
| DCHECK(max_size); | 
| DCHECK(max_platform_handles); | 
| -  DCHECK(HasOneRef());  // Only one ref => no need to take the lock. | 
| +  //DCHECK(HasOneRef());  // Only one ref => no need to take the lock. | 
| +  // jam: document exactly when this happens: i.e. when startserialize is called | 
| +  // on main thread. | 
| DCHECK(!is_closed_); | 
| -  StartSerializeImplNoLock(channel, max_size, max_platform_handles); | 
| +  StartSerializeImplNoLock(max_size, max_platform_handles); | 
| } | 
|  | 
| bool Dispatcher::EndSerializeAndClose( | 
| -    Channel* channel, | 
| void* destination, | 
| size_t* actual_size, | 
| embedder::PlatformHandleVector* platform_handles) { | 
| -  DCHECK(channel); | 
| DCHECK(actual_size); | 
| -  DCHECK(HasOneRef());  // Only one ref => no need to take the lock. | 
| +  //DCHECK(HasOneRef());  // Only one ref => no need to take the lock. | 
| +  // jam: same as startserialize | 
| DCHECK(!is_closed_); | 
|  | 
| // Like other |...Close()| methods, we mark ourselves as closed before calling | 
| @@ -477,10 +479,10 @@ bool Dispatcher::EndSerializeAndClose( | 
| // See the comment above |EndSerializeAndCloseImplNoLock()|. In brief: Locking | 
| // isn't actually needed, but we need to satisfy assertions (which we don't | 
| // want to remove or weaken). | 
| -  MutexLocker locker(&mutex_); | 
| +  base::AutoLock locker(lock_); | 
| #endif | 
|  | 
| -  return EndSerializeAndCloseImplNoLock(channel, destination, actual_size, | 
| +  return EndSerializeAndCloseImplNoLock(destination, actual_size, | 
| platform_handles); | 
| } | 
|  | 
| @@ -488,7 +490,10 @@ bool Dispatcher::EndSerializeAndClose( | 
|  | 
| void DispatcherTransport::End() { | 
| DCHECK(dispatcher_); | 
| -  dispatcher_->mutex_.Unlock(); | 
| +  dispatcher_->lock_.Release(); | 
| + | 
| +  dispatcher_->TransportEnded(); | 
| + | 
| dispatcher_ = nullptr; | 
| } | 
|  | 
|  |