event/Loop: pass timeout=nullptr to io_uring if there is no timer

This commit is contained in:
Max Kellermann
2025-02-12 21:03:43 +01:00
committed by Max Kellermann
parent 624da8ce5b
commit 5b393052ee
5 changed files with 16 additions and 13 deletions

@ -297,23 +297,25 @@ ExportTimeoutMS(Event::Duration timeout) noexcept
#ifdef HAVE_URING #ifdef HAVE_URING
static constexpr struct __kernel_timespec static struct __kernel_timespec *
ExportTimeoutKernelTimespec(Event::Duration timeout) noexcept ExportTimeoutKernelTimespec(Event::Duration timeout, struct __kernel_timespec &buffer) noexcept
{ {
if (timeout < timeout.zero()) if (timeout < timeout.zero())
// TODO if there is no time, there should be no timeout at all return nullptr;
return { .tv_sec = 24 * 3600 };
if (timeout >= std::chrono::duration_cast<Event::Duration>(std::chrono::hours{24})) [[unlikely]] if (timeout >= std::chrono::duration_cast<Event::Duration>(std::chrono::hours{24})) [[unlikely]] {
return { buffer = {
.tv_sec = std::chrono::ceil<std::chrono::duration<__kernel_time64_t>>(timeout).count(), .tv_sec = std::chrono::ceil<std::chrono::duration<__kernel_time64_t>>(timeout).count(),
}; };
return &buffer;
}
const auto nsec = std::chrono::ceil<std::chrono::nanoseconds>(timeout); const auto nsec = std::chrono::ceil<std::chrono::nanoseconds>(timeout);
return { buffer = {
.tv_sec = nsec.count() / 1000000000, .tv_sec = nsec.count() / 1000000000,
.tv_nsec = nsec.count() % 1000000000, .tv_nsec = nsec.count() % 1000000000,
}; };
return &buffer;
} }
#endif #endif
@ -424,7 +426,8 @@ EventLoop::Run() noexcept
consume all events to rearm it */ consume all events to rearm it */
if (!epoll_ready) { if (!epoll_ready) {
auto kernel_timeout = ExportTimeoutKernelTimespec(timeout); struct __kernel_timespec timeout_buffer;
auto *kernel_timeout = ExportTimeoutKernelTimespec(timeout, timeout_buffer);
Uring::Queue &uring_queue = *uring; Uring::Queue &uring_queue = *uring;
uring_queue.SubmitAndWaitDispatchCompletions(kernel_timeout); uring_queue.SubmitAndWaitDispatchCompletions(kernel_timeout);
} }

@ -104,7 +104,7 @@ Queue::WaitDispatchOneCompletion()
} }
bool bool
Queue::SubmitAndWaitDispatchCompletions(struct __kernel_timespec &timeout) Queue::SubmitAndWaitDispatchCompletions(struct __kernel_timespec *timeout)
{ {
auto *cqe = ring.SubmitAndWaitCompletion(timeout); auto *cqe = ring.SubmitAndWaitCompletion(timeout);
if (cqe == nullptr) if (cqe == nullptr)

@ -101,7 +101,7 @@ public:
while (WaitDispatchOneCompletion()) {} while (WaitDispatchOneCompletion()) {}
} }
bool SubmitAndWaitDispatchCompletions(struct __kernel_timespec &timeout); bool SubmitAndWaitDispatchCompletions(struct __kernel_timespec *timeout);
private: private:
static void _DispatchOneCompletion(const struct io_uring_cqe &cqe) noexcept; static void _DispatchOneCompletion(const struct io_uring_cqe &cqe) noexcept;

@ -61,10 +61,10 @@ Ring::WaitCompletion()
} }
struct io_uring_cqe * struct io_uring_cqe *
Ring::SubmitAndWaitCompletion(struct __kernel_timespec &timeout) Ring::SubmitAndWaitCompletion(struct __kernel_timespec *timeout)
{ {
struct io_uring_cqe *cqe; struct io_uring_cqe *cqe;
if (int error = io_uring_submit_and_wait_timeout(&ring, &cqe, 1, &timeout, nullptr); if (int error = io_uring_submit_and_wait_timeout(&ring, &cqe, 1, timeout, nullptr);
error < 0) { error < 0) {
if (error == -ETIME || error == -EAGAIN || error == -EINTR) if (error == -ETIME || error == -EAGAIN || error == -EINTR)
return nullptr; return nullptr;

@ -109,7 +109,7 @@ public:
* *
* @return a completion queue entry or nullptr on EAGAIN/ETIME * @return a completion queue entry or nullptr on EAGAIN/ETIME
*/ */
struct io_uring_cqe *SubmitAndWaitCompletion(struct __kernel_timespec &timeout); struct io_uring_cqe *SubmitAndWaitCompletion(struct __kernel_timespec *timeout);
/** /**
* Peek one completion (non-blocking). * Peek one completion (non-blocking).