IORING_TIMEOUT_IMMEDIATE_ARG allows the user to store the timeout in the SQE without indirection to a user timespec. Update io_uring.h and extend tests to cover the feature. Signed-off-by: Pavel Begunkov --- src/include/liburing/io_uring.h | 5 ++++ test/timeout.c | 44 ++++++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/include/liburing/io_uring.h b/src/include/liburing/io_uring.h index ab1450ec..74b3f86d 100644 --- a/src/include/liburing/io_uring.h +++ b/src/include/liburing/io_uring.h @@ -332,6 +332,10 @@ enum io_uring_op { /* * sqe->timeout_flags + * + * IORING_TIMEOUT_IMMEDIATE_ARG: If set, sqe->addr stores the timeout + * value in nanoseconds instead of + * pointing to a timespec. */ #define IORING_TIMEOUT_ABS (1U << 0) #define IORING_TIMEOUT_UPDATE (1U << 1) @@ -340,6 +344,7 @@ enum io_uring_op { #define IORING_LINK_TIMEOUT_UPDATE (1U << 4) #define IORING_TIMEOUT_ETIME_SUCCESS (1U << 5) #define IORING_TIMEOUT_MULTISHOT (1U << 6) +#define IORING_TIMEOUT_IMMEDIATE_ARG (1U << 7) #define IORING_TIMEOUT_CLOCK_MASK (IORING_TIMEOUT_BOOTTIME | IORING_TIMEOUT_REALTIME) #define IORING_TIMEOUT_UPDATE_MASK (IORING_TIMEOUT_UPDATE | IORING_LINK_TIMEOUT_UPDATE) /* diff --git a/test/timeout.c b/test/timeout.c index 003ba743..332efcbc 100644 --- a/test/timeout.c +++ b/test/timeout.c @@ -23,6 +23,7 @@ static int not_supported; static int no_modify; static int no_multishot; +static int no_immediate; static void msec_to_ts(struct __kernel_timespec *ts, unsigned int msec) { @@ -30,11 +31,25 @@ static void msec_to_ts(struct __kernel_timespec *ts, unsigned int msec) ts->tv_nsec = (msec % 1000) * 1000000; } +static void t_prep_timeout_rel(struct io_uring_sqe *sqe, + const struct __kernel_timespec *ts, + bool immediate) +{ + if (!immediate) { + io_uring_prep_timeout(sqe, ts, 0, 0); + return; + } + + io_uring_prep_timeout(sqe, NULL, 0, 0); + sqe->addr = ts->tv_sec * 1000000000 + ts->tv_nsec; + sqe->timeout_flags = IORING_TIMEOUT_IMMEDIATE_ARG; +} + /* * Test that we return to userspace if a timeout triggers, even if we * don't satisfy the number of events asked for. */ -static int test_single_timeout_many(struct io_uring *ring) +static int test_single_timeout_many(struct io_uring *ring, bool immediate) { struct io_uring_cqe *cqe; struct io_uring_sqe *sqe; @@ -50,7 +65,7 @@ static int test_single_timeout_many(struct io_uring *ring) } msec_to_ts(&ts, TIMEOUT_MSEC); - io_uring_prep_timeout(sqe, &ts, 0, 0); + t_prep_timeout_rel(sqe, &ts, immediate); ret = io_uring_submit(ring); if (ret <= 0) { @@ -219,7 +234,7 @@ err: /* * Test single timeout waking us up */ -static int test_single_timeout(struct io_uring *ring) +static int test_single_timeout(struct io_uring *ring, bool immediate) { struct io_uring_cqe *cqe; struct io_uring_sqe *sqe; @@ -235,7 +250,7 @@ static int test_single_timeout(struct io_uring *ring) } msec_to_ts(&ts, TIMEOUT_MSEC); - io_uring_prep_timeout(sqe, &ts, 0, 0); + t_prep_timeout_rel(sqe, &ts, immediate); ret = io_uring_submit(ring); if (ret <= 0) { @@ -1765,7 +1780,7 @@ int main(int argc, char *argv[]) ret = io_uring_queue_init(8, &sqpoll_ring, IORING_SETUP_SQPOLL); sqpoll = !ret; - ret = test_single_timeout(&ring); + ret = test_single_timeout(&ring, false); if (ret) { fprintf(stderr, "test_single_timeout failed\n"); return ret; @@ -1773,6 +1788,15 @@ int main(int argc, char *argv[]) if (not_supported) return 0; + ret = test_single_timeout(&ring, true); + if (ret == -EINVAL) { + no_immediate = true; + printf("Immeidate timeout arguments not supported\n"); + } else if (ret) { + fprintf(stderr, "test_single_timeout (imm) failed\n"); + return ret; + } + ret = test_multi_timeout(&ring); if (ret) { fprintf(stderr, "test_multi_timeout failed\n"); @@ -1797,12 +1821,20 @@ int main(int argc, char *argv[]) return ret; } - ret = test_single_timeout_many(&ring); + ret = test_single_timeout_many(&ring, false); if (ret) { fprintf(stderr, "test_single_timeout_many failed\n"); return ret; } + if (!no_immediate) { + ret = test_single_timeout_many(&ring, true); + if (ret) { + fprintf(stderr, "test_single_timeout_many (imm) failed\n"); + return ret; + } + } + ret = test_single_timeout_nr(&ring, 1); if (ret) { fprintf(stderr, "test_single_timeout_nr(1) failed\n"); -- 2.53.0