Kernel: Use HashMap for fd->epoll_event mapping

I don't know why it was a static array :D
This commit is contained in:
2026-04-21 00:10:42 +03:00
parent fe613e4274
commit a8e496310b
2 changed files with 28 additions and 31 deletions

View File

@@ -1,12 +1,8 @@
#pragma once #pragma once
#include <BAN/Array.h>
#include <BAN/CircularQueue.h>
#include <BAN/HashMap.h> #include <BAN/HashMap.h>
#include <BAN/HashSet.h>
#include <kernel/FS/Inode.h> #include <kernel/FS/Inode.h>
#include <limits.h>
#include <sys/epoll.h> #include <sys/epoll.h>
namespace Kernel namespace Kernel
@@ -63,38 +59,41 @@ namespace Kernel
struct ListenEventList struct ListenEventList
{ {
BAN::Array<epoll_event, OPEN_MAX> events; ListenEventList() = default;
uint32_t bitmap[(OPEN_MAX + 31) / 32] {};
ListenEventList(const ListenEventList&) = delete;
ListenEventList& operator=(const ListenEventList&) = delete;
ListenEventList(ListenEventList&& other)
: events(BAN::move(other.events))
{}
ListenEventList& operator=(ListenEventList&& other)
{
events = BAN::move(other.events);
return *this;
}
BAN::HashMap<int, epoll_event> events;
bool has_fd(int fd) const bool has_fd(int fd) const
{ {
// For some reason having (fd < 0 || ...) makes GCC 15.1.0 return events.contains(fd);
// think bitmap access can be out of bounds...
if (static_cast<size_t>(fd) >= events.size())
return false;
return bitmap[fd / 32] & (1u << (fd % 32));
} }
bool empty() const bool empty() const
{ {
for (auto val : bitmap) return events.empty();
if (val != 0)
return false;
return true;
} }
void add_fd(int fd, epoll_event event) BAN::ErrorOr<void> add_fd(int fd, epoll_event event)
{ {
ASSERT(!has_fd(fd)); TRY(events.insert(fd, event));
bitmap[fd / 32] |= (1u << (fd % 32)); return {};
events[fd] = event;
} }
void remove_fd(int fd) void remove_fd(int fd)
{ {
ASSERT(has_fd(fd)); events.remove(fd);
bitmap[fd / 32] &= ~(1u << (fd % 32));
events[fd] = {};
} }
}; };

View File

@@ -16,7 +16,7 @@ namespace Kernel
Epoll::~Epoll() Epoll::~Epoll()
{ {
for (auto [inode, _] : m_listening_events) for (auto& [inode, _] : m_listening_events)
inode->del_epoll(this); inode->del_epoll(this);
} }
@@ -44,7 +44,7 @@ namespace Kernel
if (!contains_inode) if (!contains_inode)
TRY(inode->add_epoll(this)); TRY(inode->add_epoll(this));
it->value.add_fd(fd, event); TRY(it->value.add_fd(fd, event));
SpinLockGuard _(m_ready_lock); SpinLockGuard _(m_ready_lock);
auto ready_it = m_ready_events.find(inode); auto ready_it = m_ready_events.find(inode);
@@ -144,9 +144,8 @@ namespace Kernel
{ {
uint32_t listen_mask = EPOLLHUP | EPOLLERR; uint32_t listen_mask = EPOLLHUP | EPOLLERR;
for (size_t fd = 0; fd < listen.events.size(); fd++) for (const auto& [_, events] : listen.events)
if (listen.has_fd(fd)) listen_mask |= events.events;
listen_mask |= listen.events[fd].events;
events &= listen_mask; events &= listen_mask;
} }
@@ -171,11 +170,10 @@ namespace Kernel
#undef REMOVE_IT #undef REMOVE_IT
for (size_t fd = 0; fd < listen.events.size() && event_count < event_span.size(); fd++) for (auto& [_, listen_event] : listen.events)
{ {
if (!listen.has_fd(fd)) if (event_count >= event_span.size())
continue; break;
auto& listen_event = listen.events[fd];
const auto new_events = (listen_event.events | EPOLLHUP | EPOLLERR) & events; const auto new_events = (listen_event.events | EPOLLHUP | EPOLLERR) & events;
if (new_events == 0) if (new_events == 0)