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 29 matching lines...) Expand all Loading... |
40 // |MessagePipeDispatcher|) for each handle, with each handle having a strong | 40 // |MessagePipeDispatcher|) for each handle, with each handle having a strong |
41 // reference to the common "secondary" object (e.g., |MessagePipe|). This | 41 // reference to the common "secondary" object (e.g., |MessagePipe|). This |
42 // secondary object does NOT have any references to the |Dispatcher|s (even if | 42 // secondary object does NOT have any references to the |Dispatcher|s (even if |
43 // it did, it wouldn't be able to do anything with them due to lock order | 43 // it did, it wouldn't be able to do anything with them due to lock order |
44 // requirements -- see below). | 44 // requirements -- see below). |
45 // | 45 // |
46 // Waiting is implemented by having the thread that wants to wait call the | 46 // Waiting is implemented by having the thread that wants to wait call the |
47 // |Dispatcher|s for the handles that it wants to wait on with a |Waiter| | 47 // |Dispatcher|s for the handles that it wants to wait on with a |Waiter| |
48 // object; this |Waiter| object may be created on the stack of that thread or be | 48 // object; this |Waiter| object may be created on the stack of that thread or be |
49 // kept in thread local storage for that thread (TODO(vtl): future improvement). | 49 // kept in thread local storage for that thread (TODO(vtl): future improvement). |
50 // The |Dispatcher| then adds the |Waiter| to a |WaiterList| that's either owned | 50 // The |Dispatcher| then adds the |Waiter| to an |AwakableList| that's either |
51 // by that |Dispatcher| (see |SimpleDispatcher|) or by a secondary object (e.g., | 51 // owned by that |Dispatcher| (see |SimpleDispatcher|) or by a secondary object |
52 // |MessagePipe|). To signal/wake a |Waiter|, the object in question -- either a | 52 // (e.g., |MessagePipe|). To signal/wake a |Waiter|, the object in question -- |
53 // |SimpleDispatcher| or a secondary object -- talks to its |WaiterList|. | 53 // either a |SimpleDispatcher| or a secondary object -- talks to its |
| 54 // |AwakableList|. |
54 | 55 |
55 // Thread-safety notes | 56 // Thread-safety notes |
56 // | 57 // |
57 // Mojo primitives calls are thread-safe. We achieve this with relatively | 58 // Mojo primitives calls are thread-safe. We achieve this with relatively |
58 // fine-grained locking. There is a global handle table lock. This lock should | 59 // fine-grained locking. There is a global handle table lock. This lock should |
59 // be held as briefly as possible (TODO(vtl): a future improvement would be to | 60 // be held as briefly as possible (TODO(vtl): a future improvement would be to |
60 // switch it to a reader-writer lock). Each |Dispatcher| object then has a lock | 61 // switch it to a reader-writer lock). Each |Dispatcher| object then has a lock |
61 // (which subclasses can use to protect their data). | 62 // (which subclasses can use to protect their data). |
62 // | 63 // |
63 // The lock ordering is as follows: | 64 // The lock ordering is as follows: |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
214 // isn't done, in the in-process case, calls on the old handle may complete | 215 // isn't done, in the in-process case, calls on the old handle may complete |
215 // after the the message has been received and a new handle created (and | 216 // after the the message has been received and a new handle created (and |
216 // possibly even after calls have been made on the new handle). | 217 // possibly even after calls have been made on the new handle). |
217 MojoResult Core::WriteMessage(MojoHandle message_pipe_handle, | 218 MojoResult Core::WriteMessage(MojoHandle message_pipe_handle, |
218 UserPointer<const void> bytes, | 219 UserPointer<const void> bytes, |
219 uint32_t num_bytes, | 220 uint32_t num_bytes, |
220 UserPointer<const MojoHandle> handles, | 221 UserPointer<const MojoHandle> handles, |
221 uint32_t num_handles, | 222 uint32_t num_handles, |
222 MojoWriteMessageFlags flags) { | 223 MojoWriteMessageFlags flags) { |
223 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(message_pipe_handle)); | 224 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(message_pipe_handle)); |
224 if (!dispatcher.get()) | 225 if (!dispatcher) |
225 return MOJO_RESULT_INVALID_ARGUMENT; | 226 return MOJO_RESULT_INVALID_ARGUMENT; |
226 | 227 |
227 // Easy case: not sending any handles. | 228 // Easy case: not sending any handles. |
228 if (num_handles == 0) | 229 if (num_handles == 0) |
229 return dispatcher->WriteMessage(bytes, num_bytes, nullptr, flags); | 230 return dispatcher->WriteMessage(bytes, num_bytes, nullptr, flags); |
230 | 231 |
231 // We have to handle |handles| here, since we have to mark them busy in the | 232 // We have to handle |handles| here, since we have to mark them busy in the |
232 // global handle table. We can't delegate this to the dispatcher, since the | 233 // global handle table. We can't delegate this to the dispatcher, since the |
233 // handle table lock must be acquired before the dispatcher lock. | 234 // handle table lock must be acquired before the dispatcher lock. |
234 // | 235 // |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 return rv; | 282 return rv; |
282 } | 283 } |
283 | 284 |
284 MojoResult Core::ReadMessage(MojoHandle message_pipe_handle, | 285 MojoResult Core::ReadMessage(MojoHandle message_pipe_handle, |
285 UserPointer<void> bytes, | 286 UserPointer<void> bytes, |
286 UserPointer<uint32_t> num_bytes, | 287 UserPointer<uint32_t> num_bytes, |
287 UserPointer<MojoHandle> handles, | 288 UserPointer<MojoHandle> handles, |
288 UserPointer<uint32_t> num_handles, | 289 UserPointer<uint32_t> num_handles, |
289 MojoReadMessageFlags flags) { | 290 MojoReadMessageFlags flags) { |
290 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(message_pipe_handle)); | 291 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(message_pipe_handle)); |
291 if (!dispatcher.get()) | 292 if (!dispatcher) |
292 return MOJO_RESULT_INVALID_ARGUMENT; | 293 return MOJO_RESULT_INVALID_ARGUMENT; |
293 | 294 |
294 uint32_t num_handles_value = num_handles.IsNull() ? 0 : num_handles.Get(); | 295 uint32_t num_handles_value = num_handles.IsNull() ? 0 : num_handles.Get(); |
295 | 296 |
296 MojoResult rv; | 297 MojoResult rv; |
297 if (num_handles_value == 0) { | 298 if (num_handles_value == 0) { |
298 // Easy case: won't receive any handles. | 299 // Easy case: won't receive any handles. |
299 rv = dispatcher->ReadMessage(bytes, num_bytes, nullptr, &num_handles_value, | 300 rv = dispatcher->ReadMessage(bytes, num_bytes, nullptr, &num_handles_value, |
300 flags); | 301 flags); |
301 } else { | 302 } else { |
(...skipping 13 matching lines...) Expand all Loading... |
315 success = handle_table_.AddDispatcherVector( | 316 success = handle_table_.AddDispatcherVector( |
316 dispatchers, handles_writer.GetPointer()); | 317 dispatchers, handles_writer.GetPointer()); |
317 } | 318 } |
318 if (success) { | 319 if (success) { |
319 handles_writer.Commit(); | 320 handles_writer.Commit(); |
320 } else { | 321 } else { |
321 LOG(ERROR) << "Received message with " << dispatchers.size() | 322 LOG(ERROR) << "Received message with " << dispatchers.size() |
322 << " handles, but handle table full"; | 323 << " handles, but handle table full"; |
323 // Close dispatchers (outside the lock). | 324 // Close dispatchers (outside the lock). |
324 for (size_t i = 0; i < dispatchers.size(); i++) { | 325 for (size_t i = 0; i < dispatchers.size(); i++) { |
325 if (dispatchers[i].get()) | 326 if (dispatchers[i]) |
326 dispatchers[i]->Close(); | 327 dispatchers[i]->Close(); |
327 } | 328 } |
328 if (rv == MOJO_RESULT_OK) | 329 if (rv == MOJO_RESULT_OK) |
329 rv = MOJO_RESULT_RESOURCE_EXHAUSTED; | 330 rv = MOJO_RESULT_RESOURCE_EXHAUSTED; |
330 } | 331 } |
331 } | 332 } |
332 } | 333 } |
333 | 334 |
334 if (!num_handles.IsNull()) | 335 if (!num_handles.IsNull()) |
335 num_handles.Put(num_handles_value); | 336 num_handles.Put(num_handles_value); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 data_pipe_consumer_handle.Put(handle_pair.second); | 375 data_pipe_consumer_handle.Put(handle_pair.second); |
375 return MOJO_RESULT_OK; | 376 return MOJO_RESULT_OK; |
376 } | 377 } |
377 | 378 |
378 MojoResult Core::WriteData(MojoHandle data_pipe_producer_handle, | 379 MojoResult Core::WriteData(MojoHandle data_pipe_producer_handle, |
379 UserPointer<const void> elements, | 380 UserPointer<const void> elements, |
380 UserPointer<uint32_t> num_bytes, | 381 UserPointer<uint32_t> num_bytes, |
381 MojoWriteDataFlags flags) { | 382 MojoWriteDataFlags flags) { |
382 scoped_refptr<Dispatcher> dispatcher( | 383 scoped_refptr<Dispatcher> dispatcher( |
383 GetDispatcher(data_pipe_producer_handle)); | 384 GetDispatcher(data_pipe_producer_handle)); |
384 if (!dispatcher.get()) | 385 if (!dispatcher) |
385 return MOJO_RESULT_INVALID_ARGUMENT; | 386 return MOJO_RESULT_INVALID_ARGUMENT; |
386 | 387 |
387 return dispatcher->WriteData(elements, num_bytes, flags); | 388 return dispatcher->WriteData(elements, num_bytes, flags); |
388 } | 389 } |
389 | 390 |
390 MojoResult Core::BeginWriteData(MojoHandle data_pipe_producer_handle, | 391 MojoResult Core::BeginWriteData(MojoHandle data_pipe_producer_handle, |
391 UserPointer<void*> buffer, | 392 UserPointer<void*> buffer, |
392 UserPointer<uint32_t> buffer_num_bytes, | 393 UserPointer<uint32_t> buffer_num_bytes, |
393 MojoWriteDataFlags flags) { | 394 MojoWriteDataFlags flags) { |
394 scoped_refptr<Dispatcher> dispatcher( | 395 scoped_refptr<Dispatcher> dispatcher( |
395 GetDispatcher(data_pipe_producer_handle)); | 396 GetDispatcher(data_pipe_producer_handle)); |
396 if (!dispatcher.get()) | 397 if (!dispatcher) |
397 return MOJO_RESULT_INVALID_ARGUMENT; | 398 return MOJO_RESULT_INVALID_ARGUMENT; |
398 | 399 |
399 return dispatcher->BeginWriteData(buffer, buffer_num_bytes, flags); | 400 return dispatcher->BeginWriteData(buffer, buffer_num_bytes, flags); |
400 } | 401 } |
401 | 402 |
402 MojoResult Core::EndWriteData(MojoHandle data_pipe_producer_handle, | 403 MojoResult Core::EndWriteData(MojoHandle data_pipe_producer_handle, |
403 uint32_t num_bytes_written) { | 404 uint32_t num_bytes_written) { |
404 scoped_refptr<Dispatcher> dispatcher( | 405 scoped_refptr<Dispatcher> dispatcher( |
405 GetDispatcher(data_pipe_producer_handle)); | 406 GetDispatcher(data_pipe_producer_handle)); |
406 if (!dispatcher.get()) | 407 if (!dispatcher) |
407 return MOJO_RESULT_INVALID_ARGUMENT; | 408 return MOJO_RESULT_INVALID_ARGUMENT; |
408 | 409 |
409 return dispatcher->EndWriteData(num_bytes_written); | 410 return dispatcher->EndWriteData(num_bytes_written); |
410 } | 411 } |
411 | 412 |
412 MojoResult Core::ReadData(MojoHandle data_pipe_consumer_handle, | 413 MojoResult Core::ReadData(MojoHandle data_pipe_consumer_handle, |
413 UserPointer<void> elements, | 414 UserPointer<void> elements, |
414 UserPointer<uint32_t> num_bytes, | 415 UserPointer<uint32_t> num_bytes, |
415 MojoReadDataFlags flags) { | 416 MojoReadDataFlags flags) { |
416 scoped_refptr<Dispatcher> dispatcher( | 417 scoped_refptr<Dispatcher> dispatcher( |
417 GetDispatcher(data_pipe_consumer_handle)); | 418 GetDispatcher(data_pipe_consumer_handle)); |
418 if (!dispatcher.get()) | 419 if (!dispatcher) |
419 return MOJO_RESULT_INVALID_ARGUMENT; | 420 return MOJO_RESULT_INVALID_ARGUMENT; |
420 | 421 |
421 return dispatcher->ReadData(elements, num_bytes, flags); | 422 return dispatcher->ReadData(elements, num_bytes, flags); |
422 } | 423 } |
423 | 424 |
424 MojoResult Core::BeginReadData(MojoHandle data_pipe_consumer_handle, | 425 MojoResult Core::BeginReadData(MojoHandle data_pipe_consumer_handle, |
425 UserPointer<const void*> buffer, | 426 UserPointer<const void*> buffer, |
426 UserPointer<uint32_t> buffer_num_bytes, | 427 UserPointer<uint32_t> buffer_num_bytes, |
427 MojoReadDataFlags flags) { | 428 MojoReadDataFlags flags) { |
428 scoped_refptr<Dispatcher> dispatcher( | 429 scoped_refptr<Dispatcher> dispatcher( |
429 GetDispatcher(data_pipe_consumer_handle)); | 430 GetDispatcher(data_pipe_consumer_handle)); |
430 if (!dispatcher.get()) | 431 if (!dispatcher) |
431 return MOJO_RESULT_INVALID_ARGUMENT; | 432 return MOJO_RESULT_INVALID_ARGUMENT; |
432 | 433 |
433 return dispatcher->BeginReadData(buffer, buffer_num_bytes, flags); | 434 return dispatcher->BeginReadData(buffer, buffer_num_bytes, flags); |
434 } | 435 } |
435 | 436 |
436 MojoResult Core::EndReadData(MojoHandle data_pipe_consumer_handle, | 437 MojoResult Core::EndReadData(MojoHandle data_pipe_consumer_handle, |
437 uint32_t num_bytes_read) { | 438 uint32_t num_bytes_read) { |
438 scoped_refptr<Dispatcher> dispatcher( | 439 scoped_refptr<Dispatcher> dispatcher( |
439 GetDispatcher(data_pipe_consumer_handle)); | 440 GetDispatcher(data_pipe_consumer_handle)); |
440 if (!dispatcher.get()) | 441 if (!dispatcher) |
441 return MOJO_RESULT_INVALID_ARGUMENT; | 442 return MOJO_RESULT_INVALID_ARGUMENT; |
442 | 443 |
443 return dispatcher->EndReadData(num_bytes_read); | 444 return dispatcher->EndReadData(num_bytes_read); |
444 } | 445 } |
445 | 446 |
446 MojoResult Core::CreateSharedBuffer( | 447 MojoResult Core::CreateSharedBuffer( |
447 UserPointer<const MojoCreateSharedBufferOptions> options, | 448 UserPointer<const MojoCreateSharedBufferOptions> options, |
448 uint64_t num_bytes, | 449 uint64_t num_bytes, |
449 UserPointer<MojoHandle> shared_buffer_handle) { | 450 UserPointer<MojoHandle> shared_buffer_handle) { |
450 MojoCreateSharedBufferOptions validated_options = {}; | 451 MojoCreateSharedBufferOptions validated_options = {}; |
451 MojoResult result = SharedBufferDispatcher::ValidateCreateOptions( | 452 MojoResult result = SharedBufferDispatcher::ValidateCreateOptions( |
452 options, &validated_options); | 453 options, &validated_options); |
453 if (result != MOJO_RESULT_OK) | 454 if (result != MOJO_RESULT_OK) |
454 return result; | 455 return result; |
455 | 456 |
456 scoped_refptr<SharedBufferDispatcher> dispatcher; | 457 scoped_refptr<SharedBufferDispatcher> dispatcher; |
457 result = SharedBufferDispatcher::Create(platform_support(), validated_options, | 458 result = SharedBufferDispatcher::Create(platform_support(), validated_options, |
458 num_bytes, &dispatcher); | 459 num_bytes, &dispatcher); |
459 if (result != MOJO_RESULT_OK) { | 460 if (result != MOJO_RESULT_OK) { |
460 DCHECK(!dispatcher.get()); | 461 DCHECK(!dispatcher); |
461 return result; | 462 return result; |
462 } | 463 } |
463 | 464 |
464 MojoHandle h = AddDispatcher(dispatcher); | 465 MojoHandle h = AddDispatcher(dispatcher); |
465 if (h == MOJO_HANDLE_INVALID) { | 466 if (h == MOJO_HANDLE_INVALID) { |
466 LOG(ERROR) << "Handle table full"; | 467 LOG(ERROR) << "Handle table full"; |
467 dispatcher->Close(); | 468 dispatcher->Close(); |
468 return MOJO_RESULT_RESOURCE_EXHAUSTED; | 469 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
469 } | 470 } |
470 | 471 |
471 shared_buffer_handle.Put(h); | 472 shared_buffer_handle.Put(h); |
472 return MOJO_RESULT_OK; | 473 return MOJO_RESULT_OK; |
473 } | 474 } |
474 | 475 |
475 MojoResult Core::DuplicateBufferHandle( | 476 MojoResult Core::DuplicateBufferHandle( |
476 MojoHandle buffer_handle, | 477 MojoHandle buffer_handle, |
477 UserPointer<const MojoDuplicateBufferHandleOptions> options, | 478 UserPointer<const MojoDuplicateBufferHandleOptions> options, |
478 UserPointer<MojoHandle> new_buffer_handle) { | 479 UserPointer<MojoHandle> new_buffer_handle) { |
479 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle)); | 480 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle)); |
480 if (!dispatcher.get()) | 481 if (!dispatcher) |
481 return MOJO_RESULT_INVALID_ARGUMENT; | 482 return MOJO_RESULT_INVALID_ARGUMENT; |
482 | 483 |
483 // Don't verify |options| here; that's the dispatcher's job. | 484 // Don't verify |options| here; that's the dispatcher's job. |
484 scoped_refptr<Dispatcher> new_dispatcher; | 485 scoped_refptr<Dispatcher> new_dispatcher; |
485 MojoResult result = | 486 MojoResult result = |
486 dispatcher->DuplicateBufferHandle(options, &new_dispatcher); | 487 dispatcher->DuplicateBufferHandle(options, &new_dispatcher); |
487 if (result != MOJO_RESULT_OK) | 488 if (result != MOJO_RESULT_OK) |
488 return result; | 489 return result; |
489 | 490 |
490 MojoHandle new_handle = AddDispatcher(new_dispatcher); | 491 MojoHandle new_handle = AddDispatcher(new_dispatcher); |
491 if (new_handle == MOJO_HANDLE_INVALID) { | 492 if (new_handle == MOJO_HANDLE_INVALID) { |
492 LOG(ERROR) << "Handle table full"; | 493 LOG(ERROR) << "Handle table full"; |
493 dispatcher->Close(); | 494 dispatcher->Close(); |
494 return MOJO_RESULT_RESOURCE_EXHAUSTED; | 495 return MOJO_RESULT_RESOURCE_EXHAUSTED; |
495 } | 496 } |
496 | 497 |
497 new_buffer_handle.Put(new_handle); | 498 new_buffer_handle.Put(new_handle); |
498 return MOJO_RESULT_OK; | 499 return MOJO_RESULT_OK; |
499 } | 500 } |
500 | 501 |
501 MojoResult Core::MapBuffer(MojoHandle buffer_handle, | 502 MojoResult Core::MapBuffer(MojoHandle buffer_handle, |
502 uint64_t offset, | 503 uint64_t offset, |
503 uint64_t num_bytes, | 504 uint64_t num_bytes, |
504 UserPointer<void*> buffer, | 505 UserPointer<void*> buffer, |
505 MojoMapBufferFlags flags) { | 506 MojoMapBufferFlags flags) { |
506 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle)); | 507 scoped_refptr<Dispatcher> dispatcher(GetDispatcher(buffer_handle)); |
507 if (!dispatcher.get()) | 508 if (!dispatcher) |
508 return MOJO_RESULT_INVALID_ARGUMENT; | 509 return MOJO_RESULT_INVALID_ARGUMENT; |
509 | 510 |
510 scoped_ptr<embedder::PlatformSharedBufferMapping> mapping; | 511 scoped_ptr<embedder::PlatformSharedBufferMapping> mapping; |
511 MojoResult result = dispatcher->MapBuffer(offset, num_bytes, flags, &mapping); | 512 MojoResult result = dispatcher->MapBuffer(offset, num_bytes, flags, &mapping); |
512 if (result != MOJO_RESULT_OK) | 513 if (result != MOJO_RESULT_OK) |
513 return result; | 514 return result; |
514 | 515 |
515 DCHECK(mapping); | 516 DCHECK(mapping); |
516 void* address = mapping->GetBase(); | 517 void* address = mapping->GetBase(); |
517 { | 518 { |
518 base::AutoLock locker(mapping_table_lock_); | 519 base::AutoLock locker(mapping_table_lock_); |
519 result = mapping_table_.AddMapping(mapping.Pass()); | 520 result = mapping_table_.AddMapping(mapping.Pass()); |
520 } | 521 } |
521 if (result != MOJO_RESULT_OK) | 522 if (result != MOJO_RESULT_OK) |
522 return result; | 523 return result; |
523 | 524 |
524 buffer.Put(address); | 525 buffer.Put(address); |
525 return MOJO_RESULT_OK; | 526 return MOJO_RESULT_OK; |
526 } | 527 } |
527 | 528 |
528 MojoResult Core::UnmapBuffer(UserPointer<void> buffer) { | 529 MojoResult Core::UnmapBuffer(UserPointer<void> buffer) { |
529 base::AutoLock locker(mapping_table_lock_); | 530 base::AutoLock locker(mapping_table_lock_); |
530 return mapping_table_.RemoveMapping(buffer.GetPointerValue()); | 531 return mapping_table_.RemoveMapping(buffer.GetPointerValue()); |
531 } | 532 } |
532 | 533 |
533 // Note: We allow |handles| to repeat the same handle multiple times, since | 534 // Note: We allow |handles| to repeat the same handle multiple times, since |
534 // different flags may be specified. | 535 // different flags may be specified. |
535 // TODO(vtl): This incurs a performance cost in |RemoveWaiter()|. Analyze this | 536 // TODO(vtl): This incurs a performance cost in |Remove()|. Analyze this |
536 // more carefully and address it if necessary. | 537 // more carefully and address it if necessary. |
537 MojoResult Core::WaitManyInternal(const MojoHandle* handles, | 538 MojoResult Core::WaitManyInternal(const MojoHandle* handles, |
538 const MojoHandleSignals* signals, | 539 const MojoHandleSignals* signals, |
539 uint32_t num_handles, | 540 uint32_t num_handles, |
540 MojoDeadline deadline, | 541 MojoDeadline deadline, |
541 uint32_t* result_index, | 542 uint32_t* result_index, |
542 HandleSignalsState* signals_states) { | 543 HandleSignalsState* signals_states) { |
543 DCHECK_GT(num_handles, 0u); | 544 DCHECK_GT(num_handles, 0u); |
544 DCHECK_EQ(*result_index, static_cast<uint32_t>(-1)); | 545 DCHECK_EQ(*result_index, static_cast<uint32_t>(-1)); |
545 | 546 |
546 DispatcherVector dispatchers; | 547 DispatcherVector dispatchers; |
547 dispatchers.reserve(num_handles); | 548 dispatchers.reserve(num_handles); |
548 for (uint32_t i = 0; i < num_handles; i++) { | 549 for (uint32_t i = 0; i < num_handles; i++) { |
549 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handles[i]); | 550 scoped_refptr<Dispatcher> dispatcher = GetDispatcher(handles[i]); |
550 if (!dispatcher.get()) { | 551 if (!dispatcher) { |
551 *result_index = i; | 552 *result_index = i; |
552 return MOJO_RESULT_INVALID_ARGUMENT; | 553 return MOJO_RESULT_INVALID_ARGUMENT; |
553 } | 554 } |
554 dispatchers.push_back(dispatcher); | 555 dispatchers.push_back(dispatcher); |
555 } | 556 } |
556 | 557 |
557 // TODO(vtl): Should make the waiter live (permanently) in TLS. | 558 // TODO(vtl): Should make the waiter live (permanently) in TLS. |
558 Waiter waiter; | 559 Waiter waiter; |
559 waiter.Init(); | 560 waiter.Init(); |
560 | 561 |
561 uint32_t i; | 562 uint32_t i; |
562 MojoResult rv = MOJO_RESULT_OK; | 563 MojoResult rv = MOJO_RESULT_OK; |
563 for (i = 0; i < num_handles; i++) { | 564 for (i = 0; i < num_handles; i++) { |
564 rv = dispatchers[i]->AddWaiter( | 565 rv = dispatchers[i]->AddAwakable( |
565 &waiter, signals[i], i, signals_states ? &signals_states[i] : nullptr); | 566 &waiter, signals[i], i, signals_states ? &signals_states[i] : nullptr); |
566 if (rv != MOJO_RESULT_OK) { | 567 if (rv != MOJO_RESULT_OK) { |
567 *result_index = i; | 568 *result_index = i; |
568 break; | 569 break; |
569 } | 570 } |
570 } | 571 } |
571 uint32_t num_added = i; | 572 uint32_t num_added = i; |
572 | 573 |
573 if (rv == MOJO_RESULT_ALREADY_EXISTS) | 574 if (rv == MOJO_RESULT_ALREADY_EXISTS) |
574 rv = MOJO_RESULT_OK; // The i-th one is already "triggered". | 575 rv = MOJO_RESULT_OK; // The i-th one is already "triggered". |
575 else if (rv == MOJO_RESULT_OK) | 576 else if (rv == MOJO_RESULT_OK) |
576 rv = waiter.Wait(deadline, result_index); | 577 rv = waiter.Wait(deadline, result_index); |
577 | 578 |
578 // Make sure no other dispatchers try to wake |waiter| for the current | 579 // Make sure no other dispatchers try to wake |waiter| for the current |
579 // |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be | 580 // |Wait()|/|WaitMany()| call. (Only after doing this can |waiter| be |
580 // destroyed, but this would still be required if the waiter were in TLS.) | 581 // destroyed, but this would still be required if the waiter were in TLS.) |
581 for (i = 0; i < num_added; i++) { | 582 for (i = 0; i < num_added; i++) { |
582 dispatchers[i]->RemoveWaiter(&waiter, | 583 dispatchers[i]->RemoveAwakable( |
583 signals_states ? &signals_states[i] : nullptr); | 584 &waiter, signals_states ? &signals_states[i] : nullptr); |
584 } | 585 } |
585 if (signals_states) { | 586 if (signals_states) { |
586 for (; i < num_handles; i++) | 587 for (; i < num_handles; i++) |
587 signals_states[i] = dispatchers[i]->GetHandleSignalsState(); | 588 signals_states[i] = dispatchers[i]->GetHandleSignalsState(); |
588 } | 589 } |
589 | 590 |
590 return rv; | 591 return rv; |
591 } | 592 } |
592 | 593 |
593 } // namespace system | 594 } // namespace system |
594 } // namespace mojo | 595 } // namespace mojo |
OLD | NEW |