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
3 // found in the LICENSE file.
5 #include "mojo/system/dispatcher.h"
7 #include "base/logging.h"
8 #include "mojo/system/constants.h"
9 #include "mojo/system/message_pipe_dispatcher.h"
10 #include "mojo/system/platform_handle_dispatcher.h"
11 #include "mojo/system/shared_buffer_dispatcher.h"
18 // TODO(vtl): Maybe this should be defined in a test-only file instead.
19 DispatcherTransport DispatcherTryStartTransport(Dispatcher* dispatcher) {
20 return Dispatcher::HandleTableAccess::TryStartTransport(dispatcher);
25 // Dispatcher ------------------------------------------------------------------
28 DispatcherTransport Dispatcher::HandleTableAccess::TryStartTransport(
29 Dispatcher* dispatcher) {
32 if (!dispatcher->lock_.Try())
33 return DispatcherTransport();
35 // We shouldn't race with things that close dispatchers, since closing can
36 // only take place either under |handle_table_lock_| or when the handle is
38 DCHECK(!dispatcher->is_closed_);
40 return DispatcherTransport(dispatcher);
44 void Dispatcher::TransportDataAccess::StartSerialize(
45 Dispatcher* dispatcher,
48 size_t* max_platform_handles) {
50 dispatcher->StartSerialize(channel, max_size, max_platform_handles);
54 bool Dispatcher::TransportDataAccess::EndSerializeAndClose(
55 Dispatcher* dispatcher,
59 embedder::PlatformHandleVector* platform_handles) {
61 return dispatcher->EndSerializeAndClose(
62 channel, destination, actual_size, platform_handles);
66 scoped_refptr<Dispatcher> Dispatcher::TransportDataAccess::Deserialize(
71 embedder::PlatformHandleVector* platform_handles) {
72 switch (static_cast<int32_t>(type)) {
74 DVLOG(2) << "Deserializing invalid handle";
75 return scoped_refptr<Dispatcher>();
76 case kTypeMessagePipe:
77 return scoped_refptr<Dispatcher>(
78 MessagePipeDispatcher::Deserialize(channel, source, size));
79 case kTypeDataPipeProducer:
80 case kTypeDataPipeConsumer:
81 // TODO(vtl): Implement.
82 LOG(WARNING) << "Deserialization of dispatcher type " << type
84 return scoped_refptr<Dispatcher>();
85 case kTypeSharedBuffer:
86 return scoped_refptr<Dispatcher>(SharedBufferDispatcher::Deserialize(
87 channel, source, size, platform_handles));
88 case kTypePlatformHandle:
89 return scoped_refptr<Dispatcher>(PlatformHandleDispatcher::Deserialize(
90 channel, source, size, platform_handles));
92 LOG(WARNING) << "Unknown dispatcher type " << type;
93 return scoped_refptr<Dispatcher>();
96 MojoResult Dispatcher::Close() {
97 base::AutoLock locker(lock_);
99 return MOJO_RESULT_INVALID_ARGUMENT;
102 return MOJO_RESULT_OK;
105 MojoResult Dispatcher::WriteMessage(
106 UserPointer<const void> bytes,
108 std::vector<DispatcherTransport>* transports,
109 MojoWriteMessageFlags flags) {
110 DCHECK(!transports || (transports->size() > 0 &&
111 transports->size() < kMaxMessageNumHandles));
113 base::AutoLock locker(lock_);
115 return MOJO_RESULT_INVALID_ARGUMENT;
117 return WriteMessageImplNoLock(bytes, num_bytes, transports, flags);
120 MojoResult Dispatcher::ReadMessage(UserPointer<void> bytes,
121 UserPointer<uint32_t> num_bytes,
122 DispatcherVector* dispatchers,
123 uint32_t* num_dispatchers,
124 MojoReadMessageFlags flags) {
125 DCHECK(!num_dispatchers || *num_dispatchers == 0 ||
126 (dispatchers && dispatchers->empty()));
128 base::AutoLock locker(lock_);
130 return MOJO_RESULT_INVALID_ARGUMENT;
132 return ReadMessageImplNoLock(
133 bytes, num_bytes, dispatchers, num_dispatchers, flags);
136 MojoResult Dispatcher::WriteData(UserPointer<const void> elements,
137 UserPointer<uint32_t> num_bytes,
138 MojoWriteDataFlags flags) {
139 base::AutoLock locker(lock_);
141 return MOJO_RESULT_INVALID_ARGUMENT;
143 return WriteDataImplNoLock(elements, num_bytes, flags);
146 MojoResult Dispatcher::BeginWriteData(UserPointer<void*> buffer,
147 UserPointer<uint32_t> buffer_num_bytes,
148 MojoWriteDataFlags flags) {
149 base::AutoLock locker(lock_);
151 return MOJO_RESULT_INVALID_ARGUMENT;
153 return BeginWriteDataImplNoLock(buffer, buffer_num_bytes, flags);
156 MojoResult Dispatcher::EndWriteData(uint32_t num_bytes_written) {
157 base::AutoLock locker(lock_);
159 return MOJO_RESULT_INVALID_ARGUMENT;
161 return EndWriteDataImplNoLock(num_bytes_written);
164 MojoResult Dispatcher::ReadData(UserPointer<void> elements,
165 UserPointer<uint32_t> num_bytes,
166 MojoReadDataFlags flags) {
167 base::AutoLock locker(lock_);
169 return MOJO_RESULT_INVALID_ARGUMENT;
171 return ReadDataImplNoLock(elements, num_bytes, flags);
174 MojoResult Dispatcher::BeginReadData(UserPointer<const void*> buffer,
175 UserPointer<uint32_t> buffer_num_bytes,
176 MojoReadDataFlags flags) {
177 base::AutoLock locker(lock_);
179 return MOJO_RESULT_INVALID_ARGUMENT;
181 return BeginReadDataImplNoLock(buffer, buffer_num_bytes, flags);
184 MojoResult Dispatcher::EndReadData(uint32_t num_bytes_read) {
185 base::AutoLock locker(lock_);
187 return MOJO_RESULT_INVALID_ARGUMENT;
189 return EndReadDataImplNoLock(num_bytes_read);
192 MojoResult Dispatcher::DuplicateBufferHandle(
193 UserPointer<const MojoDuplicateBufferHandleOptions> options,
194 scoped_refptr<Dispatcher>* new_dispatcher) {
195 base::AutoLock locker(lock_);
197 return MOJO_RESULT_INVALID_ARGUMENT;
199 return DuplicateBufferHandleImplNoLock(options, new_dispatcher);
202 MojoResult Dispatcher::MapBuffer(
205 MojoMapBufferFlags flags,
206 scoped_ptr<embedder::PlatformSharedBufferMapping>* mapping) {
207 base::AutoLock locker(lock_);
209 return MOJO_RESULT_INVALID_ARGUMENT;
211 return MapBufferImplNoLock(offset, num_bytes, flags, mapping);
214 HandleSignalsState Dispatcher::GetHandleSignalsState() const {
215 base::AutoLock locker(lock_);
217 return HandleSignalsState();
219 return GetHandleSignalsStateImplNoLock();
222 MojoResult Dispatcher::AddWaiter(Waiter* waiter,
223 MojoHandleSignals signals,
225 HandleSignalsState* signals_state) {
226 base::AutoLock locker(lock_);
229 *signals_state = HandleSignalsState();
230 return MOJO_RESULT_INVALID_ARGUMENT;
233 return AddWaiterImplNoLock(waiter, signals, context, signals_state);
236 void Dispatcher::RemoveWaiter(Waiter* waiter,
237 HandleSignalsState* handle_signals_state) {
238 base::AutoLock locker(lock_);
240 if (handle_signals_state)
241 *handle_signals_state = HandleSignalsState();
244 RemoveWaiterImplNoLock(waiter, handle_signals_state);
247 Dispatcher::Dispatcher() : is_closed_(false) {
250 Dispatcher::~Dispatcher() {
251 // Make sure that |Close()| was called.
255 void Dispatcher::CancelAllWaitersNoLock() {
256 lock_.AssertAcquired();
258 // By default, waiting isn't supported. Only dispatchers that can be waited on
259 // will do something nontrivial.
262 void Dispatcher::CloseImplNoLock() {
263 lock_.AssertAcquired();
265 // This may not need to do anything. Dispatchers should override this to do
266 // any actual close-time cleanup necessary.
269 MojoResult Dispatcher::WriteMessageImplNoLock(
270 UserPointer<const void> /*bytes*/,
271 uint32_t /*num_bytes*/,
272 std::vector<DispatcherTransport>* /*transports*/,
273 MojoWriteMessageFlags /*flags*/) {
274 lock_.AssertAcquired();
276 // By default, not supported. Only needed for message pipe dispatchers.
277 return MOJO_RESULT_INVALID_ARGUMENT;
280 MojoResult Dispatcher::ReadMessageImplNoLock(
281 UserPointer<void> /*bytes*/,
282 UserPointer<uint32_t> /*num_bytes*/,
283 DispatcherVector* /*dispatchers*/,
284 uint32_t* /*num_dispatchers*/,
285 MojoReadMessageFlags /*flags*/) {
286 lock_.AssertAcquired();
288 // By default, not supported. Only needed for message pipe dispatchers.
289 return MOJO_RESULT_INVALID_ARGUMENT;
292 MojoResult Dispatcher::WriteDataImplNoLock(UserPointer<const void> /*elements*/,
293 UserPointer<uint32_t> /*num_bytes*/,
294 MojoWriteDataFlags /*flags*/) {
295 lock_.AssertAcquired();
297 // By default, not supported. Only needed for data pipe dispatchers.
298 return MOJO_RESULT_INVALID_ARGUMENT;
301 MojoResult Dispatcher::BeginWriteDataImplNoLock(
302 UserPointer<void*> /*buffer*/,
303 UserPointer<uint32_t> /*buffer_num_bytes*/,
304 MojoWriteDataFlags /*flags*/) {
305 lock_.AssertAcquired();
307 // By default, not supported. Only needed for data pipe dispatchers.
308 return MOJO_RESULT_INVALID_ARGUMENT;
311 MojoResult Dispatcher::EndWriteDataImplNoLock(uint32_t /*num_bytes_written*/) {
312 lock_.AssertAcquired();
314 // By default, not supported. Only needed for data pipe dispatchers.
315 return MOJO_RESULT_INVALID_ARGUMENT;
318 MojoResult Dispatcher::ReadDataImplNoLock(UserPointer<void> /*elements*/,
319 UserPointer<uint32_t> /*num_bytes*/,
320 MojoReadDataFlags /*flags*/) {
321 lock_.AssertAcquired();
323 // By default, not supported. Only needed for data pipe dispatchers.
324 return MOJO_RESULT_INVALID_ARGUMENT;
327 MojoResult Dispatcher::BeginReadDataImplNoLock(
328 UserPointer<const void*> /*buffer*/,
329 UserPointer<uint32_t> /*buffer_num_bytes*/,
330 MojoReadDataFlags /*flags*/) {
331 lock_.AssertAcquired();
333 // By default, not supported. Only needed for data pipe dispatchers.
334 return MOJO_RESULT_INVALID_ARGUMENT;
337 MojoResult Dispatcher::EndReadDataImplNoLock(uint32_t /*num_bytes_read*/) {
338 lock_.AssertAcquired();
340 // By default, not supported. Only needed for data pipe dispatchers.
341 return MOJO_RESULT_INVALID_ARGUMENT;
344 MojoResult Dispatcher::DuplicateBufferHandleImplNoLock(
345 UserPointer<const MojoDuplicateBufferHandleOptions> /*options*/,
346 scoped_refptr<Dispatcher>* /*new_dispatcher*/) {
347 lock_.AssertAcquired();
349 // By default, not supported. Only needed for buffer dispatchers.
350 return MOJO_RESULT_INVALID_ARGUMENT;
353 MojoResult Dispatcher::MapBufferImplNoLock(
355 uint64_t /*num_bytes*/,
356 MojoMapBufferFlags /*flags*/,
357 scoped_ptr<embedder::PlatformSharedBufferMapping>* /*mapping*/) {
358 lock_.AssertAcquired();
360 // By default, not supported. Only needed for buffer dispatchers.
361 return MOJO_RESULT_INVALID_ARGUMENT;
364 HandleSignalsState Dispatcher::GetHandleSignalsStateImplNoLock() const {
365 lock_.AssertAcquired();
367 // By default, waiting isn't supported. Only dispatchers that can be waited on
368 // will do something nontrivial.
369 return HandleSignalsState();
372 MojoResult Dispatcher::AddWaiterImplNoLock(Waiter* /*waiter*/,
373 MojoHandleSignals /*signals*/,
374 uint32_t /*context*/,
375 HandleSignalsState* signals_state) {
376 lock_.AssertAcquired();
378 // By default, waiting isn't supported. Only dispatchers that can be waited on
379 // will do something nontrivial.
381 *signals_state = HandleSignalsState();
382 return MOJO_RESULT_FAILED_PRECONDITION;
385 void Dispatcher::RemoveWaiterImplNoLock(Waiter* /*waiter*/,
386 HandleSignalsState* signals_state) {
387 lock_.AssertAcquired();
389 // By default, waiting isn't supported. Only dispatchers that can be waited on
390 // will do something nontrivial.
392 *signals_state = HandleSignalsState();
395 void Dispatcher::StartSerializeImplNoLock(Channel* /*channel*/,
397 size_t* max_platform_handles) {
398 DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
401 *max_platform_handles = 0;
404 bool Dispatcher::EndSerializeAndCloseImplNoLock(
405 Channel* /*channel*/,
406 void* /*destination*/,
407 size_t* /*actual_size*/,
408 embedder::PlatformHandleVector* /*platform_handles*/) {
409 DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
411 // By default, serializing isn't supported, so just close.
416 bool Dispatcher::IsBusyNoLock() const {
417 lock_.AssertAcquired();
419 // Most dispatchers support only "atomic" operations, so they are never busy
424 void Dispatcher::CloseNoLock() {
425 lock_.AssertAcquired();
429 CancelAllWaitersNoLock();
433 scoped_refptr<Dispatcher>
434 Dispatcher::CreateEquivalentDispatcherAndCloseNoLock() {
435 lock_.AssertAcquired();
439 CancelAllWaitersNoLock();
440 return CreateEquivalentDispatcherAndCloseImplNoLock();
443 void Dispatcher::StartSerialize(Channel* channel,
445 size_t* max_platform_handles) {
448 DCHECK(max_platform_handles);
449 DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
451 StartSerializeImplNoLock(channel, max_size, max_platform_handles);
454 bool Dispatcher::EndSerializeAndClose(
458 embedder::PlatformHandleVector* platform_handles) {
461 DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
464 // Like other |...Close()| methods, we mark ourselves as closed before calling
465 // the impl. But there's no need to cancel waiters: we shouldn't have any (and
466 // shouldn't be in |Core|'s handle table.
470 // See the comment above |EndSerializeAndCloseImplNoLock()|. In brief: Locking
471 // isn't actually needed, but we need to satisfy assertions (which we don't
472 // want to remove or weaken).
473 base::AutoLock locker(lock_);
476 return EndSerializeAndCloseImplNoLock(
477 channel, destination, actual_size, platform_handles);
480 // DispatcherTransport ---------------------------------------------------------
482 void DispatcherTransport::End() {
484 dispatcher_->lock_.Release();
488 } // namespace system