quick hack to replace epoll with poll

This commit is contained in:
2026-06-04 03:26:29 +03:00
parent a6a581347e
commit d0f2b5e8a6
5 changed files with 58 additions and 166 deletions

View File

@@ -12,7 +12,6 @@
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <time.h> #include <time.h>
#include <sys/epoll.h>
struct Selection struct Selection
{ {
@@ -1814,9 +1813,9 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
(void)TRY_REF(get_window(client_info, wid, X_SendEvent)); (void)TRY_REF(get_window(client_info, wid, X_SendEvent));
Client* target_client = nullptr; Client* target_client = nullptr;
for (auto& [_, thingy] : g_epoll_thingies) for (auto& [_, thingy] : g_pollables)
{ {
if (thingy.type != EpollThingy::Type::Client) if (thingy.type != Pollable::Type::Client)
continue; continue;
auto& other_client = thingy.value.get<Client>(); auto& other_client = thingy.value.get<Client>();
if (!other_client.objects.contains(wid)) if (!other_client.objects.contains(wid))
@@ -1938,47 +1937,11 @@ BAN::ErrorOr<void> handle_packet(Client& client_info, BAN::ConstByteSpan packet)
case X_GrabServer: case X_GrabServer:
{ {
g_server_grabber_fd = client_info.fd; g_server_grabber_fd = client_info.fd;
for (const auto& [_, thingy] : g_epoll_thingies)
{
if (thingy.type != EpollThingy::Type::Client)
continue;
auto& other_client = thingy.value.get<Client>();
if (client_info.fd == other_client.fd)
continue;
uint32_t events = 0;
if (other_client.has_epollout)
events |= EPOLLOUT;
epoll_event event { .events = events, .data = { .fd = other_client.fd } };
epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, other_client.fd, &event);
}
break; break;
} }
case X_UngrabServer: case X_UngrabServer:
{ {
g_server_grabber_fd = -1; g_server_grabber_fd = -1;
for (const auto& [_, thingy] : g_epoll_thingies)
{
if (thingy.type != EpollThingy::Type::Client)
continue;
auto& other_client = thingy.value.get<Client>();
if (client_info.fd == other_client.fd)
continue;
uint32_t events = EPOLLIN;
if (other_client.has_epollout)
events |= EPOLLOUT;
epoll_event event { .events = events, .data = { .fd = other_client.fd } };
epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, other_client.fd, &event);
}
break; break;
} }
case X_QueryPointer: case X_QueryPointer:

View File

@@ -140,7 +140,6 @@ struct Client
}; };
int fd; int fd;
State state; State state;
bool has_epollout { false };
bool has_bigrequests { false }; bool has_bigrequests { false };
CARD16 sequence { 0 }; CARD16 sequence { 0 };
BAN::Optional<uint32_t> pid; BAN::Optional<uint32_t> pid;
@@ -149,7 +148,7 @@ struct Client
BAN::HashSet<CARD32> objects; BAN::HashSet<CARD32> objects;
}; };
struct EpollThingy struct Pollable
{ {
enum class Type enum class Type
{ {
@@ -172,7 +171,6 @@ extern BAN::HashMap<BAN::String, ATOM> g_atoms_name_to_id;
extern BAN::HashMap<ATOM, BAN::String> g_atoms_id_to_name; extern BAN::HashMap<ATOM, BAN::String> g_atoms_id_to_name;
extern ATOM g_atom_value; extern ATOM g_atom_value;
extern int g_epoll_fd; extern BAN::HashMap<int, Pollable> g_pollables;
extern BAN::HashMap<int, EpollThingy> g_epoll_thingies;
extern int g_server_grabber_fd; extern int g_server_grabber_fd;

View File

@@ -7,23 +7,18 @@
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <time.h> #include <time.h>
#include <sys/epoll.h>
void register_event_fd(int fd, void* data) void register_event_fd(int fd, void* data)
{ {
epoll_event event { .events = EPOLLIN, .data = { .fd = fd } }; MUST(g_pollables.insert(fd, {
epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, fd, &event); .type = Pollable::Type::Event,
MUST(g_epoll_thingies.insert(fd, {
.type = EpollThingy::Type::Event,
.value = data, .value = data,
})); }));
} }
void unregister_event_fd(int fd) void unregister_event_fd(int fd)
{ {
epoll_ctl(g_epoll_fd, EPOLL_CTL_DEL, fd, nullptr); g_pollables.remove(fd);
g_epoll_thingies.remove(fd);
} }
void on_window_close_event(WINDOW wid) void on_window_close_event(WINDOW wid)

View File

@@ -7,9 +7,9 @@
template<typename F> template<typename F>
static BAN::ErrorOr<void> for_each_client(uint32_t target_spec, const F& callback) static BAN::ErrorOr<void> for_each_client(uint32_t target_spec, const F& callback)
{ {
for (auto [fd, thingy] : g_epoll_thingies) for (auto [fd, thingy] : g_pollables)
{ {
if (thingy.type != EpollThingy::Type::Client) if (thingy.type != Pollable::Type::Client)
continue; continue;
Client& client_info = thingy.value.get<Client>(); Client& client_info = thingy.value.get<Client>();

View File

@@ -5,8 +5,8 @@
#include <X11/Xatom.h> #include <X11/Xatom.h>
#include <locale.h> #include <locale.h>
#include <poll.h>
#include <signal.h> #include <signal.h>
#include <sys/epoll.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
@@ -92,8 +92,7 @@ BAN::HashMap<BAN::String, ATOM> g_atoms_name_to_id;
BAN::HashMap<ATOM, BAN::String> g_atoms_id_to_name; BAN::HashMap<ATOM, BAN::String> g_atoms_id_to_name;
ATOM g_atom_value = XA_LAST_PREDEFINED + 1; ATOM g_atom_value = XA_LAST_PREDEFINED + 1;
int g_epoll_fd; BAN::HashMap<int, Pollable> g_pollables;
BAN::HashMap<int, EpollThingy> g_epoll_thingies;
int g_server_grabber_fd = -1; int g_server_grabber_fd = -1;
@@ -155,22 +154,6 @@ int main()
return 1; return 1;
} }
g_epoll_fd = epoll_create1(0);
if (g_epoll_fd == -1)
{
perror("xbanan: epoll_create1");
return 1;
}
{
epoll_event event { .events = EPOLLIN, .data = { .ptr = nullptr } };
if (epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, server_sock, &event) == -1)
{
perror("xbanan: epoll_ctl");
return 1;
}
}
#define APPEND_ATOM(name) do { \ #define APPEND_ATOM(name) do { \
MUST(g_atoms_id_to_name.insert(name, #name##_sv.substring(3))); \ MUST(g_atoms_id_to_name.insert(name, #name##_sv.substring(3))); \
MUST(g_atoms_name_to_id.insert(#name##_sv.substring(3), name)); \ MUST(g_atoms_name_to_id.insert(#name##_sv.substring(3), name)); \
@@ -274,9 +257,9 @@ int main()
const auto close_client = const auto close_client =
[](int client_fd) [](int client_fd)
{ {
auto& epoll_thingy = g_epoll_thingies[client_fd]; auto& pollable = g_pollables[client_fd];
ASSERT(epoll_thingy.type == EpollThingy::Type::Client); ASSERT(pollable.type == Pollable::Type::Client);
auto& client_info = epoll_thingy.value.get<Client>(); auto& client_info = pollable.value.get<Client>();
dprintln("client {} disconnected", client_fd); dprintln("client {} disconnected", client_fd);
@@ -328,29 +311,11 @@ int main()
g_objects.remove(it); g_objects.remove(it);
} }
epoll_ctl(g_epoll_fd, EPOLL_CTL_DEL, client_fd, nullptr); g_pollables.remove(client_fd);
g_epoll_thingies.remove(client_fd);
close(client_fd); close(client_fd);
if (client_fd == g_server_grabber_fd) if (g_server_grabber_fd == client_fd)
{
g_server_grabber_fd = -1; g_server_grabber_fd = -1;
for (const auto& [_, thingy] : g_epoll_thingies)
{
if (thingy.type != EpollThingy::Type::Client)
continue;
auto& other_client = thingy.value.get<Client>();
uint32_t events = EPOLLIN;
if (other_client.has_epollout)
events |= EPOLLOUT;
epoll_event event { .events = events, .data = { .fd = other_client.fd } };
epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, other_client.fd, &event);
}
}
}; };
Client dummy_client {}; Client dummy_client {};
@@ -377,12 +342,37 @@ int main()
for (;;) for (;;)
{ {
epoll_event events[16]; BAN::Vector<pollfd> pollfds;
const int event_count = epoll_wait(g_epoll_fd, events, 16, -1); MUST(pollfds.reserve(g_pollables.size() + 1));
MUST(pollfds.push_back({
for (int i = 0; i < event_count; i++) .fd = server_sock,
.events = POLLIN,
.revents = 0,
}));
for (auto& [fd, pollable] : g_pollables)
{ {
if (events[i].data.ptr == nullptr) short events = 0;
if (g_server_grabber_fd == -1 || g_server_grabber_fd == fd)
events |= POLLIN;
if (pollable.type == Pollable::Type::Client && !pollable.value.get<Client>().output_buffer.empty())
events |= POLLOUT;
if (events == 0)
continue;
MUST(pollfds.push_back(pollfd {
.fd = fd,
.events = events,
.revents = 0,
}));
}
const int event_count = poll(pollfds.data(), pollfds.size(), -1);
for (const auto& pollfd : pollfds)
{
if (pollfd.revents == 0)
continue;
if (pollfd.fd == server_sock)
{ {
int client_sock = accept(server_sock, nullptr, nullptr); int client_sock = accept(server_sock, nullptr, nullptr);
if (client_sock == -1) if (client_sock == -1)
@@ -400,8 +390,8 @@ int main()
client_pid = client_cred.pid; client_pid = client_cred.pid;
#endif #endif
MUST(g_epoll_thingies.insert(client_sock, { MUST(g_pollables.insert(client_sock, {
.type = EpollThingy::Type::Client, .type = Pollable::Type::Client,
.value = Client { .value = Client {
.fd = client_sock, .fd = client_sock,
.state = Client::State::ConnectionSetup, .state = Client::State::ConnectionSetup,
@@ -409,44 +399,32 @@ int main()
} }
})); }));
uint32_t events = 0;
if (g_server_grabber_fd == -1)
events |= EPOLLIN;
epoll_event event = { .events = events, .data = { .fd = client_sock } };
if (epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, client_sock, &event) == -1)
{
perror("xbanan: epoll_ctl");
close(client_sock);
continue;
}
dprintln("client {} connected", client_sock); dprintln("client {} connected", client_sock);
continue; continue;
} }
auto it = g_epoll_thingies.find(events[i].data.fd); auto it = g_pollables.find(pollfd.fd);
if (it == g_epoll_thingies.end()) if (it == g_pollables.end())
continue; continue;
auto& epoll_thingy = it->value; auto& pollable = it->value;
if (epoll_thingy.type == EpollThingy::Type::Event) if (pollable.type == Pollable::Type::Event)
{ {
g_platform_ops.poll_events(epoll_thingy.value.get<void*>()); g_platform_ops.poll_events(pollable.value.get<void*>());
continue; continue;
} }
ASSERT(epoll_thingy.type == EpollThingy::Type::Client); ASSERT(pollable.type == Pollable::Type::Client);
auto& client_info = epoll_thingy.value.get<Client>(); auto& client_info = pollable.value.get<Client>();
if (events[i].events & EPOLLHUP) if (pollfd.revents & POLLHUP)
{ {
close_client(client_info.fd); close_client(client_info.fd);
continue; continue;
} }
if (events[i].events & EPOLLOUT) if (pollfd.revents & POLLOUT)
{ {
const ssize_t nsend = send( const ssize_t nsend = send(
client_info.fd, client_info.fd,
@@ -473,28 +451,11 @@ int main()
); );
MUST(client_info.output_buffer.resize(client_info.output_buffer.size() - nsend)); MUST(client_info.output_buffer.resize(client_info.output_buffer.size() - nsend));
if (client_info.output_buffer.empty())
{
uint32_t events = 0;
if (g_server_grabber_fd == -1 || g_server_grabber_fd == client_info.fd)
events |= EPOLLIN;
epoll_event event { .events = events, .data = { .fd = client_info.fd } };
if (epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, client_info.fd, &event) == -1)
{
perror("xbanan: epoll_ctl");
close_client(client_info.fd);
continue;
}
client_info.has_epollout = false;
}
send_done: send_done:
(void)0; (void)0;
} }
if (!(events[i].events & EPOLLIN)) if (!(pollfd.revents & POLLIN))
continue; continue;
if (g_server_grabber_fd != -1 && g_server_grabber_fd != client_info.fd) if (g_server_grabber_fd != -1 && g_server_grabber_fd != client_info.fd)
@@ -606,30 +567,5 @@ int main()
} }
} }
} }
iterator_invalidated:
for (auto& [_, thingy] : g_epoll_thingies)
{
if (thingy.type != EpollThingy::Type::Client)
continue;
auto& client_info = thingy.value.get<Client>();
if (client_info.output_buffer.empty() || client_info.has_epollout)
continue;
uint32_t events = EPOLLOUT;
if (g_server_grabber_fd == -1 || g_server_grabber_fd == client_info.fd)
events |= EPOLLIN;
epoll_event event { .events = events, .data = { .fd = client_info.fd } };
if (epoll_ctl(g_epoll_fd, EPOLL_CTL_MOD, client_info.fd, &event) == -1)
{
perror("xbanan: epoll_ctl");
close_client(client_info.fd);
goto iterator_invalidated;
}
client_info.has_epollout = true;
}
} }
} }