| Index: runtime/bin/eventhandler_fuchsia.cc | 
| diff --git a/runtime/bin/eventhandler_fuchsia.cc b/runtime/bin/eventhandler_fuchsia.cc | 
| index ff03f14ab9e9f756a9efff034b89e54dc3859d4e..0d52f55cae07abe1df2558404b6fae8799066e4d 100644 | 
| --- a/runtime/bin/eventhandler_fuchsia.cc | 
| +++ b/runtime/bin/eventhandler_fuchsia.cc | 
| @@ -13,18 +13,146 @@ | 
| #include <magenta/status.h> | 
| #include <magenta/syscalls.h> | 
|  | 
| +#include "bin/log.h" | 
| #include "bin/thread.h" | 
| #include "bin/utils.h" | 
|  | 
| +#if defined(EVENTHANDLER_LOGGING) | 
| +#define LOG_ERR(msg, ...) Log::PrintErr(msg, ##__VA_ARGS__) | 
| +#define LOG_INFO(msg, ...) Log::Print(msg, ##__VA_ARGS__) | 
| +#else | 
| +#define LOG_ERR(msg, ...) | 
| +#define LOG_INFO(msg, ...) | 
| +#endif  // defined(EVENTHANDLER_LOGGING) | 
| + | 
| namespace dart { | 
| namespace bin { | 
|  | 
| +MagentaWaitManyInfo::MagentaWaitManyInfo() | 
| +    : capacity_(kInitialCapacity), | 
| +      size_(0) { | 
| +  descriptor_infos_ = static_cast<DescriptorInfo**>( | 
| +      malloc(kInitialCapacity * sizeof(*descriptor_infos_))); | 
| +  if (descriptor_infos_ == NULL) { | 
| +    FATAL("Failed to allocate descriptor_infos array"); | 
| +  } | 
| +  handles_ = static_cast<mx_handle_t*>( | 
| +      malloc(kInitialCapacity * sizeof(*handles_))); | 
| +  if (handles_ == NULL) { | 
| +    FATAL("Failed to allocate handles array"); | 
| +  } | 
| +  signals_ = static_cast<mx_signals_t*>( | 
| +      malloc(kInitialCapacity * sizeof(*signals_))); | 
| +  if (signals_ == NULL) { | 
| +    FATAL("Failed to allocate signals array"); | 
| +  } | 
| +  signals_states_ = static_cast<mx_signals_state_t*>( | 
| +      malloc(kInitialCapacity * sizeof(*signals_states_))); | 
| +  if (signals_states_ == NULL) { | 
| +    FATAL("Failed to allocate signals_states array"); | 
| +  } | 
| +} | 
| + | 
| + | 
| +MagentaWaitManyInfo::~MagentaWaitManyInfo() { | 
| +  free(descriptor_infos_); | 
| +  free(handles_); | 
| +  free(signals_); | 
| +  free(signals_states_); | 
| +} | 
| + | 
| + | 
| +void MagentaWaitManyInfo::AddHandle(mx_handle_t handle, | 
| +                                    mx_signals_t signals, | 
| +                                    DescriptorInfo* di) { | 
| +#if defined(DEBUG) | 
| +  // Check that the handle is not already in the list. | 
| +  for (intptr_t i = 0; i < size_; i++) { | 
| +    if (handles_[i] == handle) { | 
| +      FATAL("The handle is already in the list!"); | 
| +    } | 
| +  } | 
| +#endif | 
| +  intptr_t new_size = size_ + 1; | 
| +  GrowArraysIfNeeded(new_size); | 
| +  descriptor_infos_[size_] = di; | 
| +  handles_[size_] = handle; | 
| +  signals_[size_] = signals; | 
| +  signals_states_[size_].satisfied = MX_SIGNAL_NONE; | 
| +  signals_states_[size_].satisfiable = MX_SIGNAL_NONE; | 
| +  size_ = new_size; | 
| +  LOG_INFO("AddHandle(%ld, %ld, %p), size = %ld\n", handle, signals, di, size_); | 
| +} | 
| + | 
| + | 
| +void MagentaWaitManyInfo::RemoveHandle(mx_handle_t handle) { | 
| +  intptr_t idx; | 
| +  for (idx = 1; idx < size_; idx++) { | 
| +    if (handle == handles_[idx]) { | 
| +      break; | 
| +    } | 
| +  } | 
| +  if (idx == size_) { | 
| +    FATAL("Handle is not in the list!"); | 
| +  } | 
| + | 
| +  if (idx != (size_ - 1)) { | 
| +    descriptor_infos_[idx] = descriptor_infos_[size_ - 1]; | 
| +    handles_[idx] = handles_[size_ - 1]; | 
| +    signals_[idx] = signals_[size_ - 1]; | 
| +    signals_states_[idx] = signals_states_[size_ - 1]; | 
| +  } | 
| +  descriptor_infos_[size_ - 1] = NULL; | 
| +  handles_[size_ - 1] = MX_HANDLE_INVALID; | 
| +  signals_[size_ - 1] = MX_SIGNAL_NONE; | 
| +  signals_states_[size_ - 1].satisfied = MX_SIGNAL_NONE; | 
| +  signals_states_[size_ - 1].satisfiable = MX_SIGNAL_NONE; | 
| +  size_ = size_ - 1; | 
| +  LOG_INFO("RemoveHandle(%ld), size = %ld\n", handle, size_); | 
| +} | 
| + | 
| + | 
| +void MagentaWaitManyInfo::GrowArraysIfNeeded(intptr_t desired_size) { | 
| +  if (desired_size < capacity_) { | 
| +    return; | 
| +  } | 
| +  intptr_t new_capacity = desired_size + (desired_size >> 1); | 
| +  descriptor_infos_ = static_cast<DescriptorInfo**>( | 
| +      realloc(descriptor_infos_, new_capacity * sizeof(*descriptor_infos_))); | 
| +  if (descriptor_infos_ == NULL) { | 
| +    FATAL("Failed to grow descriptor_infos array"); | 
| +  } | 
| +  handles_ = static_cast<mx_handle_t*>( | 
| +      realloc(handles_, new_capacity * sizeof(*handles_))); | 
| +  if (handles_ == NULL) { | 
| +    FATAL("Failed to grow handles array"); | 
| +  } | 
| +  signals_ = static_cast<mx_signals_t*>( | 
| +      realloc(signals_, new_capacity * sizeof(*signals_))); | 
| +  if (signals_ == NULL) { | 
| +    FATAL("Failed to grow signals array"); | 
| +  } | 
| +  signals_states_ = static_cast<mx_signals_state_t*>( | 
| +      realloc(signals_states_, new_capacity * sizeof(*signals_states_))); | 
| +  if (signals_states_ == NULL) { | 
| +    FATAL("Failed to grow signals_states array"); | 
| +  } | 
| +  capacity_ = new_capacity; | 
| +  LOG_INFO("GrowArraysIfNeeded(%ld), capacity = %ld\n", | 
| +           desired_size, capacity_); | 
| +} | 
| + | 
| + | 
| EventHandlerImplementation::EventHandlerImplementation() { | 
| mx_status_t status = mx_msgpipe_create(interrupt_handles_, 0); | 
| if (status != NO_ERROR) { | 
| FATAL1("mx_msgpipe_create failed: %s\n", mx_status_get_string(status)); | 
| } | 
| shutdown_ = false; | 
| +  info_.AddHandle(interrupt_handles_[0], | 
| +                  MX_SIGNAL_READABLE | MX_SIGNAL_PEER_CLOSED, | 
| +                  NULL); | 
| +  LOG_INFO("EventHandlerImplementation initialized\n"); | 
| } | 
|  | 
|  | 
| @@ -37,6 +165,7 @@ EventHandlerImplementation::~EventHandlerImplementation() { | 
| if (status != NO_ERROR) { | 
| FATAL1("mx_handle_close failed: %s\n", mx_status_get_string(status)); | 
| } | 
| +  LOG_INFO("EventHandlerImplementation destroyed\n"); | 
| } | 
|  | 
|  | 
| @@ -53,10 +182,12 @@ void EventHandlerImplementation::WakeupHandler(intptr_t id, | 
| if (status != NO_ERROR) { | 
| FATAL1("mx_msgpipe_write failed: %s\n", mx_status_get_string(status)); | 
| } | 
| +  LOG_INFO("WakeupHandler(%ld, %ld, %lld)\n", id, dart_port, data); | 
| } | 
|  | 
|  | 
| void EventHandlerImplementation::HandleInterruptFd() { | 
| +  LOG_INFO("HandleInterruptFd entry\n"); | 
| InterruptMessage msg; | 
| uint32_t bytes = kInterruptMessageSize; | 
| mx_status_t status; | 
| @@ -68,10 +199,14 @@ void EventHandlerImplementation::HandleInterruptFd() { | 
| } | 
| ASSERT(bytes == kInterruptMessageSize); | 
| if (msg.id == kTimerId) { | 
| +      LOG_INFO("HandleInterruptFd read timer update\n"); | 
| timeout_queue_.UpdateTimeout(msg.dart_port, msg.data); | 
| } else if (msg.id == kShutdownId) { | 
| +      LOG_INFO("HandleInterruptFd read shutdown\n"); | 
| shutdown_ = true; | 
| } else { | 
| +      // TODO(zra): Handle commands to add and remove handles from the | 
| +      // MagentaWaitManyInfo. | 
| UNIMPLEMENTED(); | 
| } | 
| } | 
| @@ -80,13 +215,32 @@ void EventHandlerImplementation::HandleInterruptFd() { | 
| if (status != ERR_SHOULD_WAIT) { | 
| FATAL1("mx_msgpipe_read failed: %s\n", mx_status_get_string(status)); | 
| } | 
| +  LOG_INFO("HandleInterruptFd exit\n"); | 
| } | 
|  | 
|  | 
| void EventHandlerImplementation::HandleEvents() { | 
| -  // TODO(zra): Handle events from other handles. At the moment we are only | 
| -  // interrupted when there is a message on interrupt_handles_[0]. | 
| -  HandleInterruptFd(); | 
| +  LOG_INFO("HandleEvents entry\n"); | 
| +  for (intptr_t i = 1; i < info_.size(); i++) { | 
| +    if (info_.signals_states()[i].satisfied != MX_SIGNAL_NONE) { | 
| +      // Only the control handle has no descriptor info. | 
| +      ASSERT(info_.descriptor_infos()[i] != NULL); | 
| +      ASSERT(info_.handles()[i] != interrupt_handles_[0]); | 
| +      // TODO(zra): Handle events on other handles. At the moment we are | 
| +      // only interrupted when there is a message on interrupt_handles_[0]. | 
| +      UNIMPLEMENTED(); | 
| +    } | 
| +  } | 
| + | 
| +  if ((info_.signals_states()[0].satisfied & MX_SIGNAL_PEER_CLOSED) != 0) { | 
| +    FATAL("EventHandlerImplementation::Poll: Unexpected peer closed\n"); | 
| +  } | 
| +  if ((info_.signals_states()[0].satisfied & MX_SIGNAL_READABLE) != 0) { | 
| +    LOG_INFO("HandleEvents interrupt_handles_[0] readable\n"); | 
| +    HandleInterruptFd(); | 
| +  } else { | 
| +    LOG_INFO("HandleEvents interrupt_handles_[0] not readable\n"); | 
| +  } | 
| } | 
|  | 
|  | 
| @@ -120,28 +274,30 @@ void EventHandlerImplementation::Poll(uword args) { | 
| while (!handler_impl->shutdown_) { | 
| int64_t millis = handler_impl->GetTimeout(); | 
| ASSERT((millis == kInfinityTimeout) || (millis >= 0)); | 
| - | 
| mx_time_t timeout = | 
| millis * kMicrosecondsPerMillisecond * kNanosecondsPerMicrosecond; | 
| -    mx_signals_state_t signals_state; | 
| -    mx_status_t status = mx_handle_wait_one( | 
| -        handler_impl->interrupt_handles_[0], | 
| -        MX_SIGNAL_READABLE | MX_SIGNAL_PEER_CLOSED, | 
| +    const MagentaWaitManyInfo& info = handler_impl->info(); | 
| +    uint32_t result_index; | 
| +    LOG_INFO("mx_handle_wait_many(%ld, %p, %p, %lld, %p, %p)\n", | 
| +        info.size(), info.handles(), info.signals(), timeout, &result_index, | 
| +        info.signals_states()); | 
| +    mx_status_t status = mx_handle_wait_many( | 
| +        info.size(), | 
| +        info.handles(), | 
| +        info.signals(), | 
| timeout, | 
| -        &signals_state); | 
| +        &result_index, | 
| +        info.signals_states()); | 
| if ((status != NO_ERROR) && (status != ERR_TIMED_OUT)) { | 
| -      FATAL1("mx_handle_wait_one failed: %s\n", mx_status_get_string(status)); | 
| +      FATAL1("mx_handle_wait_many failed: %s\n", mx_status_get_string(status)); | 
| } else { | 
| +      LOG_INFO("mx_handle_wait_many returned: %ld\n", status); | 
| handler_impl->HandleTimeout(); | 
| -      if ((signals_state.satisfied & MX_SIGNAL_READABLE) != 0) { | 
| -        handler_impl->HandleEvents(); | 
| -      } | 
| -      if ((signals_state.satisfied & MX_SIGNAL_PEER_CLOSED) != 0) { | 
| -        FATAL("EventHandlerImplementation::Poll: Unexpected peer closed\n"); | 
| -      } | 
| +      handler_impl->HandleEvents(); | 
| } | 
| } | 
| handler->NotifyShutdownDone(); | 
| +  LOG_INFO("EventHandlerImplementation notifying about shutdown\n"); | 
| } | 
|  | 
|  | 
|  |