Fuchsia: Use mx_handle_wait_many in the eventhandler
This is to set up for more handles coming in from sockets, etc. R=asiva@google.com Review URL: https://codereview.chromium.org/2438903002 .
This commit is contained in:
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -9,11 +9,82 @@
|
||||
#error Do not include eventhandler_fuchsia.h directly; use eventhandler.h instead.
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
#include <magenta/syscalls.h>
|
||||
|
||||
#include "platform/signal_blocker.h"
|
||||
|
||||
namespace dart {
|
||||
namespace bin {
|
||||
|
||||
class DescriptorInfo : public DescriptorInfoBase {
|
||||
public:
|
||||
explicit DescriptorInfo(intptr_t fd) : DescriptorInfoBase(fd) { }
|
||||
|
||||
virtual ~DescriptorInfo() { }
|
||||
|
||||
virtual void Close() {
|
||||
VOID_TEMP_FAILURE_RETRY(close(fd_));
|
||||
fd_ = -1;
|
||||
}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(DescriptorInfo);
|
||||
};
|
||||
|
||||
class DescriptorInfoSingle
|
||||
: public DescriptorInfoSingleMixin<DescriptorInfo> {
|
||||
public:
|
||||
explicit DescriptorInfoSingle(intptr_t fd)
|
||||
: DescriptorInfoSingleMixin(fd, false) {}
|
||||
virtual ~DescriptorInfoSingle() {}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(DescriptorInfoSingle);
|
||||
};
|
||||
|
||||
class DescriptorInfoMultiple
|
||||
: public DescriptorInfoMultipleMixin<DescriptorInfo> {
|
||||
public:
|
||||
explicit DescriptorInfoMultiple(intptr_t fd)
|
||||
: DescriptorInfoMultipleMixin(fd, false) {}
|
||||
virtual ~DescriptorInfoMultiple() {}
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(DescriptorInfoMultiple);
|
||||
};
|
||||
|
||||
// Information needed to call mx_handle_wait_many(), and to handle events.
|
||||
class MagentaWaitManyInfo {
|
||||
public:
|
||||
MagentaWaitManyInfo();
|
||||
~MagentaWaitManyInfo();
|
||||
|
||||
intptr_t capacity() const { return capacity_; }
|
||||
intptr_t size() const { return size_; }
|
||||
DescriptorInfo** descriptor_infos() const { return descriptor_infos_; }
|
||||
mx_handle_t* handles() const { return handles_; }
|
||||
mx_signals_t* signals() const { return signals_; }
|
||||
mx_signals_state_t* signals_states() const { return signals_states_; }
|
||||
|
||||
void AddHandle(mx_handle_t handle, mx_signals_t signals, DescriptorInfo* di);
|
||||
void RemoveHandle(mx_handle_t handle);
|
||||
|
||||
private:
|
||||
static const intptr_t kInitialCapacity = 32;
|
||||
|
||||
void GrowArraysIfNeeded(intptr_t desired_size);
|
||||
|
||||
intptr_t capacity_;
|
||||
intptr_t size_;
|
||||
DescriptorInfo** descriptor_infos_;
|
||||
mx_handle_t* handles_;
|
||||
mx_signals_t* signals_;
|
||||
mx_signals_state_t* signals_states_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(MagentaWaitManyInfo);
|
||||
};
|
||||
|
||||
class EventHandlerImplementation {
|
||||
public:
|
||||
EventHandlerImplementation();
|
||||
@@ -23,6 +94,8 @@ class EventHandlerImplementation {
|
||||
void Start(EventHandler* handler);
|
||||
void Shutdown();
|
||||
|
||||
const MagentaWaitManyInfo& info() const { return info_; }
|
||||
|
||||
private:
|
||||
int64_t GetTimeout() const;
|
||||
void HandleEvents();
|
||||
@@ -35,6 +108,8 @@ class EventHandlerImplementation {
|
||||
bool shutdown_;
|
||||
mx_handle_t interrupt_handles_[2];
|
||||
|
||||
MagentaWaitManyInfo info_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(EventHandlerImplementation);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user