laforge has submitted this change. ( https://gerrit.osmocom.org/c/libosmocore/+/40855?usp=email )
Change subject: Remove old empty io_uring ......................................................................
Remove old empty io_uring
A previous patch creates a new io_uring, if it becomes too small to store all SQEs. When all SQEs of the old ring are completed, the old ring will be destroyed.
A counter is incremented whenever an SQE is submitted to an io_uring. The counter is decremented whenever a CQE is received and handled. This counter will determine when a ring is empty and can be destroyed.
Related: OS#6705 Change-Id: Id2d2a0400ad442198c684ea0ead4eaeaead4c53d --- M src/core/osmo_io_uring.c 1 file changed, 36 insertions(+), 8 deletions(-)
Approvals: pespin: Looks good to me, but someone else must approve Jenkins Builder: Verified laforge: Looks good to me, approved
diff --git a/src/core/osmo_io_uring.c b/src/core/osmo_io_uring.c index 12caa77..45a08fe 100644 --- a/src/core/osmo_io_uring.c +++ b/src/core/osmo_io_uring.c @@ -66,7 +66,7 @@ bool g_io_uring_batch = false; bool g_io_uring_submit_needed = false;
-static unsigned int g_io_uring_size = IOFD_URING_INITIAL_SIZE; +static int g_io_uring_size = IOFD_URING_INITIAL_SIZE;
static int g_io_uring_read_sqes = 1;
@@ -74,6 +74,7 @@ struct osmo_fd event_ofd; struct io_uring ring; struct llist_head cancel_queue; + unsigned int num_pending_submissions; };
static __thread struct osmo_io_uring *g_ring = NULL; @@ -167,6 +168,29 @@ } }
+static void osmo_iofd_uring_exit(struct osmo_io_uring *ring) +{ + LOGP(DLIO, LOGL_DEBUG, "Old empty io_uring will be destroyed."); + + io_uring_queue_exit(&ring->ring); + + osmo_fd_unregister(&ring->event_ofd); + close(ring->event_ofd.fd); + + talloc_free(ring); +} + +static inline struct io_uring_sqe *io_uring_get_sqe_and_count(struct osmo_io_uring *ring) +{ + struct io_uring_sqe *sqe; + + sqe = io_uring_get_sqe(&ring->ring); + if (sqe) + ring->num_pending_submissions++; + + return sqe; +} + static struct io_uring_sqe *iofd_uring_get_sqe(struct osmo_io_fd *iofd, bool read) { struct io_uring_sqe *sqe; @@ -175,7 +199,7 @@ if (read && iofd->u.uring.reads_submitted > 0 && iofd->u.uring.read_ring != &g_ring->ring) return NULL;
- sqe = io_uring_get_sqe(&g_ring->ring); + sqe = io_uring_get_sqe_and_count(g_ring); if (sqe) return sqe;
@@ -199,7 +223,7 @@
osmo_iofd_uring_init();
- sqe = io_uring_get_sqe(&g_ring->ring); + sqe = io_uring_get_sqe_and_count(g_ring); OSMO_ASSERT(sqe); return sqe; } @@ -424,6 +448,7 @@ struct osmo_io_uring *orig_ring = container_of(ring, struct osmo_io_uring, ring);
while (io_uring_peek_cqe(ring, &cqe) == 0) { + orig_ring->num_pending_submissions--;
msghdr = io_uring_cqe_get_data(cqe); if (!msghdr) { @@ -448,11 +473,15 @@ }
/* If there are unsubmitted cancel SQEs, try to queue them now. */ - if (OSMO_LIKELY(llist_empty(&orig_ring->cancel_queue))) + if (OSMO_LIKELY(llist_empty(&orig_ring->cancel_queue))) { + /* Old ring is empty, remove it. */ + if (OSMO_UNLIKELY(orig_ring != g_ring && orig_ring->num_pending_submissions == 0)) + osmo_iofd_uring_exit(orig_ring); return; + } llist_for_each_entry_safe(msghdr, msghdr2, &orig_ring->cancel_queue, list) { struct io_uring_sqe *sqe; - sqe = io_uring_get_sqe(&orig_ring->ring); + sqe = io_uring_get_sqe_and_count(orig_ring); if (!sqe) break; io_uring_sqe_set_data(sqe, NULL); @@ -462,7 +491,6 @@ msghdr->in_cancel_queue = false; } io_uring_submit(&orig_ring->ring); - }
/*! will submit the next to-be-transmitted message for given iofd */ @@ -589,7 +617,7 @@ if (&ring->ring == &g_ring->ring) osmo_io_uring_submit(); /* If the submission queue is full, use cancel queue. We cannot cancel SQEs on the new ring. */ - sqe = io_uring_get_sqe(&ring->ring); + sqe = io_uring_get_sqe_and_count(ring); if (sqe) { io_uring_sqe_set_data(sqe, NULL); LOGPIO(iofd, LOGL_DEBUG, "Cancelling read\n"); @@ -619,7 +647,7 @@ if (&ring->ring == &g_ring->ring) osmo_io_uring_submit(); /* If the submission queue is full, use cancel queue. We cannot cancel SQEs on the new ring. */ - sqe = io_uring_get_sqe(&ring->ring); + sqe = io_uring_get_sqe_and_count(ring); if (sqe) { io_uring_sqe_set_data(sqe, NULL); LOGPIO(iofd, LOGL_DEBUG, "Cancelling write\n");