| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "mojo/edk/system/dispatcher.h" | 5 #include "mojo/edk/system/dispatcher.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "mojo/edk/system/configuration.h" | 8 #include "mojo/edk/system/configuration.h" |
| 9 #include "mojo/edk/system/data_pipe_consumer_dispatcher.h" | 9 #include "mojo/edk/system/data_pipe_consumer_dispatcher.h" |
| 10 #include "mojo/edk/system/data_pipe_producer_dispatcher.h" | 10 #include "mojo/edk/system/data_pipe_producer_dispatcher.h" |
| 11 #include "mojo/edk/system/message_pipe_dispatcher.h" | 11 #include "mojo/edk/system/message_pipe_dispatcher.h" |
| 12 #include "mojo/edk/system/platform_handle_dispatcher.h" | 12 #include "mojo/edk/system/platform_handle_dispatcher.h" |
| 13 #include "mojo/edk/system/shared_buffer_dispatcher.h" | 13 #include "mojo/edk/system/shared_buffer_dispatcher.h" |
| 14 | 14 |
| 15 namespace mojo { | 15 namespace mojo { |
| 16 namespace system { | 16 namespace system { |
| 17 | 17 |
| 18 namespace test { | 18 namespace test { |
| 19 | 19 |
| 20 // TODO(vtl): Maybe this should be defined in a test-only file instead. | 20 // TODO(vtl): Maybe this should be defined in a test-only file instead. |
| 21 DispatcherTransport DispatcherTryStartTransport(Dispatcher* dispatcher) { | 21 DispatcherTransport DispatcherTryStartTransport(Dispatcher* dispatcher) { |
| 22 return Dispatcher::HandleTableAccess::TryStartTransport(dispatcher); | 22 return Dispatcher::HandleTableAccess::TryStartTransport(dispatcher); |
| 23 } | 23 } |
| 24 | 24 |
| 25 } // namespace test | 25 } // namespace test |
| 26 | 26 |
| 27 // Dispatcher ------------------------------------------------------------------ | 27 // Dispatcher ------------------------------------------------------------------ |
| 28 | 28 |
| 29 // TODO(vtl): The thread-safety analyzer isn't smart enough to deal with the | |
| 30 // fact that we give up if |TryLock()| fails. | |
| 31 // static | 29 // static |
| 32 DispatcherTransport Dispatcher::HandleTableAccess::TryStartTransport( | 30 DispatcherTransport Dispatcher::HandleTableAccess::TryStartTransport( |
| 33 Dispatcher* dispatcher) MOJO_NO_THREAD_SAFETY_ANALYSIS { | 31 Dispatcher* dispatcher) { |
| 34 DCHECK(dispatcher); | 32 DCHECK(dispatcher); |
| 35 | 33 |
| 36 if (!dispatcher->mutex_.TryLock()) | 34 // if (!dispatcher->lock_.Try()) |
| 37 return DispatcherTransport(); | 35 // return DispatcherTransport(); |
| 36 // Our dispatcher implemetnations hop to IO thread on initialization, so it's |
| 37 // valid that while their raw channel os being initialized on IO thread, the |
| 38 // dispatcher is being sent. We handle this by just acquiring the lock. |
| 39 |
| 40 // See comment in header for why we need this. |
| 41 dispatcher->TransportStarted(); |
| 42 |
| 43 dispatcher->lock_.Acquire(); |
| 38 | 44 |
| 39 // We shouldn't race with things that close dispatchers, since closing can | 45 // We shouldn't race with things that close dispatchers, since closing can |
| 40 // only take place either under |handle_table_mutex_| or when the handle is | 46 // only take place either under |handle_table_lock_| or when the handle is |
| 41 // marked as busy. | 47 // marked as busy. |
| 42 DCHECK(!dispatcher->is_closed_); | 48 DCHECK(!dispatcher->is_closed_); |
| 43 | 49 |
| 44 return DispatcherTransport(dispatcher); | 50 return DispatcherTransport(dispatcher); |
| 45 } | 51 } |
| 46 | 52 |
| 47 // static | 53 // static |
| 48 void Dispatcher::TransportDataAccess::StartSerialize( | 54 void Dispatcher::TransportDataAccess::StartSerialize( |
| 49 Dispatcher* dispatcher, | 55 Dispatcher* dispatcher, |
| 50 Channel* channel, | |
| 51 size_t* max_size, | 56 size_t* max_size, |
| 52 size_t* max_platform_handles) { | 57 size_t* max_platform_handles) { |
| 53 DCHECK(dispatcher); | 58 DCHECK(dispatcher); |
| 54 dispatcher->StartSerialize(channel, max_size, max_platform_handles); | 59 dispatcher->StartSerialize(max_size, max_platform_handles); |
| 55 } | 60 } |
| 56 | 61 |
| 57 // static | 62 // static |
| 58 bool Dispatcher::TransportDataAccess::EndSerializeAndClose( | 63 bool Dispatcher::TransportDataAccess::EndSerializeAndClose( |
| 59 Dispatcher* dispatcher, | 64 Dispatcher* dispatcher, |
| 60 Channel* channel, | |
| 61 void* destination, | 65 void* destination, |
| 62 size_t* actual_size, | 66 size_t* actual_size, |
| 63 embedder::PlatformHandleVector* platform_handles) { | 67 embedder::PlatformHandleVector* platform_handles) { |
| 64 DCHECK(dispatcher); | 68 DCHECK(dispatcher); |
| 65 return dispatcher->EndSerializeAndClose(channel, destination, actual_size, | 69 return dispatcher->EndSerializeAndClose(destination, actual_size, |
| 66 platform_handles); | 70 platform_handles); |
| 67 } | 71 } |
| 68 | 72 |
| 69 // static | 73 // static |
| 70 scoped_refptr<Dispatcher> Dispatcher::TransportDataAccess::Deserialize( | 74 scoped_refptr<Dispatcher> Dispatcher::TransportDataAccess::Deserialize( |
| 71 Channel* channel, | |
| 72 int32_t type, | 75 int32_t type, |
| 73 const void* source, | 76 const void* source, |
| 74 size_t size, | 77 size_t size, |
| 75 embedder::PlatformHandleVector* platform_handles) { | 78 embedder::PlatformHandleVector* platform_handles) { |
| 76 switch (static_cast<Dispatcher::Type>(type)) { | 79 switch (static_cast<Dispatcher::Type>(type)) { |
| 77 case Type::UNKNOWN: | 80 case Type::UNKNOWN: |
| 78 DVLOG(2) << "Deserializing invalid handle"; | 81 DVLOG(2) << "Deserializing invalid handle"; |
| 79 return nullptr; | 82 return nullptr; |
| 80 case Type::MESSAGE_PIPE: | 83 case Type::MESSAGE_PIPE: |
| 81 return scoped_refptr<Dispatcher>( | 84 return scoped_refptr<Dispatcher>(MessagePipeDispatcher::Deserialize( |
| 82 MessagePipeDispatcher::Deserialize(channel, source, size)); | 85 source, size, platform_handles)); |
| 83 case Type::DATA_PIPE_PRODUCER: | 86 case Type::DATA_PIPE_PRODUCER: |
| 84 return scoped_refptr<Dispatcher>( | 87 return scoped_refptr<Dispatcher>( |
| 85 DataPipeProducerDispatcher::Deserialize(channel, source, size)); | 88 DataPipeProducerDispatcher::Deserialize( |
| 89 source, size, platform_handles)); |
| 86 case Type::DATA_PIPE_CONSUMER: | 90 case Type::DATA_PIPE_CONSUMER: |
| 87 return scoped_refptr<Dispatcher>( | 91 return scoped_refptr<Dispatcher>( |
| 88 DataPipeConsumerDispatcher::Deserialize(channel, source, size)); | 92 DataPipeConsumerDispatcher::Deserialize( |
| 93 source, size, platform_handles)); |
| 89 case Type::SHARED_BUFFER: | 94 case Type::SHARED_BUFFER: |
| 90 return scoped_refptr<Dispatcher>(SharedBufferDispatcher::Deserialize( | 95 return scoped_refptr<Dispatcher>(SharedBufferDispatcher::Deserialize( |
| 91 channel, source, size, platform_handles)); | 96 source, size, platform_handles)); |
| 92 case Type::PLATFORM_HANDLE: | 97 case Type::PLATFORM_HANDLE: |
| 93 return scoped_refptr<Dispatcher>(PlatformHandleDispatcher::Deserialize( | 98 return scoped_refptr<Dispatcher>(PlatformHandleDispatcher::Deserialize( |
| 94 channel, source, size, platform_handles)); | 99 source, size, platform_handles)); |
| 95 } | 100 } |
| 96 LOG(WARNING) << "Unknown dispatcher type " << type; | 101 LOG(WARNING) << "Unknown dispatcher type " << type; |
| 97 return nullptr; | 102 return nullptr; |
| 98 } | 103 } |
| 99 | 104 |
| 100 MojoResult Dispatcher::Close() { | 105 MojoResult Dispatcher::Close() { |
| 101 MutexLocker locker(&mutex_); | 106 base::AutoLock locker(lock_); |
| 102 if (is_closed_) | 107 if (is_closed_) |
| 103 return MOJO_RESULT_INVALID_ARGUMENT; | 108 return MOJO_RESULT_INVALID_ARGUMENT; |
| 104 | 109 |
| 105 CloseNoLock(); | 110 CloseNoLock(); |
| 106 return MOJO_RESULT_OK; | 111 return MOJO_RESULT_OK; |
| 107 } | 112 } |
| 108 | 113 |
| 109 MojoResult Dispatcher::WriteMessage( | 114 MojoResult Dispatcher::WriteMessage( |
| 110 UserPointer<const void> bytes, | 115 UserPointer<const void> bytes, |
| 111 uint32_t num_bytes, | 116 uint32_t num_bytes, |
| 112 std::vector<DispatcherTransport>* transports, | 117 std::vector<DispatcherTransport>* transports, |
| 113 MojoWriteMessageFlags flags) { | 118 MojoWriteMessageFlags flags) { |
| 114 DCHECK(!transports || | 119 DCHECK(!transports || |
| 115 (transports->size() > 0 && | 120 (transports->size() > 0 && |
| 116 transports->size() < GetConfiguration().max_message_num_handles)); | 121 transports->size() < GetConfiguration().max_message_num_handles)); |
| 117 | 122 |
| 118 MutexLocker locker(&mutex_); | 123 base::AutoLock locker(lock_); |
| 119 if (is_closed_) | 124 if (is_closed_) |
| 120 return MOJO_RESULT_INVALID_ARGUMENT; | 125 return MOJO_RESULT_INVALID_ARGUMENT; |
| 121 | 126 |
| 122 return WriteMessageImplNoLock(bytes, num_bytes, transports, flags); | 127 return WriteMessageImplNoLock(bytes, num_bytes, transports, flags); |
| 123 } | 128 } |
| 124 | 129 |
| 125 MojoResult Dispatcher::ReadMessage(UserPointer<void> bytes, | 130 MojoResult Dispatcher::ReadMessage(UserPointer<void> bytes, |
| 126 UserPointer<uint32_t> num_bytes, | 131 UserPointer<uint32_t> num_bytes, |
| 127 DispatcherVector* dispatchers, | 132 DispatcherVector* dispatchers, |
| 128 uint32_t* num_dispatchers, | 133 uint32_t* num_dispatchers, |
| 129 MojoReadMessageFlags flags) { | 134 MojoReadMessageFlags flags) { |
| 130 DCHECK(!num_dispatchers || *num_dispatchers == 0 || | 135 DCHECK(!num_dispatchers || *num_dispatchers == 0 || |
| 131 (dispatchers && dispatchers->empty())); | 136 (dispatchers && dispatchers->empty())); |
| 132 | 137 |
| 133 MutexLocker locker(&mutex_); | 138 base::AutoLock locker(lock_); |
| 134 if (is_closed_) | 139 if (is_closed_) |
| 135 return MOJO_RESULT_INVALID_ARGUMENT; | 140 return MOJO_RESULT_INVALID_ARGUMENT; |
| 136 | 141 |
| 137 return ReadMessageImplNoLock(bytes, num_bytes, dispatchers, num_dispatchers, | 142 return ReadMessageImplNoLock(bytes, num_bytes, dispatchers, num_dispatchers, |
| 138 flags); | 143 flags); |
| 139 } | 144 } |
| 140 | 145 |
| 141 MojoResult Dispatcher::WriteData(UserPointer<const void> elements, | 146 MojoResult Dispatcher::WriteData(UserPointer<const void> elements, |
| 142 UserPointer<uint32_t> num_bytes, | 147 UserPointer<uint32_t> num_bytes, |
| 143 MojoWriteDataFlags flags) { | 148 MojoWriteDataFlags flags) { |
| 144 MutexLocker locker(&mutex_); | 149 base::AutoLock locker(lock_); |
| 145 if (is_closed_) | 150 if (is_closed_) |
| 146 return MOJO_RESULT_INVALID_ARGUMENT; | 151 return MOJO_RESULT_INVALID_ARGUMENT; |
| 147 | 152 |
| 148 return WriteDataImplNoLock(elements, num_bytes, flags); | 153 return WriteDataImplNoLock(elements, num_bytes, flags); |
| 149 } | 154 } |
| 150 | 155 |
| 151 MojoResult Dispatcher::BeginWriteData(UserPointer<void*> buffer, | 156 MojoResult Dispatcher::BeginWriteData(UserPointer<void*> buffer, |
| 152 UserPointer<uint32_t> buffer_num_bytes, | 157 UserPointer<uint32_t> buffer_num_bytes, |
| 153 MojoWriteDataFlags flags) { | 158 MojoWriteDataFlags flags) { |
| 154 MutexLocker locker(&mutex_); | 159 base::AutoLock locker(lock_); |
| 155 if (is_closed_) | 160 if (is_closed_) |
| 156 return MOJO_RESULT_INVALID_ARGUMENT; | 161 return MOJO_RESULT_INVALID_ARGUMENT; |
| 157 | 162 |
| 158 return BeginWriteDataImplNoLock(buffer, buffer_num_bytes, flags); | 163 return BeginWriteDataImplNoLock(buffer, buffer_num_bytes, flags); |
| 159 } | 164 } |
| 160 | 165 |
| 161 MojoResult Dispatcher::EndWriteData(uint32_t num_bytes_written) { | 166 MojoResult Dispatcher::EndWriteData(uint32_t num_bytes_written) { |
| 162 MutexLocker locker(&mutex_); | 167 base::AutoLock locker(lock_); |
| 163 if (is_closed_) | 168 if (is_closed_) |
| 164 return MOJO_RESULT_INVALID_ARGUMENT; | 169 return MOJO_RESULT_INVALID_ARGUMENT; |
| 165 | 170 |
| 166 return EndWriteDataImplNoLock(num_bytes_written); | 171 return EndWriteDataImplNoLock(num_bytes_written); |
| 167 } | 172 } |
| 168 | 173 |
| 169 MojoResult Dispatcher::ReadData(UserPointer<void> elements, | 174 MojoResult Dispatcher::ReadData(UserPointer<void> elements, |
| 170 UserPointer<uint32_t> num_bytes, | 175 UserPointer<uint32_t> num_bytes, |
| 171 MojoReadDataFlags flags) { | 176 MojoReadDataFlags flags) { |
| 172 MutexLocker locker(&mutex_); | 177 base::AutoLock locker(lock_); |
| 173 if (is_closed_) | 178 if (is_closed_) |
| 174 return MOJO_RESULT_INVALID_ARGUMENT; | 179 return MOJO_RESULT_INVALID_ARGUMENT; |
| 175 | 180 |
| 176 return ReadDataImplNoLock(elements, num_bytes, flags); | 181 return ReadDataImplNoLock(elements, num_bytes, flags); |
| 177 } | 182 } |
| 178 | 183 |
| 179 MojoResult Dispatcher::BeginReadData(UserPointer<const void*> buffer, | 184 MojoResult Dispatcher::BeginReadData(UserPointer<const void*> buffer, |
| 180 UserPointer<uint32_t> buffer_num_bytes, | 185 UserPointer<uint32_t> buffer_num_bytes, |
| 181 MojoReadDataFlags flags) { | 186 MojoReadDataFlags flags) { |
| 182 MutexLocker locker(&mutex_); | 187 base::AutoLock locker(lock_); |
| 183 if (is_closed_) | 188 if (is_closed_) |
| 184 return MOJO_RESULT_INVALID_ARGUMENT; | 189 return MOJO_RESULT_INVALID_ARGUMENT; |
| 185 | 190 |
| 186 return BeginReadDataImplNoLock(buffer, buffer_num_bytes, flags); | 191 return BeginReadDataImplNoLock(buffer, buffer_num_bytes, flags); |
| 187 } | 192 } |
| 188 | 193 |
| 189 MojoResult Dispatcher::EndReadData(uint32_t num_bytes_read) { | 194 MojoResult Dispatcher::EndReadData(uint32_t num_bytes_read) { |
| 190 MutexLocker locker(&mutex_); | 195 base::AutoLock locker(lock_); |
| 191 if (is_closed_) | 196 if (is_closed_) |
| 192 return MOJO_RESULT_INVALID_ARGUMENT; | 197 return MOJO_RESULT_INVALID_ARGUMENT; |
| 193 | 198 |
| 194 return EndReadDataImplNoLock(num_bytes_read); | 199 return EndReadDataImplNoLock(num_bytes_read); |
| 195 } | 200 } |
| 196 | 201 |
| 197 MojoResult Dispatcher::DuplicateBufferHandle( | 202 MojoResult Dispatcher::DuplicateBufferHandle( |
| 198 UserPointer<const MojoDuplicateBufferHandleOptions> options, | 203 UserPointer<const MojoDuplicateBufferHandleOptions> options, |
| 199 scoped_refptr<Dispatcher>* new_dispatcher) { | 204 scoped_refptr<Dispatcher>* new_dispatcher) { |
| 200 MutexLocker locker(&mutex_); | 205 base::AutoLock locker(lock_); |
| 201 if (is_closed_) | 206 if (is_closed_) |
| 202 return MOJO_RESULT_INVALID_ARGUMENT; | 207 return MOJO_RESULT_INVALID_ARGUMENT; |
| 203 | 208 |
| 204 return DuplicateBufferHandleImplNoLock(options, new_dispatcher); | 209 return DuplicateBufferHandleImplNoLock(options, new_dispatcher); |
| 205 } | 210 } |
| 206 | 211 |
| 207 MojoResult Dispatcher::MapBuffer( | 212 MojoResult Dispatcher::MapBuffer( |
| 208 uint64_t offset, | 213 uint64_t offset, |
| 209 uint64_t num_bytes, | 214 uint64_t num_bytes, |
| 210 MojoMapBufferFlags flags, | 215 MojoMapBufferFlags flags, |
| 211 scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) { | 216 scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) { |
| 212 MutexLocker locker(&mutex_); | 217 base::AutoLock locker(lock_); |
| 213 if (is_closed_) | 218 if (is_closed_) |
| 214 return MOJO_RESULT_INVALID_ARGUMENT; | 219 return MOJO_RESULT_INVALID_ARGUMENT; |
| 215 | 220 |
| 216 return MapBufferImplNoLock(offset, num_bytes, flags, mapping); | 221 return MapBufferImplNoLock(offset, num_bytes, flags, mapping); |
| 217 } | 222 } |
| 218 | 223 |
| 219 HandleSignalsState Dispatcher::GetHandleSignalsState() const { | 224 HandleSignalsState Dispatcher::GetHandleSignalsState() const { |
| 220 MutexLocker locker(&mutex_); | 225 base::AutoLock locker(lock_); |
| 221 if (is_closed_) | 226 if (is_closed_) |
| 222 return HandleSignalsState(); | 227 return HandleSignalsState(); |
| 223 | 228 |
| 224 return GetHandleSignalsStateImplNoLock(); | 229 return GetHandleSignalsStateImplNoLock(); |
| 225 } | 230 } |
| 226 | 231 |
| 227 MojoResult Dispatcher::AddAwakable(Awakable* awakable, | 232 MojoResult Dispatcher::AddAwakable(Awakable* awakable, |
| 228 MojoHandleSignals signals, | 233 MojoHandleSignals signals, |
| 229 uint32_t context, | 234 uint32_t context, |
| 230 HandleSignalsState* signals_state) { | 235 HandleSignalsState* signals_state) { |
| 231 MutexLocker locker(&mutex_); | 236 base::AutoLock locker(lock_); |
| 232 if (is_closed_) { | 237 if (is_closed_) { |
| 233 if (signals_state) | 238 if (signals_state) |
| 234 *signals_state = HandleSignalsState(); | 239 *signals_state = HandleSignalsState(); |
| 235 return MOJO_RESULT_INVALID_ARGUMENT; | 240 return MOJO_RESULT_INVALID_ARGUMENT; |
| 236 } | 241 } |
| 237 | 242 |
| 238 return AddAwakableImplNoLock(awakable, signals, context, signals_state); | 243 return AddAwakableImplNoLock(awakable, signals, context, signals_state); |
| 239 } | 244 } |
| 240 | 245 |
| 241 void Dispatcher::RemoveAwakable(Awakable* awakable, | 246 void Dispatcher::RemoveAwakable(Awakable* awakable, |
| 242 HandleSignalsState* handle_signals_state) { | 247 HandleSignalsState* handle_signals_state) { |
| 243 MutexLocker locker(&mutex_); | 248 base::AutoLock locker(lock_); |
| 244 if (is_closed_) { | 249 if (is_closed_) { |
| 245 if (handle_signals_state) | 250 if (handle_signals_state) |
| 246 *handle_signals_state = HandleSignalsState(); | 251 *handle_signals_state = HandleSignalsState(); |
| 247 return; | 252 return; |
| 248 } | 253 } |
| 249 | 254 |
| 250 RemoveAwakableImplNoLock(awakable, handle_signals_state); | 255 RemoveAwakableImplNoLock(awakable, handle_signals_state); |
| 251 } | 256 } |
| 252 | 257 |
| 253 Dispatcher::Dispatcher() : is_closed_(false) { | 258 Dispatcher::Dispatcher() : is_closed_(false) { |
| 254 } | 259 } |
| 255 | 260 |
| 256 Dispatcher::~Dispatcher() { | 261 Dispatcher::~Dispatcher() { |
| 257 // Make sure that |Close()| was called. | 262 // Make sure that |Close()| was called. |
| 258 DCHECK(is_closed_); | 263 DCHECK(is_closed_); |
| 259 } | 264 } |
| 260 | 265 |
| 261 void Dispatcher::CancelAllAwakablesNoLock() { | 266 void Dispatcher::CancelAllAwakablesNoLock() { |
| 262 mutex_.AssertHeld(); | 267 lock_.AssertAcquired(); |
| 263 DCHECK(is_closed_); | 268 DCHECK(is_closed_); |
| 264 // By default, waiting isn't supported. Only dispatchers that can be waited on | 269 // By default, waiting isn't supported. Only dispatchers that can be waited on |
| 265 // will do something nontrivial. | 270 // will do something nontrivial. |
| 266 } | 271 } |
| 267 | 272 |
| 268 void Dispatcher::CloseImplNoLock() { | 273 void Dispatcher::CloseImplNoLock() { |
| 269 mutex_.AssertHeld(); | 274 lock_.AssertAcquired(); |
| 270 DCHECK(is_closed_); | 275 DCHECK(is_closed_); |
| 271 // This may not need to do anything. Dispatchers should override this to do | 276 // This may not need to do anything. Dispatchers should override this to do |
| 272 // any actual close-time cleanup necessary. | 277 // any actual close-time cleanup necessary. |
| 273 } | 278 } |
| 274 | 279 |
| 275 MojoResult Dispatcher::WriteMessageImplNoLock( | 280 MojoResult Dispatcher::WriteMessageImplNoLock( |
| 276 UserPointer<const void> /*bytes*/, | 281 UserPointer<const void> /*bytes*/, |
| 277 uint32_t /*num_bytes*/, | 282 uint32_t /*num_bytes*/, |
| 278 std::vector<DispatcherTransport>* /*transports*/, | 283 std::vector<DispatcherTransport>* /*transports*/, |
| 279 MojoWriteMessageFlags /*flags*/) { | 284 MojoWriteMessageFlags /*flags*/) { |
| 280 mutex_.AssertHeld(); | 285 lock_.AssertAcquired(); |
| 281 DCHECK(!is_closed_); | 286 DCHECK(!is_closed_); |
| 282 // By default, not supported. Only needed for message pipe dispatchers. | 287 // By default, not supported. Only needed for message pipe dispatchers. |
| 283 return MOJO_RESULT_INVALID_ARGUMENT; | 288 return MOJO_RESULT_INVALID_ARGUMENT; |
| 284 } | 289 } |
| 285 | 290 |
| 286 MojoResult Dispatcher::ReadMessageImplNoLock( | 291 MojoResult Dispatcher::ReadMessageImplNoLock( |
| 287 UserPointer<void> /*bytes*/, | 292 UserPointer<void> /*bytes*/, |
| 288 UserPointer<uint32_t> /*num_bytes*/, | 293 UserPointer<uint32_t> /*num_bytes*/, |
| 289 DispatcherVector* /*dispatchers*/, | 294 DispatcherVector* /*dispatchers*/, |
| 290 uint32_t* /*num_dispatchers*/, | 295 uint32_t* /*num_dispatchers*/, |
| 291 MojoReadMessageFlags /*flags*/) { | 296 MojoReadMessageFlags /*flags*/) { |
| 292 mutex_.AssertHeld(); | 297 lock_.AssertAcquired(); |
| 293 DCHECK(!is_closed_); | 298 DCHECK(!is_closed_); |
| 294 // By default, not supported. Only needed for message pipe dispatchers. | 299 // By default, not supported. Only needed for message pipe dispatchers. |
| 295 return MOJO_RESULT_INVALID_ARGUMENT; | 300 return MOJO_RESULT_INVALID_ARGUMENT; |
| 296 } | 301 } |
| 297 | 302 |
| 298 MojoResult Dispatcher::WriteDataImplNoLock(UserPointer<const void> /*elements*/, | 303 MojoResult Dispatcher::WriteDataImplNoLock(UserPointer<const void> /*elements*/, |
| 299 UserPointer<uint32_t> /*num_bytes*/, | 304 UserPointer<uint32_t> /*num_bytes*/, |
| 300 MojoWriteDataFlags /*flags*/) { | 305 MojoWriteDataFlags /*flags*/) { |
| 301 mutex_.AssertHeld(); | 306 lock_.AssertAcquired(); |
| 302 DCHECK(!is_closed_); | 307 DCHECK(!is_closed_); |
| 303 // By default, not supported. Only needed for data pipe dispatchers. | 308 // By default, not supported. Only needed for data pipe dispatchers. |
| 304 return MOJO_RESULT_INVALID_ARGUMENT; | 309 return MOJO_RESULT_INVALID_ARGUMENT; |
| 305 } | 310 } |
| 306 | 311 |
| 307 MojoResult Dispatcher::BeginWriteDataImplNoLock( | 312 MojoResult Dispatcher::BeginWriteDataImplNoLock( |
| 308 UserPointer<void*> /*buffer*/, | 313 UserPointer<void*> /*buffer*/, |
| 309 UserPointer<uint32_t> /*buffer_num_bytes*/, | 314 UserPointer<uint32_t> /*buffer_num_bytes*/, |
| 310 MojoWriteDataFlags /*flags*/) { | 315 MojoWriteDataFlags /*flags*/) { |
| 311 mutex_.AssertHeld(); | 316 lock_.AssertAcquired(); |
| 312 DCHECK(!is_closed_); | 317 DCHECK(!is_closed_); |
| 313 // By default, not supported. Only needed for data pipe dispatchers. | 318 // By default, not supported. Only needed for data pipe dispatchers. |
| 314 return MOJO_RESULT_INVALID_ARGUMENT; | 319 return MOJO_RESULT_INVALID_ARGUMENT; |
| 315 } | 320 } |
| 316 | 321 |
| 317 MojoResult Dispatcher::EndWriteDataImplNoLock(uint32_t /*num_bytes_written*/) { | 322 MojoResult Dispatcher::EndWriteDataImplNoLock(uint32_t /*num_bytes_written*/) { |
| 318 mutex_.AssertHeld(); | 323 lock_.AssertAcquired(); |
| 319 DCHECK(!is_closed_); | 324 DCHECK(!is_closed_); |
| 320 // By default, not supported. Only needed for data pipe dispatchers. | 325 // By default, not supported. Only needed for data pipe dispatchers. |
| 321 return MOJO_RESULT_INVALID_ARGUMENT; | 326 return MOJO_RESULT_INVALID_ARGUMENT; |
| 322 } | 327 } |
| 323 | 328 |
| 324 MojoResult Dispatcher::ReadDataImplNoLock(UserPointer<void> /*elements*/, | 329 MojoResult Dispatcher::ReadDataImplNoLock(UserPointer<void> /*elements*/, |
| 325 UserPointer<uint32_t> /*num_bytes*/, | 330 UserPointer<uint32_t> /*num_bytes*/, |
| 326 MojoReadDataFlags /*flags*/) { | 331 MojoReadDataFlags /*flags*/) { |
| 327 mutex_.AssertHeld(); | 332 lock_.AssertAcquired(); |
| 328 DCHECK(!is_closed_); | 333 DCHECK(!is_closed_); |
| 329 // By default, not supported. Only needed for data pipe dispatchers. | 334 // By default, not supported. Only needed for data pipe dispatchers. |
| 330 return MOJO_RESULT_INVALID_ARGUMENT; | 335 return MOJO_RESULT_INVALID_ARGUMENT; |
| 331 } | 336 } |
| 332 | 337 |
| 333 MojoResult Dispatcher::BeginReadDataImplNoLock( | 338 MojoResult Dispatcher::BeginReadDataImplNoLock( |
| 334 UserPointer<const void*> /*buffer*/, | 339 UserPointer<const void*> /*buffer*/, |
| 335 UserPointer<uint32_t> /*buffer_num_bytes*/, | 340 UserPointer<uint32_t> /*buffer_num_bytes*/, |
| 336 MojoReadDataFlags /*flags*/) { | 341 MojoReadDataFlags /*flags*/) { |
| 337 mutex_.AssertHeld(); | 342 lock_.AssertAcquired(); |
| 338 DCHECK(!is_closed_); | 343 DCHECK(!is_closed_); |
| 339 // By default, not supported. Only needed for data pipe dispatchers. | 344 // By default, not supported. Only needed for data pipe dispatchers. |
| 340 return MOJO_RESULT_INVALID_ARGUMENT; | 345 return MOJO_RESULT_INVALID_ARGUMENT; |
| 341 } | 346 } |
| 342 | 347 |
| 343 MojoResult Dispatcher::EndReadDataImplNoLock(uint32_t /*num_bytes_read*/) { | 348 MojoResult Dispatcher::EndReadDataImplNoLock(uint32_t /*num_bytes_read*/) { |
| 344 mutex_.AssertHeld(); | 349 lock_.AssertAcquired(); |
| 345 DCHECK(!is_closed_); | 350 DCHECK(!is_closed_); |
| 346 // By default, not supported. Only needed for data pipe dispatchers. | 351 // By default, not supported. Only needed for data pipe dispatchers. |
| 347 return MOJO_RESULT_INVALID_ARGUMENT; | 352 return MOJO_RESULT_INVALID_ARGUMENT; |
| 348 } | 353 } |
| 349 | 354 |
| 350 MojoResult Dispatcher::DuplicateBufferHandleImplNoLock( | 355 MojoResult Dispatcher::DuplicateBufferHandleImplNoLock( |
| 351 UserPointer<const MojoDuplicateBufferHandleOptions> /*options*/, | 356 UserPointer<const MojoDuplicateBufferHandleOptions> /*options*/, |
| 352 scoped_refptr<Dispatcher>* /*new_dispatcher*/) { | 357 scoped_refptr<Dispatcher>* /*new_dispatcher*/) { |
| 353 mutex_.AssertHeld(); | 358 lock_.AssertAcquired(); |
| 354 DCHECK(!is_closed_); | 359 DCHECK(!is_closed_); |
| 355 // By default, not supported. Only needed for buffer dispatchers. | 360 // By default, not supported. Only needed for buffer dispatchers. |
| 356 return MOJO_RESULT_INVALID_ARGUMENT; | 361 return MOJO_RESULT_INVALID_ARGUMENT; |
| 357 } | 362 } |
| 358 | 363 |
| 359 MojoResult Dispatcher::MapBufferImplNoLock( | 364 MojoResult Dispatcher::MapBufferImplNoLock( |
| 360 uint64_t /*offset*/, | 365 uint64_t /*offset*/, |
| 361 uint64_t /*num_bytes*/, | 366 uint64_t /*num_bytes*/, |
| 362 MojoMapBufferFlags /*flags*/, | 367 MojoMapBufferFlags /*flags*/, |
| 363 scoped_ptr<embedder::PlatformSharedBufferMapping>* /*mapping*/) { | 368 scoped_ptr<embedder::PlatformSharedBufferMapping>* /*mapping*/) { |
| 364 mutex_.AssertHeld(); | 369 lock_.AssertAcquired(); |
| 365 DCHECK(!is_closed_); | 370 DCHECK(!is_closed_); |
| 366 // By default, not supported. Only needed for buffer dispatchers. | 371 // By default, not supported. Only needed for buffer dispatchers. |
| 367 return MOJO_RESULT_INVALID_ARGUMENT; | 372 return MOJO_RESULT_INVALID_ARGUMENT; |
| 368 } | 373 } |
| 369 | 374 |
| 370 HandleSignalsState Dispatcher::GetHandleSignalsStateImplNoLock() const { | 375 HandleSignalsState Dispatcher::GetHandleSignalsStateImplNoLock() const { |
| 371 mutex_.AssertHeld(); | 376 lock_.AssertAcquired(); |
| 372 DCHECK(!is_closed_); | 377 DCHECK(!is_closed_); |
| 373 // By default, waiting isn't supported. Only dispatchers that can be waited on | 378 // By default, waiting isn't supported. Only dispatchers that can be waited on |
| 374 // will do something nontrivial. | 379 // will do something nontrivial. |
| 375 return HandleSignalsState(); | 380 return HandleSignalsState(); |
| 376 } | 381 } |
| 377 | 382 |
| 378 MojoResult Dispatcher::AddAwakableImplNoLock( | 383 MojoResult Dispatcher::AddAwakableImplNoLock( |
| 379 Awakable* /*awakable*/, | 384 Awakable* /*awakable*/, |
| 380 MojoHandleSignals /*signals*/, | 385 MojoHandleSignals /*signals*/, |
| 381 uint32_t /*context*/, | 386 uint32_t /*context*/, |
| 382 HandleSignalsState* signals_state) { | 387 HandleSignalsState* signals_state) { |
| 383 mutex_.AssertHeld(); | 388 lock_.AssertAcquired(); |
| 384 DCHECK(!is_closed_); | 389 DCHECK(!is_closed_); |
| 385 // By default, waiting isn't supported. Only dispatchers that can be waited on | 390 // By default, waiting isn't supported. Only dispatchers that can be waited on |
| 386 // will do something nontrivial. | 391 // will do something nontrivial. |
| 387 if (signals_state) | 392 if (signals_state) |
| 388 *signals_state = HandleSignalsState(); | 393 *signals_state = HandleSignalsState(); |
| 389 return MOJO_RESULT_FAILED_PRECONDITION; | 394 return MOJO_RESULT_FAILED_PRECONDITION; |
| 390 } | 395 } |
| 391 | 396 |
| 392 void Dispatcher::RemoveAwakableImplNoLock(Awakable* /*awakable*/, | 397 void Dispatcher::RemoveAwakableImplNoLock(Awakable* /*awakable*/, |
| 393 HandleSignalsState* signals_state) { | 398 HandleSignalsState* signals_state) { |
| 394 mutex_.AssertHeld(); | 399 lock_.AssertAcquired(); |
| 395 DCHECK(!is_closed_); | 400 DCHECK(!is_closed_); |
| 396 // By default, waiting isn't supported. Only dispatchers that can be waited on | 401 // By default, waiting isn't supported. Only dispatchers that can be waited on |
| 397 // will do something nontrivial. | 402 // will do something nontrivial. |
| 398 if (signals_state) | 403 if (signals_state) |
| 399 *signals_state = HandleSignalsState(); | 404 *signals_state = HandleSignalsState(); |
| 400 } | 405 } |
| 401 | 406 |
| 402 void Dispatcher::StartSerializeImplNoLock(Channel* /*channel*/, | 407 void Dispatcher::StartSerializeImplNoLock(size_t* max_size, |
| 403 size_t* max_size, | |
| 404 size_t* max_platform_handles) { | 408 size_t* max_platform_handles) { |
| 405 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. | 409 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. |
| 406 DCHECK(!is_closed_); | 410 DCHECK(!is_closed_); |
| 407 *max_size = 0; | 411 *max_size = 0; |
| 408 *max_platform_handles = 0; | 412 *max_platform_handles = 0; |
| 409 } | 413 } |
| 410 | 414 |
| 411 bool Dispatcher::EndSerializeAndCloseImplNoLock( | 415 bool Dispatcher::EndSerializeAndCloseImplNoLock( |
| 412 Channel* /*channel*/, | |
| 413 void* /*destination*/, | 416 void* /*destination*/, |
| 414 size_t* /*actual_size*/, | 417 size_t* /*actual_size*/, |
| 415 embedder::PlatformHandleVector* /*platform_handles*/) { | 418 embedder::PlatformHandleVector* /*platform_handles*/) { |
| 416 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. | 419 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. |
| 417 DCHECK(is_closed_); | 420 DCHECK(is_closed_); |
| 418 // By default, serializing isn't supported, so just close. | 421 // By default, serializing isn't supported, so just close. |
| 419 CloseImplNoLock(); | 422 CloseImplNoLock(); |
| 420 return false; | 423 return false; |
| 421 } | 424 } |
| 422 | 425 |
| 423 bool Dispatcher::IsBusyNoLock() const { | 426 bool Dispatcher::IsBusyNoLock() const { |
| 424 mutex_.AssertHeld(); | 427 lock_.AssertAcquired(); |
| 425 DCHECK(!is_closed_); | 428 DCHECK(!is_closed_); |
| 426 // Most dispatchers support only "atomic" operations, so they are never busy | 429 // Most dispatchers support only "atomic" operations, so they are never busy |
| 427 // (in this sense). | 430 // (in this sense). |
| 428 return false; | 431 return false; |
| 429 } | 432 } |
| 430 | 433 |
| 431 void Dispatcher::CloseNoLock() { | 434 void Dispatcher::CloseNoLock() { |
| 432 mutex_.AssertHeld(); | 435 lock_.AssertAcquired(); |
| 433 DCHECK(!is_closed_); | 436 DCHECK(!is_closed_); |
| 434 | 437 |
| 435 is_closed_ = true; | 438 is_closed_ = true; |
| 436 CancelAllAwakablesNoLock(); | 439 CancelAllAwakablesNoLock(); |
| 437 CloseImplNoLock(); | 440 CloseImplNoLock(); |
| 438 } | 441 } |
| 439 | 442 |
| 440 scoped_refptr<Dispatcher> | 443 scoped_refptr<Dispatcher> |
| 441 Dispatcher::CreateEquivalentDispatcherAndCloseNoLock() { | 444 Dispatcher::CreateEquivalentDispatcherAndCloseNoLock() { |
| 442 mutex_.AssertHeld(); | 445 lock_.AssertAcquired(); |
| 443 DCHECK(!is_closed_); | 446 DCHECK(!is_closed_); |
| 444 | 447 |
| 445 is_closed_ = true; | 448 is_closed_ = true; |
| 446 CancelAllAwakablesNoLock(); | 449 CancelAllAwakablesNoLock(); |
| 447 return CreateEquivalentDispatcherAndCloseImplNoLock(); | 450 return CreateEquivalentDispatcherAndCloseImplNoLock(); |
| 448 } | 451 } |
| 449 | 452 |
| 450 void Dispatcher::StartSerialize(Channel* channel, | 453 void Dispatcher::StartSerialize(size_t* max_size, |
| 451 size_t* max_size, | |
| 452 size_t* max_platform_handles) { | 454 size_t* max_platform_handles) { |
| 453 DCHECK(channel); | |
| 454 DCHECK(max_size); | 455 DCHECK(max_size); |
| 455 DCHECK(max_platform_handles); | 456 DCHECK(max_platform_handles); |
| 456 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. | 457 //DCHECK(HasOneRef()); // Only one ref => no need to take the lock. |
| 458 // jam: document exactly when this happens: i.e. when startserialize is called |
| 459 // on main thread. |
| 457 DCHECK(!is_closed_); | 460 DCHECK(!is_closed_); |
| 458 StartSerializeImplNoLock(channel, max_size, max_platform_handles); | 461 StartSerializeImplNoLock(max_size, max_platform_handles); |
| 459 } | 462 } |
| 460 | 463 |
| 461 bool Dispatcher::EndSerializeAndClose( | 464 bool Dispatcher::EndSerializeAndClose( |
| 462 Channel* channel, | |
| 463 void* destination, | 465 void* destination, |
| 464 size_t* actual_size, | 466 size_t* actual_size, |
| 465 embedder::PlatformHandleVector* platform_handles) { | 467 embedder::PlatformHandleVector* platform_handles) { |
| 466 DCHECK(channel); | |
| 467 DCHECK(actual_size); | 468 DCHECK(actual_size); |
| 468 DCHECK(HasOneRef()); // Only one ref => no need to take the lock. | 469 //DCHECK(HasOneRef()); // Only one ref => no need to take the lock. |
| 470 // jam: same as startserialize |
| 469 DCHECK(!is_closed_); | 471 DCHECK(!is_closed_); |
| 470 | 472 |
| 471 // Like other |...Close()| methods, we mark ourselves as closed before calling | 473 // Like other |...Close()| methods, we mark ourselves as closed before calling |
| 472 // the impl. But there's no need to cancel waiters: we shouldn't have any (and | 474 // the impl. But there's no need to cancel waiters: we shouldn't have any (and |
| 473 // shouldn't be in |Core|'s handle table. | 475 // shouldn't be in |Core|'s handle table. |
| 474 is_closed_ = true; | 476 is_closed_ = true; |
| 475 | 477 |
| 476 #if !defined(NDEBUG) | 478 #if !defined(NDEBUG) |
| 477 // See the comment above |EndSerializeAndCloseImplNoLock()|. In brief: Locking | 479 // See the comment above |EndSerializeAndCloseImplNoLock()|. In brief: Locking |
| 478 // isn't actually needed, but we need to satisfy assertions (which we don't | 480 // isn't actually needed, but we need to satisfy assertions (which we don't |
| 479 // want to remove or weaken). | 481 // want to remove or weaken). |
| 480 MutexLocker locker(&mutex_); | 482 base::AutoLock locker(lock_); |
| 481 #endif | 483 #endif |
| 482 | 484 |
| 483 return EndSerializeAndCloseImplNoLock(channel, destination, actual_size, | 485 return EndSerializeAndCloseImplNoLock(destination, actual_size, |
| 484 platform_handles); | 486 platform_handles); |
| 485 } | 487 } |
| 486 | 488 |
| 487 // DispatcherTransport --------------------------------------------------------- | 489 // DispatcherTransport --------------------------------------------------------- |
| 488 | 490 |
| 489 void DispatcherTransport::End() { | 491 void DispatcherTransport::End() { |
| 490 DCHECK(dispatcher_); | 492 DCHECK(dispatcher_); |
| 491 dispatcher_->mutex_.Unlock(); | 493 dispatcher_->lock_.Release(); |
| 494 |
| 495 dispatcher_->TransportEnded(); |
| 496 |
| 492 dispatcher_ = nullptr; | 497 dispatcher_ = nullptr; |
| 493 } | 498 } |
| 494 | 499 |
| 495 } // namespace system | 500 } // namespace system |
| 496 } // namespace mojo | 501 } // namespace mojo |
| OLD | NEW |