commit: a2036911b69c3e05d1cc5f5bd7c90784b9a72fc3
Author: Michał Górny <mgorny <AT> gentoo <DOT> org>
AuthorDate: Tue Nov 18 18:45:05 2025 +0000
Commit: Michał Górny <mgorny <AT> gentoo <DOT> org>
CommitDate: Tue Nov 18 18:45:05 2025 +0000
URL: https://gitweb.gentoo.org/proj/steve.git/commit/?id=a2036911
Support polling
Signed-off-by: Michał Górny <mgorny <AT> gentoo.org>
steve.cxx | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/steve.cxx b/steve.cxx
index 81e88f4..713137f 100644
--- a/steve.cxx
+++ b/steve.cxx
@@ -17,6 +17,7 @@
#include <deque>
#include <unordered_map>
+#include <sys/poll.h>
#include <unistd.h>
#include <cuse_lowlevel.h>
@@ -39,6 +40,21 @@ struct steve_read_waiter {
uint64_t pid;
};
+struct steve_poll_waiter {
+ fuse_pollhandle *poll_handle;
+ uint64_t pid;
+
+ steve_poll_waiter(fuse_pollhandle *new_poll_handle, uint64_t new_pid)
+ : poll_handle(new_poll_handle), pid(new_pid) {}
+
+ steve_poll_waiter(const steve_poll_waiter &) = delete;
+ steve_poll_waiter& operator=(const steve_poll_waiter &) = delete;
+
+ ~steve_poll_waiter() {
+ fuse_pollhandle_destroy(poll_handle);
+ }
+};
+
struct steve_process {
unsigned int tokens_held{0};
};
@@ -48,6 +64,7 @@ struct steve_state {
unsigned int jobs;
unsigned int tokens;
std::deque<steve_read_waiter> read_waiters;
+ std::deque<steve_poll_waiter> poll_waiters;
std::unordered_map<uint64_t, steve_process> processes;
};
@@ -103,6 +120,16 @@ static void steve_wake_waiters(steve_state *state)
fuse_reply_buf(read_waiter->req, "+", 1);
state->read_waiters.pop_front();
}
+
+ if (state->tokens > 0) {
+ for (auto &poll_waiter : state->poll_waiters) {
+ if (state->verbose)
+ printf("Notifying PID %ld about POLLIN, %d
tokens left, %d tokens held by process\n",
+ poll_waiter.pid, state->tokens,
state->processes[poll_waiter.pid].tokens_held);
+ fuse_lowlevel_notify_poll(poll_waiter.poll_handle);
+ }
+ state->poll_waiters.clear();
+ }
}
static void steve_check_processes(steve_state *state)
@@ -248,6 +275,28 @@ static void steve_write(
steve_wake_waiters(state);
}
+static void steve_poll(
+ fuse_req_t req, struct fuse_file_info *fi, struct fuse_pollhandle *ph)
+{
+ steve_state *state = static_cast<steve_state *>(fuse_req_userdata(req));
+ int events = fi->poll_events & (POLLIN | POLLOUT);
+
+ if (state->verbose)
+ printf("PID %ld requested poll, %d tokens available, %d tokens
held by process\n",
+ fi->fh, state->tokens,
state->processes[fi->fh].tokens_held);
+
+ /* check if we have tokens to reclaim */
+ if (state->tokens == 0)
+ steve_check_processes(state);
+ /* POLLOUT is always possible, POLLIN only if we have any tokens */
+ if (state->tokens == 0) {
+ state->poll_waiters.emplace_back(ph, fi->fh);
+ events &= ~POLLIN;
+ }
+
+ fuse_reply_poll(req, events);
+}
+
static const struct cuse_lowlevel_ops steve_ops = {
.init = steve_init,
.destroy = steve_destroy,
@@ -255,6 +304,7 @@ static const struct cuse_lowlevel_ops steve_ops = {
.read = steve_read,
.write = steve_write,
.release = steve_release,
+ .poll = steve_poll,
};
int main(int argc, char **argv)