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
static constexpr struct __kernel_timespec
ExportTimeoutKernelTimespec(Event::Duration timeout) noexcept
static struct __kernel_timespec *
ExportTimeoutKernelTimespec(Event::Duration timeout, struct __kernel_timespec &buffer) noexcept
{
if (timeout < timeout.zero())
// TODO if there is no time, there should be no timeout at all
return { .tv_sec = 24 * 3600 };
return nullptr;
if (timeout >= std::chrono::duration_cast<Event::Duration>(std::chrono::hours{24})) [[unlikely]]
return {
if (timeout >= std::chrono::duration_cast<Event::Duration>(std::chrono::hours{24})) [[unlikely]] {
buffer = {
.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);
return {
buffer = {
.tv_sec = nsec.count() / 1000000000,
.tv_nsec = nsec.count() % 1000000000,
};
return &buffer;
}
#endif
@ -424,7 +426,8 @@ EventLoop::Run() noexcept
consume all events to rearm it */
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.SubmitAndWaitDispatchCompletions(kernel_timeout);
}

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

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

@ -61,10 +61,10 @@ Ring::WaitCompletion()
}
struct io_uring_cqe *
Ring::SubmitAndWaitCompletion(struct __kernel_timespec &timeout)
Ring::SubmitAndWaitCompletion(struct __kernel_timespec *timeout)
{
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) {
if (error == -ETIME || error == -EAGAIN || error == -EINTR)
return nullptr;

@ -109,7 +109,7 @@ public:
*
* @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).