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/core.h" | 5 #include "mojo/edk/system/core.h" |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/time/time.h" | 10 #include "base/time/time.h" |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
79 | 79 |
80 // TODO(vtl): This should take a |scoped_ptr<PlatformSupport>| as a parameter. | 80 // TODO(vtl): This should take a |scoped_ptr<PlatformSupport>| as a parameter. |
81 Core::Core(embedder::PlatformSupport* platform_support) | 81 Core::Core(embedder::PlatformSupport* platform_support) |
82 : platform_support_(platform_support) { | 82 : platform_support_(platform_support) { |
83 } | 83 } |
84 | 84 |
85 Core::~Core() { | 85 Core::~Core() { |
86 } | 86 } |
87 | 87 |
88 MojoHandle Core::AddDispatcher(const scoped_refptr<Dispatcher>& dispatcher) { | 88 MojoHandle Core::AddDispatcher(const scoped_refptr<Dispatcher>& dispatcher) { |
89 base::AutoLock locker(handle_table_lock_); | 89 MutexLocker locker(&handle_table_mutex_); |
90 return handle_table_.AddDispatcher(dispatcher); | 90 return handle_table_.AddDispatcher(dispatcher); |
91 } | 91 } |
92 | 92 |
93 scoped_refptr<Dispatcher> Core::GetDispatcher(MojoHandle handle) { | 93 scoped_refptr<Dispatcher> Core::GetDispatcher(MojoHandle handle) { |
94 if (handle == MOJO_HANDLE_INVALID) | 94 if (handle == MOJO_HANDLE_INVALID) |
95 return nullptr; | 95 return nullptr; |
96 | 96 |
97 base::AutoLock locker(handle_table_lock_); | 97 MutexLocker locker(&handle_table_mutex_); |
98 return handle_table_.GetDispatcher(handle); | 98 return handle_table_.GetDispatcher(handle); |
99 } | 99 } |
100 | 100 |
101 MojoResult Core::GetAndRemoveDispatcher(MojoHandle handle, | 101 MojoResult Core::GetAndRemoveDispatcher(MojoHandle handle, |
102 scoped_refptr<Dispatcher>* dispatcher) { | 102 scoped_refptr<Dispatcher>* dispatcher) { |
103 if (handle == MOJO_HANDLE_INVALID) | 103 if (handle == MOJO_HANDLE_INVALID) |
104 return MOJO_RESULT_INVALID_ARGUMENT; | 104 return MOJO_RESULT_INVALID_ARGUMENT; |
105 | 105 |
106 base::AutoLock locker(handle_table_lock_); | 106 MutexLocker locker(&handle_table_mutex_); |
107 return handle_table_.GetAndRemoveDispatcher(handle, dispatcher); | 107 return handle_table_.GetAndRemoveDispatcher(handle, dispatcher); |
108 } | 108 } |
109 | 109 |
110 MojoResult Core::AsyncWait(MojoHandle handle, | 110 MojoResult Core::AsyncWait(MojoHandle handle, |
111 MojoHandleSignals signals, | 111 MojoHandleSignals signals, |
112 const base::Callback<void(MojoResult)>& callback) { | 112 const base::Callback<void(MojoResult)>& callback) { |
113 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle); | 113 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handle); |
114 DCHECK(dispatcher); | 114 DCHECK(dispatcher); |
115 | 115 |
116 scoped_ptr<AsyncWaiter> waiter = make_scoped_ptr(new AsyncWaiter(callback)); | 116 scoped_ptr<AsyncWaiter> waiter = make_scoped_ptr(new AsyncWaiter(callback)); |
117 MojoResult rv = dispatcher->AddAwakable(waiter.get(), signals, 0, nullptr); | 117 MojoResult rv = dispatcher->AddAwakable(waiter.get(), signals, 0, nullptr); |
118 if (rv == MOJO_RESULT_OK) | 118 if (rv == MOJO_RESULT_OK) |
119 ignore_result(waiter.release()); | 119 ignore_result(waiter.release()); |
120 return rv; | 120 return rv; |
121 } | 121 } |
122 | 122 |
123 MojoTimeTicks Core::GetTimeTicksNow() { | 123 MojoTimeTicks Core::GetTimeTicksNow() { |
124 return base::TimeTicks::Now().ToInternalValue(); | 124 return base::TimeTicks::Now().ToInternalValue(); |
125 } | 125 } |
126 | 126 |
127 MojoResult Core::Close(MojoHandle handle) { | 127 MojoResult Core::Close(MojoHandle handle) { |
128 if (handle == MOJO_HANDLE_INVALID) | 128 if (handle == MOJO_HANDLE_INVALID) |
129 return MOJO_RESULT_INVALID_ARGUMENT; | 129 return MOJO_RESULT_INVALID_ARGUMENT; |
130 | 130 |
131 scoped_refptr<Dispatcher> dispatcher; | 131 scoped_refptr<Dispatcher> dispatcher; |
132 { | 132 { |
133 base::AutoLock locker(handle_table_lock_); | 133 MutexLocker locker(&handle_table_mutex_); |
134 MojoResult result = | 134 MojoResult result = |
135 handle_table_.GetAndRemoveDispatcher(handle, &dispatcher); | 135 handle_table_.GetAndRemoveDispatcher(handle, &dispatcher); |
136 if (result != MOJO_RESULT_OK) | 136 if (result != MOJO_RESULT_OK) |
137 return result; | 137 return result; |
138 } | 138 } |
139 | 139 |
140 // The dispatcher doesn't have a say in being closed, but gets notified of it. | 140 // The dispatcher doesn't have a say in being closed, but gets notified of it. |
141 // Note: This is done outside of |handle_table_lock_|. As a result, there's a | 141 // Note: This is done outside of |handle_table_mutex_|. As a result, there's a |
142 // race condition that the dispatcher must handle; see the comment in | 142 // race condition that the dispatcher must handle; see the comment in |
143 // |Dispatcher| in dispatcher.h. | 143 // |Dispatcher| in dispatcher.h. |
144 return dispatcher->Close(); | 144 return dispatcher->Close(); |
145 } | 145 } |
146 | 146 |
147 MojoResult Core::Wait(MojoHandle handle, | 147 MojoResult Core::Wait(MojoHandle handle, |
148 MojoHandleSignals signals, | 148 MojoHandleSignals signals, |
149 MojoDeadline deadline, | 149 MojoDeadline deadline, |
150 UserPointer<MojoHandleSignalsState> signals_state) { | 150 UserPointer<MojoHandleSignalsState> signals_state) { |
151 uint32_t unused = static_cast<uint32_t>(-1); | 151 uint32_t unused = static_cast<uint32_t>(-1); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
204 if (result != MOJO_RESULT_OK) | 204 if (result != MOJO_RESULT_OK) |
205 return result; | 205 return result; |
206 | 206 |
207 scoped_refptr<MessagePipeDispatcher> dispatcher0 = | 207 scoped_refptr<MessagePipeDispatcher> dispatcher0 = |
208 MessagePipeDispatcher::Create(validated_options); | 208 MessagePipeDispatcher::Create(validated_options); |
209 scoped_refptr<MessagePipeDispatcher> dispatcher1 = | 209 scoped_refptr<MessagePipeDispatcher> dispatcher1 = |
210 MessagePipeDispatcher::Create(validated_options); | 210 MessagePipeDispatcher::Create(validated_options); |
211 | 211 |
212 std::pair<MojoHandle, MojoHandle> handle_pair; | 212 std::pair<MojoHandle, MojoHandle> handle_pair; |
213 { | 213 { |
214 base::AutoLock locker(handle_table_lock_); | 214 MutexLocker locker(&handle_table_mutex_); |
215 handle_pair = handle_table_.AddDispatcherPair(dispatcher0, dispatcher1); | 215 handle_pair = handle_table_.AddDispatcherPair(dispatcher0, dispatcher1); |
216 } | 216 } |
217 if (handle_pair.first == MOJO_HANDLE_INVALID) { | 217 if (handle_pair.first == MOJO_HANDLE_INVALID) { |
218 DCHECK_EQ(handle_pair.second, MOJO_HANDLE_INVALID); | 218 DCHECK_EQ(handle_pair.second, MOJO_HANDLE_INVALID); |
219 LOG(ERROR) << "Handle table full"; | 219 LOG(ERROR) << "Handle table full"; |
220 dispatcher0->Close(); | 220 dispatcher0->Close(); |
221 dispatcher1->Close(); | 221 dispatcher1->Close(); |
222 return MOJO_RESULT_RESOURCE_EXHAUSTED; | 222 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
223 } | 223 } |
224 | 224 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
269 // |WriteMessage()| and also so that we can unlock their locks afterwards | 269 // |WriteMessage()| and also so that we can unlock their locks afterwards |
270 // without accessing the handle table. These can be dumb pointers, since their | 270 // without accessing the handle table. These can be dumb pointers, since their |
271 // entries in the handle table won't get removed (since they'll be marked as | 271 // entries in the handle table won't get removed (since they'll be marked as |
272 // busy). | 272 // busy). |
273 std::vector<DispatcherTransport> transports(num_handles); | 273 std::vector<DispatcherTransport> transports(num_handles); |
274 | 274 |
275 // When we pass handles, we have to try to take all their dispatchers' locks | 275 // When we pass handles, we have to try to take all their dispatchers' locks |
276 // and mark the handles as busy. If the call succeeds, we then remove the | 276 // and mark the handles as busy. If the call succeeds, we then remove the |
277 // handles from the handle table. | 277 // handles from the handle table. |
278 { | 278 { |
279 base::AutoLock locker(handle_table_lock_); | 279 MutexLocker locker(&handle_table_mutex_); |
280 MojoResult result = handle_table_.MarkBusyAndStartTransport( | 280 MojoResult result = handle_table_.MarkBusyAndStartTransport( |
281 message_pipe_handle, handles_reader.GetPointer(), num_handles, | 281 message_pipe_handle, handles_reader.GetPointer(), num_handles, |
282 &transports); | 282 &transports); |
283 if (result != MOJO_RESULT_OK) | 283 if (result != MOJO_RESULT_OK) |
284 return result; | 284 return result; |
285 } | 285 } |
286 | 286 |
287 MojoResult rv = | 287 MojoResult rv = |
288 dispatcher->WriteMessage(bytes, num_bytes, &transports, flags); | 288 dispatcher->WriteMessage(bytes, num_bytes, &transports, flags); |
289 | 289 |
290 // We need to release the dispatcher locks before we take the handle table | 290 // We need to release the dispatcher locks before we take the handle table |
291 // lock. | 291 // lock. |
292 for (uint32_t i = 0; i < num_handles; i++) | 292 for (uint32_t i = 0; i < num_handles; i++) |
293 transports[i].End(); | 293 transports[i].End(); |
294 | 294 |
295 { | 295 { |
296 base::AutoLock locker(handle_table_lock_); | 296 MutexLocker locker(&handle_table_mutex_); |
297 if (rv == MOJO_RESULT_OK) { | 297 if (rv == MOJO_RESULT_OK) { |
298 handle_table_.RemoveBusyHandles(handles_reader.GetPointer(), num_handles); | 298 handle_table_.RemoveBusyHandles(handles_reader.GetPointer(), num_handles); |
299 } else { | 299 } else { |
300 handle_table_.RestoreBusyHandles(handles_reader.GetPointer(), | 300 handle_table_.RestoreBusyHandles(handles_reader.GetPointer(), |
301 num_handles); | 301 num_handles); |
302 } | 302 } |
303 } | 303 } |
304 | 304 |
305 return rv; | 305 return rv; |
306 } | 306 } |
(...skipping 21 matching lines...) Expand all Loading... |
328 &num_handles_value, flags); | 328 &num_handles_value, flags); |
329 if (!dispatchers.empty()) { | 329 if (!dispatchers.empty()) { |
330 DCHECK_EQ(rv, MOJO_RESULT_OK); | 330 DCHECK_EQ(rv, MOJO_RESULT_OK); |
331 DCHECK(!num_handles.IsNull()); | 331 DCHECK(!num_handles.IsNull()); |
332 DCHECK_LE(dispatchers.size(), static_cast<size_t>(num_handles_value)); | 332 DCHECK_LE(dispatchers.size(), static_cast<size_t>(num_handles_value)); |
333 | 333 |
334 bool success; | 334 bool success; |
335 UserPointer<MojoHandle>::Writer handles_writer(handles, | 335 UserPointer<MojoHandle>::Writer handles_writer(handles, |
336 dispatchers.size()); | 336 dispatchers.size()); |
337 { | 337 { |
338 base::AutoLock locker(handle_table_lock_); | 338 MutexLocker locker(&handle_table_mutex_); |
339 success = handle_table_.AddDispatcherVector( | 339 success = handle_table_.AddDispatcherVector( |
340 dispatchers, handles_writer.GetPointer()); | 340 dispatchers, handles_writer.GetPointer()); |
341 } | 341 } |
342 if (success) { | 342 if (success) { |
343 handles_writer.Commit(); | 343 handles_writer.Commit(); |
344 } else { | 344 } else { |
345 LOG(ERROR) << "Received message with " << dispatchers.size() | 345 LOG(ERROR) << "Received message with " << dispatchers.size() |
346 << " handles, but handle table full"; | 346 << " handles, but handle table full"; |
347 // Close dispatchers (outside the lock). | 347 // Close dispatchers (outside the lock). |
348 for (size_t i = 0; i < dispatchers.size(); i++) { | 348 for (size_t i = 0; i < dispatchers.size(); i++) { |
(...skipping 21 matching lines...) Expand all Loading... |
370 if (result != MOJO_RESULT_OK) | 370 if (result != MOJO_RESULT_OK) |
371 return result; | 371 return result; |
372 | 372 |
373 scoped_refptr<DataPipeProducerDispatcher> producer_dispatcher = | 373 scoped_refptr<DataPipeProducerDispatcher> producer_dispatcher = |
374 DataPipeProducerDispatcher::Create(); | 374 DataPipeProducerDispatcher::Create(); |
375 scoped_refptr<DataPipeConsumerDispatcher> consumer_dispatcher = | 375 scoped_refptr<DataPipeConsumerDispatcher> consumer_dispatcher = |
376 DataPipeConsumerDispatcher::Create(); | 376 DataPipeConsumerDispatcher::Create(); |
377 | 377 |
378 std::pair<MojoHandle, MojoHandle> handle_pair; | 378 std::pair<MojoHandle, MojoHandle> handle_pair; |
379 { | 379 { |
380 base::AutoLock locker(handle_table_lock_); | 380 MutexLocker locker(&handle_table_mutex_); |
381 handle_pair = handle_table_.AddDispatcherPair(producer_dispatcher, | 381 handle_pair = handle_table_.AddDispatcherPair(producer_dispatcher, |
382 consumer_dispatcher); | 382 consumer_dispatcher); |
383 } | 383 } |
384 if (handle_pair.first == MOJO_HANDLE_INVALID) { | 384 if (handle_pair.first == MOJO_HANDLE_INVALID) { |
385 DCHECK_EQ(handle_pair.second, MOJO_HANDLE_INVALID); | 385 DCHECK_EQ(handle_pair.second, MOJO_HANDLE_INVALID); |
386 LOG(ERROR) << "Handle table full"; | 386 LOG(ERROR) << "Handle table full"; |
387 producer_dispatcher->Close(); | 387 producer_dispatcher->Close(); |
388 consumer_dispatcher->Close(); | 388 consumer_dispatcher->Close(); |
389 return MOJO_RESULT_RESOURCE_EXHAUSTED; | 389 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
390 } | 390 } |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
532 return MOJO_RESULT_INVALID_ARGUMENT; | 532 return MOJO_RESULT_INVALID_ARGUMENT; |
533 | 533 |
534 scoped_ptr<embedder::PlatformSharedBufferMapping> mapping; | 534 scoped_ptr<embedder::PlatformSharedBufferMapping> mapping; |
535 MojoResult result = dispatcher->MapBuffer(offset, num_bytes, flags, &mapping); | 535 MojoResult result = dispatcher->MapBuffer(offset, num_bytes, flags, &mapping); |
536 if (result != MOJO_RESULT_OK) | 536 if (result != MOJO_RESULT_OK) |
537 return result; | 537 return result; |
538 | 538 |
539 DCHECK(mapping); | 539 DCHECK(mapping); |
540 void* address = mapping->GetBase(); | 540 void* address = mapping->GetBase(); |
541 { | 541 { |
542 base::AutoLock locker(mapping_table_lock_); | 542 MutexLocker locker(&mapping_table_mutex_); |
543 result = mapping_table_.AddMapping(mapping.Pass()); | 543 result = mapping_table_.AddMapping(mapping.Pass()); |
544 } | 544 } |
545 if (result != MOJO_RESULT_OK) | 545 if (result != MOJO_RESULT_OK) |
546 return result; | 546 return result; |
547 | 547 |
548 buffer.Put(address); | 548 buffer.Put(address); |
549 return MOJO_RESULT_OK; | 549 return MOJO_RESULT_OK; |
550 } | 550 } |
551 | 551 |
552 MojoResult Core::UnmapBuffer(UserPointer<void> buffer) { | 552 MojoResult Core::UnmapBuffer(UserPointer<void> buffer) { |
553 base::AutoLock locker(mapping_table_lock_); | 553 MutexLocker locker(&mapping_table_mutex_); |
554 return mapping_table_.RemoveMapping(buffer.GetPointerValue()); | 554 return mapping_table_.RemoveMapping(buffer.GetPointerValue()); |
555 } | 555 } |
556 | 556 |
557 // Note: We allow |handles| to repeat the same handle multiple times, since | 557 // Note: We allow |handles| to repeat the same handle multiple times, since |
558 // different flags may be specified. | 558 // different flags may be specified. |
559 // TODO(vtl): This incurs a performance cost in |Remove()|. Analyze this | 559 // TODO(vtl): This incurs a performance cost in |Remove()|. Analyze this |
560 // more carefully and address it if necessary. | 560 // more carefully and address it if necessary. |
561 MojoResult Core::WaitManyInternal(const MojoHandle* handles, | 561 MojoResult Core::WaitManyInternal(const MojoHandle* handles, |
562 const MojoHandleSignals* signals, | 562 const MojoHandleSignals* signals, |
563 uint32_t num_handles, | 563 uint32_t num_handles, |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
609 if (signals_states) { | 609 if (signals_states) { |
610 for (; i < num_handles; i++) | 610 for (; i < num_handles; i++) |
611 signals_states[i] = dispatchers[i]->GetHandleSignalsState(); | 611 signals_states[i] = dispatchers[i]->GetHandleSignalsState(); |
612 } | 612 } |
613 | 613 |
614 return rv; | 614 return rv; |
615 } | 615 } |
616 | 616 |
617 } // namespace system | 617 } // namespace system |
618 } // namespace mojo | 618 } // namespace mojo |
OLD | NEW |