1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
|
#include "private/uds/channel_event_set.h"
#include <errno.h>
#include <log/log.h>
#include <poll.h>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <uds/ipc_helper.h>
namespace android {
namespace pdx {
namespace uds {
namespace {
template <typename FileHandleType>
Status<void> SetupHandle(int fd, FileHandleType* handle,
const char* error_name) {
const int error = errno;
handle->Reset(fd);
if (!*handle) {
ALOGE("SetupHandle: Failed to setup %s handle: %s", error_name,
strerror(error));
return ErrorStatus{error};
}
return {};
}
} // anonymous namespace
ChannelEventSet::ChannelEventSet() {
const int flags = EFD_CLOEXEC | EFD_NONBLOCK;
LocalHandle pollin_event_fd, pollhup_event_fd;
if (!SetupHandle(eventfd(0, flags), &pollin_event_fd, "pollin_event") ||
!SetupHandle(eventfd(0, flags), &pollhup_event_fd, "pollhup_event")) {
return;
}
pollin_event_fd_ = std::move(pollin_event_fd);
pollhup_event_fd_ = std::move(pollhup_event_fd);
}
int ChannelEventSet::ModifyEvents(int clear_mask, int set_mask) {
ALOGD_IF(TRACE, "ChannelEventSet::ModifyEvents: clear_mask=%x set_mask=%x",
clear_mask, set_mask);
const int old_bits = event_bits_;
const int new_bits = (event_bits_ & ~clear_mask) | set_mask;
event_bits_ = new_bits;
eventfd_t value;
// Calculate which bits changed and how. Bits that haven't changed since last
// modification will not change the state of an eventfd.
const int set_bits = new_bits & ~old_bits;
const int clear_bits = ~new_bits & old_bits;
if (set_bits & EPOLLIN)
eventfd_write(pollin_event_fd_.Get(), 1);
else if (clear_bits & EPOLLIN)
eventfd_read(pollin_event_fd_.Get(), &value);
if (set_bits & EPOLLHUP)
eventfd_write(pollhup_event_fd_.Get(), 1);
else if (clear_bits & EPOLLHUP)
eventfd_read(pollhup_event_fd_.Get(), &value);
return 0;
}
ChannelEventReceiver::ChannelEventReceiver(LocalHandle data_fd,
LocalHandle pollin_event_fd,
LocalHandle pollhup_event_fd) {
LocalHandle epoll_fd;
if (!SetupHandle(epoll_create1(EPOLL_CLOEXEC), &epoll_fd, "epoll")) {
return;
}
epoll_event event;
event.events = EPOLLHUP | EPOLLRDHUP;
event.data.u32 = 0;
if (epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, data_fd.Get(), &event) < 0) {
const int error = errno;
ALOGE("ChannelEventSet::ChannelEventSet: Failed to add data_fd: %s",
strerror(error));
return;
}
event.events = EPOLLIN;
event.data.u32 = 0;
if (epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, pollin_event_fd.Get(), &event) <
0) {
const int error = errno;
ALOGE("ChannelEventSet::ChannelEventSet: Failed to add pollin_event_fd: %s",
strerror(error));
return;
}
event.events = EPOLLIN;
event.data.u32 = 0;
if (epoll_ctl(epoll_fd.Get(), EPOLL_CTL_ADD, pollhup_event_fd.Get(), &event) <
0) {
const int error = errno;
ALOGE(
"ChannelEventSet::ChannelEventSet: Failed to add pollhup_event_fd: %s",
strerror(error));
return;
}
pollin_event_fd_ = std::move(pollin_event_fd);
pollhup_event_fd_ = std::move(pollhup_event_fd);
data_fd_ = std::move(data_fd);
epoll_fd_ = std::move(epoll_fd);
}
Status<int> ChannelEventReceiver::PollPendingEvents(int timeout_ms) const {
std::array<pollfd, 3> pfds = {{{pollin_event_fd_.Get(), POLLIN, 0},
{pollhup_event_fd_.Get(), POLLIN, 0},
{data_fd_.Get(), POLLHUP | POLLRDHUP, 0}}};
if (RETRY_EINTR(poll(pfds.data(), pfds.size(), timeout_ms)) < 0) {
const int error = errno;
ALOGE(
"ChannelEventReceiver::PollPendingEvents: Failed to poll for events: "
"%s",
strerror(error));
return ErrorStatus{error};
}
const int event_mask =
((pfds[0].revents & POLLIN) ? EPOLLIN : 0) |
((pfds[1].revents & POLLIN) ? EPOLLHUP : 0) |
((pfds[2].revents & (POLLHUP | POLLRDHUP)) ? EPOLLHUP : 0);
return {event_mask};
}
Status<int> ChannelEventReceiver::GetPendingEvents() const {
constexpr long kTimeoutMs = 0;
return PollPendingEvents(kTimeoutMs);
}
std::vector<ClientChannel::EventSource> ChannelEventReceiver::GetEventSources()
const {
return {{data_fd_.Get(), EPOLLHUP | EPOLLRDHUP},
{pollin_event_fd_.Get(), EPOLLIN},
{pollhup_event_fd_.Get(), POLLIN}};
}
} // namespace uds
} // namespace pdx
} // namespace android
|