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(
20 Dispatcher
* dispatcher
) {
21 return Dispatcher::HandleTableAccess::TryStartTransport(dispatcher
);
26 // Dispatcher ------------------------------------------------------------------
29 DispatcherTransport
Dispatcher::HandleTableAccess::TryStartTransport(
30 Dispatcher
* dispatcher
) {
33 if (!dispatcher
->lock_
.Try())
34 return DispatcherTransport();
36 // We shouldn't race with things that close dispatchers, since closing can
37 // only take place either under |handle_table_lock_| or when the handle is
39 DCHECK(!dispatcher
->is_closed_
);
41 return DispatcherTransport(dispatcher
);
45 void Dispatcher::TransportDataAccess::StartSerialize(
46 Dispatcher
* dispatcher
,
49 size_t* max_platform_handles
) {
51 dispatcher
->StartSerialize(channel
, max_size
, max_platform_handles
);
55 bool Dispatcher::TransportDataAccess::EndSerializeAndClose(
56 Dispatcher
* dispatcher
,
60 embedder::PlatformHandleVector
* platform_handles
) {
62 return dispatcher
->EndSerializeAndClose(channel
, destination
, actual_size
,
67 scoped_refptr
<Dispatcher
> Dispatcher::TransportDataAccess::Deserialize(
72 embedder::PlatformHandleVector
* platform_handles
) {
73 switch (static_cast<int32_t>(type
)) {
75 DVLOG(2) << "Deserializing invalid handle";
76 return scoped_refptr
<Dispatcher
>();
77 case kTypeMessagePipe
:
78 return scoped_refptr
<Dispatcher
>(
79 MessagePipeDispatcher::Deserialize(channel
, source
, size
));
80 case kTypeDataPipeProducer
:
81 case kTypeDataPipeConsumer
:
82 // TODO(vtl): Implement.
83 LOG(WARNING
) << "Deserialization of dispatcher type " << type
85 return scoped_refptr
<Dispatcher
>();
86 case kTypeSharedBuffer
:
87 return scoped_refptr
<Dispatcher
>(
88 SharedBufferDispatcher::Deserialize(channel
, source
, size
,
90 case kTypePlatformHandle
:
91 return scoped_refptr
<Dispatcher
>(
92 PlatformHandleDispatcher::Deserialize(channel
, source
, size
,
95 LOG(WARNING
) << "Unknown dispatcher type " << type
;
96 return scoped_refptr
<Dispatcher
>();
99 MojoResult
Dispatcher::Close() {
100 base::AutoLock
locker(lock_
);
102 return MOJO_RESULT_INVALID_ARGUMENT
;
105 return MOJO_RESULT_OK
;
108 MojoResult
Dispatcher::WriteMessage(
111 std::vector
<DispatcherTransport
>* transports
,
112 MojoWriteMessageFlags flags
) {
113 DCHECK(!transports
|| (transports
->size() > 0 &&
114 transports
->size() < kMaxMessageNumHandles
));
116 base::AutoLock
locker(lock_
);
118 return MOJO_RESULT_INVALID_ARGUMENT
;
120 return WriteMessageImplNoLock(bytes
, num_bytes
, transports
, flags
);
123 MojoResult
Dispatcher::ReadMessage(void* bytes
,
125 DispatcherVector
* dispatchers
,
126 uint32_t* num_dispatchers
,
127 MojoReadMessageFlags flags
) {
128 DCHECK(!num_dispatchers
|| *num_dispatchers
== 0 ||
129 (dispatchers
&& dispatchers
->empty()));
131 base::AutoLock
locker(lock_
);
133 return MOJO_RESULT_INVALID_ARGUMENT
;
135 return ReadMessageImplNoLock(bytes
, num_bytes
, dispatchers
, num_dispatchers
,
139 MojoResult
Dispatcher::WriteData(const void* elements
,
141 MojoWriteDataFlags flags
) {
142 base::AutoLock
locker(lock_
);
144 return MOJO_RESULT_INVALID_ARGUMENT
;
146 return WriteDataImplNoLock(elements
, num_bytes
, flags
);
149 MojoResult
Dispatcher::BeginWriteData(void** buffer
,
150 uint32_t* buffer_num_bytes
,
151 MojoWriteDataFlags flags
) {
152 base::AutoLock
locker(lock_
);
154 return MOJO_RESULT_INVALID_ARGUMENT
;
156 return BeginWriteDataImplNoLock(buffer
, buffer_num_bytes
, flags
);
159 MojoResult
Dispatcher::EndWriteData(uint32_t num_bytes_written
) {
160 base::AutoLock
locker(lock_
);
162 return MOJO_RESULT_INVALID_ARGUMENT
;
164 return EndWriteDataImplNoLock(num_bytes_written
);
167 MojoResult
Dispatcher::ReadData(void* elements
,
169 MojoReadDataFlags flags
) {
170 base::AutoLock
locker(lock_
);
172 return MOJO_RESULT_INVALID_ARGUMENT
;
174 return ReadDataImplNoLock(elements
, num_bytes
, flags
);
177 MojoResult
Dispatcher::BeginReadData(const void** buffer
,
178 uint32_t* buffer_num_bytes
,
179 MojoReadDataFlags flags
) {
180 base::AutoLock
locker(lock_
);
182 return MOJO_RESULT_INVALID_ARGUMENT
;
184 return BeginReadDataImplNoLock(buffer
, buffer_num_bytes
, flags
);
187 MojoResult
Dispatcher::EndReadData(uint32_t num_bytes_read
) {
188 base::AutoLock
locker(lock_
);
190 return MOJO_RESULT_INVALID_ARGUMENT
;
192 return EndReadDataImplNoLock(num_bytes_read
);
195 MojoResult
Dispatcher::DuplicateBufferHandle(
196 const MojoDuplicateBufferHandleOptions
* options
,
197 scoped_refptr
<Dispatcher
>* new_dispatcher
) {
198 base::AutoLock
locker(lock_
);
200 return MOJO_RESULT_INVALID_ARGUMENT
;
202 return DuplicateBufferHandleImplNoLock(options
, new_dispatcher
);
205 MojoResult
Dispatcher::MapBuffer(
208 MojoMapBufferFlags flags
,
209 scoped_ptr
<RawSharedBufferMapping
>* mapping
) {
210 base::AutoLock
locker(lock_
);
212 return MOJO_RESULT_INVALID_ARGUMENT
;
214 return MapBufferImplNoLock(offset
, num_bytes
, flags
, mapping
);
217 MojoResult
Dispatcher::AddWaiter(Waiter
* waiter
,
219 MojoResult wake_result
) {
220 DCHECK_GE(wake_result
, 0);
222 base::AutoLock
locker(lock_
);
224 return MOJO_RESULT_INVALID_ARGUMENT
;
226 return AddWaiterImplNoLock(waiter
, flags
, wake_result
);
229 void Dispatcher::RemoveWaiter(Waiter
* waiter
) {
230 base::AutoLock
locker(lock_
);
233 RemoveWaiterImplNoLock(waiter
);
236 Dispatcher::Dispatcher()
237 : is_closed_(false) {
240 Dispatcher::~Dispatcher() {
241 // Make sure that |Close()| was called.
245 void Dispatcher::CancelAllWaitersNoLock() {
246 lock_
.AssertAcquired();
248 // By default, waiting isn't supported. Only dispatchers that can be waited on
249 // will do something nontrivial.
252 void Dispatcher::CloseImplNoLock() {
253 lock_
.AssertAcquired();
255 // This may not need to do anything. Dispatchers should override this to do
256 // any actual close-time cleanup necessary.
259 MojoResult
Dispatcher::WriteMessageImplNoLock(
260 const void* /*bytes*/,
261 uint32_t /*num_bytes*/,
262 std::vector
<DispatcherTransport
>* /*transports*/,
263 MojoWriteMessageFlags
/*flags*/) {
264 lock_
.AssertAcquired();
266 // By default, not supported. Only needed for message pipe dispatchers.
267 return MOJO_RESULT_INVALID_ARGUMENT
;
270 MojoResult
Dispatcher::ReadMessageImplNoLock(void* /*bytes*/,
271 uint32_t* /*num_bytes*/,
272 DispatcherVector
* /*dispatchers*/,
273 uint32_t* /*num_dispatchers*/,
274 MojoReadMessageFlags
/*flags*/) {
275 lock_
.AssertAcquired();
277 // By default, not supported. Only needed for message pipe dispatchers.
278 return MOJO_RESULT_INVALID_ARGUMENT
;
281 MojoResult
Dispatcher::WriteDataImplNoLock(const void* /*elements*/,
282 uint32_t* /*num_bytes*/,
283 MojoWriteDataFlags
/*flags*/) {
284 lock_
.AssertAcquired();
286 // By default, not supported. Only needed for data pipe dispatchers.
287 return MOJO_RESULT_INVALID_ARGUMENT
;
290 MojoResult
Dispatcher::BeginWriteDataImplNoLock(void** /*buffer*/,
291 uint32_t* /*buffer_num_bytes*/,
292 MojoWriteDataFlags
/*flags*/) {
293 lock_
.AssertAcquired();
295 // By default, not supported. Only needed for data pipe dispatchers.
296 return MOJO_RESULT_INVALID_ARGUMENT
;
299 MojoResult
Dispatcher::EndWriteDataImplNoLock(uint32_t /*num_bytes_written*/) {
300 lock_
.AssertAcquired();
302 // By default, not supported. Only needed for data pipe dispatchers.
303 return MOJO_RESULT_INVALID_ARGUMENT
;
306 MojoResult
Dispatcher::ReadDataImplNoLock(void* /*elements*/,
307 uint32_t* /*num_bytes*/,
308 MojoReadDataFlags
/*flags*/) {
309 lock_
.AssertAcquired();
311 // By default, not supported. Only needed for data pipe dispatchers.
312 return MOJO_RESULT_INVALID_ARGUMENT
;
315 MojoResult
Dispatcher::BeginReadDataImplNoLock(const void** /*buffer*/,
316 uint32_t* /*buffer_num_bytes*/,
317 MojoReadDataFlags
/*flags*/) {
318 lock_
.AssertAcquired();
320 // By default, not supported. Only needed for data pipe dispatchers.
321 return MOJO_RESULT_INVALID_ARGUMENT
;
324 MojoResult
Dispatcher::EndReadDataImplNoLock(uint32_t /*num_bytes_read*/) {
325 lock_
.AssertAcquired();
327 // By default, not supported. Only needed for data pipe dispatchers.
328 return MOJO_RESULT_INVALID_ARGUMENT
;
331 MojoResult
Dispatcher::DuplicateBufferHandleImplNoLock(
332 const MojoDuplicateBufferHandleOptions
* /*options*/,
333 scoped_refptr
<Dispatcher
>* /*new_dispatcher*/) {
334 lock_
.AssertAcquired();
336 // By default, not supported. Only needed for buffer dispatchers.
337 return MOJO_RESULT_INVALID_ARGUMENT
;
340 MojoResult
Dispatcher::MapBufferImplNoLock(
342 uint64_t /*num_bytes*/,
343 MojoMapBufferFlags
/*flags*/,
344 scoped_ptr
<RawSharedBufferMapping
>* /*mapping*/) {
345 lock_
.AssertAcquired();
347 // By default, not supported. Only needed for buffer dispatchers.
348 return MOJO_RESULT_INVALID_ARGUMENT
;
351 MojoResult
Dispatcher::AddWaiterImplNoLock(Waiter
* /*waiter*/,
352 MojoWaitFlags
/*flags*/,
353 MojoResult
/*wake_result*/) {
354 lock_
.AssertAcquired();
356 // By default, waiting isn't supported. Only dispatchers that can be waited on
357 // will do something nontrivial.
358 return MOJO_RESULT_FAILED_PRECONDITION
;
361 void Dispatcher::RemoveWaiterImplNoLock(Waiter
* /*waiter*/) {
362 lock_
.AssertAcquired();
364 // By default, waiting isn't supported. Only dispatchers that can be waited on
365 // will do something nontrivial.
368 void Dispatcher::StartSerializeImplNoLock(Channel
* /*channel*/,
370 size_t* max_platform_handles
) {
371 DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
374 *max_platform_handles
= 0;
377 bool Dispatcher::EndSerializeAndCloseImplNoLock(
378 Channel
* /*channel*/,
379 void* /*destination*/,
380 size_t* /*actual_size*/,
381 embedder::PlatformHandleVector
* /*platform_handles*/) {
382 DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
384 // By default, serializing isn't supported, so just close.
389 bool Dispatcher::IsBusyNoLock() const {
390 lock_
.AssertAcquired();
392 // Most dispatchers support only "atomic" operations, so they are never busy
397 void Dispatcher::CloseNoLock() {
398 lock_
.AssertAcquired();
402 CancelAllWaitersNoLock();
406 scoped_refptr
<Dispatcher
>
407 Dispatcher::CreateEquivalentDispatcherAndCloseNoLock() {
408 lock_
.AssertAcquired();
412 CancelAllWaitersNoLock();
413 return CreateEquivalentDispatcherAndCloseImplNoLock();
416 void Dispatcher::StartSerialize(Channel
* channel
,
418 size_t* max_platform_handles
) {
421 DCHECK(max_platform_handles
);
422 DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
424 StartSerializeImplNoLock(channel
, max_size
, max_platform_handles
);
427 bool Dispatcher::EndSerializeAndClose(
431 embedder::PlatformHandleVector
* platform_handles
) {
434 DCHECK(HasOneRef()); // Only one ref => no need to take the lock.
437 // Like other |...Close()| methods, we mark ourselves as closed before calling
440 // No need to cancel waiters: we shouldn't have any (and shouldn't be in
441 // |Core|'s handle table.
444 // See the comment above |EndSerializeAndCloseImplNoLock()|. In brief: Locking
445 // isn't actually needed, but we need to satisfy assertions (which we don't
446 // want to remove or weaken).
447 base::AutoLock
locker(lock_
);
450 return EndSerializeAndCloseImplNoLock(channel
, destination
, actual_size
,
454 // DispatcherTransport ---------------------------------------------------------
456 void DispatcherTransport::End() {
458 dispatcher_
->lock_
.Release();
462 } // namespace system