* [PATCH] liburing: Add io_uring_submit_and_wait_timeout function in API @ 2021-10-04 13:31 Olivier Langlois 2021-10-04 14:38 ` Jens Axboe 0 siblings, 1 reply; 3+ messages in thread From: Olivier Langlois @ 2021-10-04 13:31 UTC (permalink / raw) To: Jens Axboe, Pavel Begunkov, io-uring before commit 0ea4ccd1c0e4 ("src/queue: don't flush SQ ring for new wait interface"), io_uring_wait_cqes() was serving the purpose of submit sqe and wait for cqe up to a certain timeout value. Since the commit, a new function is needed to fill this gap. Fixes: https://github.com/axboe/liburing/issues/440 Signed-off-by: Olivier Langlois <[email protected]> --- src/include/liburing.h | 5 +++++ src/liburing.map | 5 +++++ src/queue.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/src/include/liburing.h b/src/include/liburing.h index 0c2c5c2..fe8bfbe 100644 --- a/src/include/liburing.h +++ b/src/include/liburing.h @@ -122,6 +122,11 @@ int io_uring_wait_cqe_timeout(struct io_uring *ring, struct __kernel_timespec *ts); int io_uring_submit(struct io_uring *ring); int io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr); +int io_uring_submit_and_wait_timout(struct io_uring *ring, + struct io_uring_cqe **cqe_ptr, + unsigned wait_nr, + struct __kernel_timespec *ts, + sigset_t *sigmask); struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring); int io_uring_register_buffers(struct io_uring *ring, const struct iovec *iovecs, diff --git a/src/liburing.map b/src/liburing.map index 6692a3b..09f4275 100644 --- a/src/liburing.map +++ b/src/liburing.map @@ -44,3 +44,8 @@ LIBURING_2.1 { io_uring_unregister_iowq_aff; io_uring_register_iowq_max_workers; } LIBURING_2.0; + +LIBURING_2.2 { + global: + io_uring_submit_and_wait_timout; +} LIBURING_2.1; diff --git a/src/queue.c b/src/queue.c index 31aa17c..9ac9fe5 100644 --- a/src/queue.c +++ b/src/queue.c @@ -305,6 +305,39 @@ int io_uring_wait_cqes(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, return __io_uring_get_cqe(ring, cqe_ptr, to_submit, wait_nr, sigmask); } +int io_uring_submit_and_wait_timout(struct io_uring *ring, + struct io_uring_cqe **cqe_ptr, + unsigned wait_nr, + struct __kernel_timespec *ts, + sigset_t *sigmask) +{ + if (uring_likely(ts)) { + if (uring_unlikely(!(ring->features & IORING_FEAT_EXT_ARG))) + return io_uring_wait_cqes(ring, cqe_ptr, wait_nr, + ts, sigmask); + else { + struct io_uring_getevents_arg arg = { + .sigmask = (unsigned long) sigmask, + .sigmask_sz = _NSIG / 8, + .ts = (unsigned long) ts + }; + struct get_data data = { + .submit = __io_uring_flush_sq(ring), + .wait_nr = wait_nr, + .get_flags = IORING_ENTER_EXT_ARG, + .sz = sizeof(arg), + .arg = &arg + }; + + return _io_uring_get_cqe(ring, cqe_ptr, &data); + } + } + else + return __io_uring_get_cqe(ring, cqe_ptr, + __io_uring_flush_sq(ring), + wait_nr, sigmask); +} + /* * See io_uring_wait_cqes() - this function is the same, it just always uses * '1' as the wait_nr. -- 2.33.0 ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] liburing: Add io_uring_submit_and_wait_timeout function in API 2021-10-04 13:31 [PATCH] liburing: Add io_uring_submit_and_wait_timeout function in API Olivier Langlois @ 2021-10-04 14:38 ` Jens Axboe 2021-10-04 15:07 ` Olivier Langlois 0 siblings, 1 reply; 3+ messages in thread From: Jens Axboe @ 2021-10-04 14:38 UTC (permalink / raw) To: Olivier Langlois, Pavel Begunkov, io-uring On 10/4/21 7:31 AM, Olivier Langlois wrote: > before commit 0ea4ccd1c0e4 ("src/queue: don't flush SQ ring for new wait interface"), > io_uring_wait_cqes() was serving the purpose of submit sqe and wait for cqe up to a certain timeout value. > > Since the commit, a new function is needed to fill this gap. > > Fixes: https://github.com/axboe/liburing/issues/440 > Signed-off-by: Olivier Langlois <[email protected]> > --- > src/include/liburing.h | 5 +++++ > src/liburing.map | 5 +++++ > src/queue.c | 33 +++++++++++++++++++++++++++++++++ > 3 files changed, 43 insertions(+) > > diff --git a/src/include/liburing.h b/src/include/liburing.h > index 0c2c5c2..fe8bfbe 100644 > --- a/src/include/liburing.h > +++ b/src/include/liburing.h > @@ -122,6 +122,11 @@ int io_uring_wait_cqe_timeout(struct io_uring *ring, > struct __kernel_timespec *ts); > int io_uring_submit(struct io_uring *ring); > int io_uring_submit_and_wait(struct io_uring *ring, unsigned wait_nr); > +int io_uring_submit_and_wait_timout(struct io_uring *ring, > + struct io_uring_cqe **cqe_ptr, > + unsigned wait_nr, > + struct __kernel_timespec *ts, > + sigset_t *sigmask); > struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring); > > int io_uring_register_buffers(struct io_uring *ring, const struct iovec *iovecs, > diff --git a/src/liburing.map b/src/liburing.map > index 6692a3b..09f4275 100644 > --- a/src/liburing.map > +++ b/src/liburing.map > @@ -44,3 +44,8 @@ LIBURING_2.1 { > io_uring_unregister_iowq_aff; > io_uring_register_iowq_max_workers; > } LIBURING_2.0; > + > +LIBURING_2.2 { > + global: > + io_uring_submit_and_wait_timout; > +} LIBURING_2.1; > diff --git a/src/queue.c b/src/queue.c > index 31aa17c..9ac9fe5 100644 > --- a/src/queue.c > +++ b/src/queue.c > @@ -305,6 +305,39 @@ int io_uring_wait_cqes(struct io_uring *ring, struct io_uring_cqe **cqe_ptr, > return __io_uring_get_cqe(ring, cqe_ptr, to_submit, wait_nr, sigmask); > } > > +int io_uring_submit_and_wait_timout(struct io_uring *ring, > + struct io_uring_cqe **cqe_ptr, > + unsigned wait_nr, > + struct __kernel_timespec *ts, > + sigset_t *sigmask) > +{ > + if (uring_likely(ts)) { > + if (uring_unlikely(!(ring->features & IORING_FEAT_EXT_ARG))) > + return io_uring_wait_cqes(ring, cqe_ptr, wait_nr, > + ts, sigmask); > + else { > + struct io_uring_getevents_arg arg = { > + .sigmask = (unsigned long) sigmask, > + .sigmask_sz = _NSIG / 8, > + .ts = (unsigned long) ts > + }; > + struct get_data data = { > + .submit = __io_uring_flush_sq(ring), > + .wait_nr = wait_nr, > + .get_flags = IORING_ENTER_EXT_ARG, > + .sz = sizeof(arg), > + .arg = &arg > + }; > + > + return _io_uring_get_cqe(ring, cqe_ptr, &data); > + } > + } > + else > + return __io_uring_get_cqe(ring, cqe_ptr, > + __io_uring_flush_sq(ring), > + wait_nr, sigmask); > +} I'd get rid of the likely/unlikely, imho it just hinders readability and for some cases they may end up being wrong. You also don't need an else when there's a return, and if you use braces on one condition, use it for all. IOW, something like: if (ts) { if (ring->features & IORING_FEAT_EXT_ARG) { struct io_uring_getevents_arg arg = { .sigmask = (unsigned long) sigmask, .sigmask_sz = _NSIG / 8, .ts = (unsigned long) ts }; struct get_data data = { .submit = __io_uring_flush_sq(ring), .wait_nr = wait_nr, .get_flags = IORING_ENTER_EXT_ARG, .sz = sizeof(arg), .arg = &arg }; return _io_uring_get_cqe(ring, cqe_ptr, &data); } return io_uring_wait_cqes(ring, cqe_ptr, wait_nr, ts, sigmask); } return __io_uring_get_cqe(ring, cqe_ptr, __io_uring_flush_sq(ring), wait_nr, sigmask); which is a lot more readable too. -- Jens Axboe ^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] liburing: Add io_uring_submit_and_wait_timeout function in API 2021-10-04 14:38 ` Jens Axboe @ 2021-10-04 15:07 ` Olivier Langlois 0 siblings, 0 replies; 3+ messages in thread From: Olivier Langlois @ 2021-10-04 15:07 UTC (permalink / raw) To: Jens Axboe, Pavel Begunkov, io-uring On Mon, 2021-10-04 at 08:38 -0600, Jens Axboe wrote: > > I'd get rid of the likely/unlikely, imho it just hinders readability > and for some cases they may end up being wrong. You also don't need > an > else when there's a return, and if you use braces on one condition, > use > it for all. IOW, something like: > > if (ts) { > if (ring->features & IORING_FEAT_EXT_ARG) { > struct io_uring_getevents_arg arg = { > .sigmask = (unsigned long) > sigmask, > .sigmask_sz = _NSIG / 8, > .ts = (unsigned long) ts > }; > struct get_data data = { > .submit = > __io_uring_flush_sq(ring), > .wait_nr = wait_nr, > .get_flags = > IORING_ENTER_EXT_ARG, > .sz = sizeof(arg), > .arg = &arg > }; > > return _io_uring_get_cqe(ring, cqe_ptr, > &data); > } > return io_uring_wait_cqes(ring, cqe_ptr, wait_nr, ts, > sigmask); > } > > return __io_uring_get_cqe(ring, cqe_ptr, > __io_uring_flush_sq(ring), > wait_nr, sigmask); > > which is a lot more readable too. > ok. I will do as you suggest. I agree with the readability argument. However, I believe that the likely events were correctly identified as if ts is NULL, you should be calling io_uring_submit_and_wait() instead of this new function. and the second condition as no other choice to become more and more likely as the time pass. That being said, out of my old memories, I remember that if you want to optimize code manually to help x86 branch prediction algo, you can do so by crafting the conditional expression to be true for the most likely case so what you propose still keep the same flow implicitly (with better readability). Since submission, I got another improvement idea that I will integrate in v2. I am leveraging io_uring_wait_cqes() code for the case where the kernel is old and timeout must be passed as an extra sqe. 1. It is brittle. If someone change that part of io_uring_wait_cqes(), he could unknowingly break io_uring_submit_and_wait_timeout(). 2. The intent behind calling io_uring_wait_cqes from io_uring_submit_and_wait_timeout isn't 100% clear IMHO. I am thinking factoring out the common code into a static function. Considering that running over an old kernel should, hopefully, become a rare event, the extra function call shouldn't be a too big issue to reach a better readability. ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2021-10-04 15:07 UTC | newest] Thread overview: 3+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2021-10-04 13:31 [PATCH] liburing: Add io_uring_submit_and_wait_timeout function in API Olivier Langlois 2021-10-04 14:38 ` Jens Axboe 2021-10-04 15:07 ` Olivier Langlois
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox