mirror of
https://fuchsia.googlesource.com/third_party/pigweed.googlesource.com/pigweed/pigweed
synced 2024-07-12 01:23:34 +00:00
pw_async2_epoll: Use unordered_map; silence persistent warnings
Rather than adding and removing read and write wakers to a vector, use an unordered_map that maps a file descriptor to read and write wakers. Also, silence unnecessary warning logs. Previously, epoll dispatcher frequently emitted these warnings: WRN Received an event for registered file descriptor 4, but there is no task to wake This warning would occur with every read. This is because epoll emits both EPOLLIN and EPOLLOUT events when reading from a read/write channel, resulting in unhandled write events, even though no tasks are trying to write. Retain the log as a debug-level log, and only trigger it if no tasks were waiting for either reads or writes. Change-Id: I241776d8d9f6cce01fbdf95babebd48bd5bd81fe Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/218860 Reviewed-by: Alexei Frolov <frolv@google.com> Lint: Lint 🤖 <android-build-ayeaye@system.gserviceaccount.com> Pigweed-Auto-Submit: Wyatt Hepler <hepler@google.com> Commit-Queue: Wyatt Hepler <hepler@google.com>
This commit is contained in:
parent
8b8ad3820d
commit
62da50a4f4
|
@ -257,7 +257,7 @@ class Waker {
|
|||
friend class DispatcherImpl;
|
||||
|
||||
public:
|
||||
Waker() = default;
|
||||
constexpr Waker() = default;
|
||||
Waker(Waker&& other) noexcept PW_LOCKS_EXCLUDED(dispatcher_lock());
|
||||
|
||||
/// Replace this ``Waker`` with another.
|
||||
|
|
|
@ -124,15 +124,24 @@ Status Dispatcher::NativeWaitForWake() {
|
|||
PW_CHECK_INT_EQ(
|
||||
bytes_read, 1, "Dispatcher failed to read wake notification");
|
||||
PW_DCHECK_INT_EQ(unused, kNotificationSignal);
|
||||
} else {
|
||||
if ((event.events & (EPOLLIN | EPOLLRDHUP)) != 0) {
|
||||
NativeFindAndWakeFileDescriptor(event.data.fd,
|
||||
FileDescriptorType::kReadable);
|
||||
}
|
||||
if ((event.events & EPOLLOUT) != 0) {
|
||||
NativeFindAndWakeFileDescriptor(event.data.fd,
|
||||
FileDescriptorType::kWritable);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Debug log for missed events.
|
||||
if (PW_LOG_LEVEL >= PW_LOG_LEVEL_DEBUG &&
|
||||
wakers_[event.data.fd].read.IsEmpty() &&
|
||||
wakers_[event.data.fd].write.IsEmpty()) {
|
||||
PW_LOG_DEBUG(
|
||||
"Received an event for registered file descriptor %d, but there is "
|
||||
"no task to wake",
|
||||
event.data.fd);
|
||||
}
|
||||
|
||||
if ((event.events & (EPOLLIN | EPOLLRDHUP)) != 0) {
|
||||
std::move(wakers_[event.data.fd].read).Wake();
|
||||
}
|
||||
if ((event.events & EPOLLOUT) != 0) {
|
||||
std::move(wakers_[event.data.fd].write).Wake();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -167,35 +176,10 @@ Status Dispatcher::NativeUnregisterFileDescriptor(int fd) {
|
|||
PW_LOG_ERROR("Failed to unregister epoll event: %s", std::strerror(errno));
|
||||
return Status::Internal();
|
||||
}
|
||||
|
||||
auto fd_waker = std::find_if(fd_wakers_.begin(),
|
||||
fd_wakers_.end(),
|
||||
[fd](auto& f) { return f.fd == fd; });
|
||||
if (fd_waker != fd_wakers_.end()) {
|
||||
fd_wakers_.erase(fd_waker);
|
||||
}
|
||||
|
||||
wakers_.erase(fd);
|
||||
return OkStatus();
|
||||
}
|
||||
|
||||
void Dispatcher::NativeFindAndWakeFileDescriptor(int fd,
|
||||
FileDescriptorType type) {
|
||||
auto fd_waker =
|
||||
std::find_if(fd_wakers_.begin(), fd_wakers_.end(), [fd, type](auto& f) {
|
||||
return f.fd == fd && f.type == type;
|
||||
});
|
||||
if (fd_waker == fd_wakers_.end()) {
|
||||
PW_LOG_WARN(
|
||||
"Received an event for registered file descriptor %d, but there is no "
|
||||
"task to wake",
|
||||
fd);
|
||||
return;
|
||||
}
|
||||
|
||||
std::move(fd_waker->waker).Wake();
|
||||
fd_wakers_.erase(fd_waker);
|
||||
}
|
||||
|
||||
void Dispatcher::DoWake() {
|
||||
// Perform a write to unblock the waiting dispatcher.
|
||||
ssize_t bytes_written = write(notify_fd_, &kNotificationSignal, 1);
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
// the License.
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "pw_assert/assert.h"
|
||||
#include "pw_async2/dispatcher_base.h"
|
||||
|
@ -41,22 +41,19 @@ class Dispatcher final : public DispatcherImpl<Dispatcher> {
|
|||
Status NativeUnregisterFileDescriptor(int fd);
|
||||
|
||||
void NativeAddReadWakerForFileDescriptor(int fd, Waker&& waker) {
|
||||
NativeAddWakerForFileDescriptor(
|
||||
fd, FileDescriptorType::kReadable, std::move(waker));
|
||||
wakers_[fd].read = std::move(waker);
|
||||
}
|
||||
|
||||
void NativeAddWriteWakerForFileDescriptor(int fd, Waker&& waker) {
|
||||
NativeAddWakerForFileDescriptor(
|
||||
fd, FileDescriptorType::kWritable, std::move(waker));
|
||||
wakers_[fd].write = std::move(waker);
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr size_t kMaxEventsToProcessAtOnce = 5;
|
||||
|
||||
struct FdWaker {
|
||||
int fd;
|
||||
FileDescriptorType type;
|
||||
Waker waker;
|
||||
struct ReadWriteWaker {
|
||||
Waker read;
|
||||
Waker write;
|
||||
};
|
||||
|
||||
void DoWake() final;
|
||||
|
@ -67,17 +64,11 @@ class Dispatcher final : public DispatcherImpl<Dispatcher> {
|
|||
Status NativeWaitForWake();
|
||||
void NativeFindAndWakeFileDescriptor(int fd, FileDescriptorType type);
|
||||
|
||||
void NativeAddWakerForFileDescriptor(int fd,
|
||||
FileDescriptorType type,
|
||||
Waker&& waker) {
|
||||
fd_wakers_.push_back({fd, type, std::move(waker)});
|
||||
}
|
||||
|
||||
int epoll_fd_;
|
||||
int notify_fd_;
|
||||
int wait_fd_;
|
||||
|
||||
std::vector<FdWaker> fd_wakers_;
|
||||
std::unordered_map<int, ReadWriteWaker> wakers_;
|
||||
};
|
||||
|
||||
} // namespace pw::async2
|
||||
|
|
Loading…
Reference in New Issue
Block a user