From: David Wei <[email protected]>
To: [email protected]
Cc: Jens Axboe <[email protected]>, Pavel Begunkov <[email protected]>
Subject: [PATCH v1 4/4] liburing: add unit test for io_uring_register_iowait()
Date: Fri, 23 Feb 2024 21:07:35 -0800 [thread overview]
Message-ID: <[email protected]> (raw)
In-Reply-To: <[email protected]>
From: David Wei <[email protected]>
Add a unit test for io_uring_register_iowait() by creating a thread that
writes into a pipe after a delay, checking iowait before and after.
Signed-off-by: David Wei <[email protected]>
---
test/Makefile | 1 +
test/iowait.c | 157 ++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 158 insertions(+)
create mode 100644 test/iowait.c
diff --git a/test/Makefile b/test/Makefile
index b09228f..779a7db 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -107,6 +107,7 @@ test_srcs := \
io_uring_passthrough.c \
io_uring_register.c \
io_uring_setup.c \
+ iowait.c \
lfs-openat.c \
lfs-openat-write.c \
link.c \
diff --git a/test/iowait.c b/test/iowait.c
new file mode 100644
index 0000000..fcd4004
--- /dev/null
+++ b/test/iowait.c
@@ -0,0 +1,157 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Description: Test that waiting for CQ is accounted as iowait if enabled via
+ * io_uring_register_iowait(), and vice versa.
+ *
+ */
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/time.h>
+#include <pthread.h>
+#include <linux/kernel.h>
+
+#include "liburing.h"
+#include "helpers.h"
+
+struct data {
+ pthread_barrier_t startup;
+ int out_fd;
+};
+
+static unsigned long long get_iowait()
+{
+ FILE *fp;
+ char buf[256];
+ unsigned long long user, nice, system, idle, iowait;
+
+ fp = fopen("/proc/stat", "r");
+ if (!fp) {
+ perror("fopen");
+ exit(T_EXIT_FAIL);
+ }
+
+ if (fgets(buf, sizeof(buf), fp) == NULL) {
+ perror("fgets");
+ fclose(fp);
+ exit(T_EXIT_FAIL);
+ }
+ fclose(fp);
+
+ sscanf(buf, "cpu %llu %llu %llu %llu %llu", &user, &nice, &system,
+ &idle, &iowait);
+
+ return iowait;
+}
+
+static void *pipe_write(void *data)
+{
+ struct data *d = data;
+ char buf[32];
+ int ret;
+
+ memset(buf, 0x55, sizeof(buf));
+ pthread_barrier_wait(&d->startup);
+ usleep(100000);
+
+ ret = write(d->out_fd, buf, sizeof(buf));
+ if (ret < 0) {
+ perror("write");
+ return NULL;
+ }
+
+ return NULL;
+}
+
+static int test_iowait(struct io_uring *ring, bool enabled)
+{
+ unsigned long long iowait_pre, iowait_post, iowait;
+ double iowait_ms_max_diff;
+ struct io_uring_cqe *cqe;
+ struct io_uring_sqe *sqe;
+ pthread_t thread;
+ double iowait_ms;
+ int ret, fds[2];
+ struct data d;
+ char buf[32];
+ void *tret;
+
+ if (pipe(fds) < 0) {
+ perror("pipe");
+ return T_EXIT_FAIL;
+ }
+ d.out_fd = fds[1];
+
+ pthread_barrier_init(&d.startup, NULL, 2);
+ pthread_create(&thread, NULL, pipe_write, &d);
+ pthread_barrier_wait(&d.startup);
+
+ io_uring_register_iowait(ring, enabled);
+
+ sqe = io_uring_get_sqe(ring);
+ io_uring_prep_read(sqe, fds[0], buf, sizeof(buf), 0);
+
+ io_uring_submit(ring);
+
+ iowait_pre = get_iowait();
+ ret = io_uring_wait_cqe(ring, &cqe);
+ if (ret) {
+ fprintf(stderr, "wait_cqe: %d\n", ret);
+ return T_EXIT_FAIL;
+ }
+ io_uring_cq_advance(ring, 1);
+
+ iowait_post = get_iowait();
+
+ /*
+ * writer sleeps for 100 ms, so max diff is 100 plus a tolerance of
+ * 10 ms
+ */
+ iowait_ms_max_diff = (enabled ? 100.0 : 0.0) + 10.0;
+
+ if (iowait_post > iowait_pre)
+ iowait = iowait_post - iowait_pre;
+ else
+ iowait = iowait_pre - iowait_post;
+ iowait_ms = ((double)iowait / sysconf(_SC_CLK_TCK)) * 1000;
+
+ if (iowait_ms > iowait_ms_max_diff)
+ ret = T_EXIT_FAIL;
+ else
+ ret = T_EXIT_PASS;
+
+ pthread_join(thread, &tret);
+ close(fds[0]);
+ close(fds[1]);
+ return ret;
+}
+
+int main(int argc, char *argv[])
+{
+ struct io_uring ring;
+ struct io_uring_params p = { };
+ int ret;
+
+ if (argc > 1)
+ return 0;
+
+ ret = t_create_ring_params(8, &ring, &p);
+ if (ret == T_SETUP_SKIP)
+ return T_EXIT_SKIP;
+ else if (ret != T_SETUP_OK)
+ return ret;
+
+ ret = test_iowait(&ring, false);
+ if (ret == T_EXIT_FAIL || ret == T_EXIT_SKIP)
+ return ret;
+
+ ret = test_iowait(&ring, true);
+ if (ret == T_EXIT_FAIL || ret == T_EXIT_SKIP)
+ return ret;
+
+ io_uring_queue_exit(&ring);
+ return T_EXIT_PASS;
+}
--
2.43.0
next prev parent reply other threads:[~2024-02-24 5:07 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-02-24 5:07 [PATCH v1 1/4] io_uring: only account cqring wait time as iowait if enabled for a ring David Wei
2024-02-24 5:07 ` [PATCH v1 2/4] liburing: add examples/proxy to .gitignore David Wei
2024-02-24 5:07 ` [PATCH v1 3/4] liburing: add helper for IORING_REGISTER_IOWAIT David Wei
2024-02-24 15:29 ` Jens Axboe
2024-02-24 16:39 ` David Wei
2024-02-24 5:07 ` David Wei [this message]
2024-02-24 15:28 ` [PATCH v1 1/4] io_uring: only account cqring wait time as iowait if enabled for a ring Jens Axboe
2024-02-24 15:31 ` Pavel Begunkov
2024-02-24 17:20 ` David Wei
2024-02-24 18:55 ` Jens Axboe
2024-02-25 1:39 ` Pavel Begunkov
2024-02-25 16:43 ` Jens Axboe
2024-02-25 21:11 ` Jens Axboe
2024-02-25 21:33 ` Jens Axboe
2024-02-26 14:56 ` Pavel Begunkov
2024-02-26 15:22 ` Jens Axboe
2024-02-24 18:51 ` Jens Axboe
2024-02-25 0:58 ` Pavel Begunkov
2024-02-25 16:39 ` Jens Axboe
2024-03-05 14:59 ` Christian Loehle
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
[email protected] \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox