[prev in list] [next in list] [prev in thread] [next in thread] 

List:       linux-aio
Subject:    [PATCH] libaio: elide the syscall if the completed events greater than min_nr
From:       Rain <rain.by.zhou () gmail ! com>
Date:       2021-08-09 8:33:35
Message-ID: 20210809083335.GA95212 () RaindeMacBook-Pro ! local
[Download RAW message or body]

Hi,

> We noticed that many applications elide the call of io_getevents as possible as the \
> can do, like seastar, fio. So let's do it.

I submitted this patch once before, but there was no response at that time. I \
submitted it again, hoping to have some suggestions. The patch related to \
https://pagure.io/libaio/issue/2

Signed-off-by: Rain <rain.by.zhou@gmail.com>
---
 src/aio_ring.h     |  2 ++
 src/arch.h         | 14 ++++++++++++++
 src/io_getevents.c | 29 ++++++++++++++++++++++++++++-
 3 files changed, 44 insertions(+), 1 deletion(-)
 create mode 100644 src/arch.h

diff --git a/src/aio_ring.h b/src/aio_ring.h
index 3842c4b..489f0d6 100644
--- a/src/aio_ring.h
+++ b/src/aio_ring.h
@@ -31,6 +31,8 @@ struct aio_ring {
 	unsigned        compat_features;
 	unsigned        incompat_features;
 	unsigned        header_length;  /* size of aio_ring */
+
+	struct io_event events[0];
 };
 
 static inline int aio_ring_is_empty(io_context_t ctx, struct timespec *timeout)
diff --git a/src/arch.h b/src/arch.h
new file mode 100644
index 0000000..a03ed98
--- /dev/null
+++ b/src/arch.h
@@ -0,0 +1,14 @@
+#ifndef _AIO_ARCH_H
+#define _AIO_ARCH_H
+
+#ifdef __x86_64__
+#define read_barrier() __asm__ __volatile__("lfence" ::: "memory")
+#else
+#ifdef __i386__
+#define read_barrier() __asm__ __volatile__("" : : : "memory")
+#else
+#define read_barrier() __sync_synchronize()
+#endif
+#endif
+
+#endif /* _AIO_ARCH_H */
diff --git a/src/io_getevents.c b/src/io_getevents.c
index 90d6081..f594119 100644
--- a/src/io_getevents.c
+++ b/src/io_getevents.c
@@ -22,14 +22,41 @@
 #include <time.h>
 #include "syscall.h"
 #include "aio_ring.h"
+#include "arch.h"
 
 io_syscall5(int, __io_getevents_0_4, io_getevents, io_context_t, ctx, long, min_nr, \
long, nr, struct io_event *, events, struct timespec *, timeout)  
+long reap_events_from_ring(io_context_t ctx, long max_nr, struct io_event *events) {
+	struct aio_ring *ring = (struct aio_ring *)ctx;
+	unsigned head;
+	long i = 0;
+
+	while (i < max_nr) {
+		head = ring->head;
+
+		if (head == ring->tail) {
+			break;
+		} else {
+			events[i++] = ring->events[head];
+			read_barrier();
+			ring->head = (head + 1) % ring->nr;
+		}
+	}
+	return i;
+}
+
 int io_getevents_0_4(io_context_t ctx, long min_nr, long nr, struct io_event * \
events, struct timespec * timeout)  {
+	int n = 0;
+
 	if (aio_ring_is_empty(ctx, timeout))
 		return 0;
-	return __io_getevents_0_4(ctx, min_nr, nr, events, timeout);
+
+	n = reap_events_from_ring(ctx, nr, events);
+	if (n >= min_nr)
+		return n;
+
+	return __io_getevents_0_4(ctx, min_nr - n, nr - n, &events[n], timeout);
 }
 
 DEFSYMVER(io_getevents_0_4, io_getevents, 0.4)
-- 
2.17.1


--
To unsubscribe, send a message with 'unsubscribe linux-aio' in
the body to majordomo@kvack.org.  For more info on Linux AIO,
see: http://www.kvack.org/aio/
Don't email: <a href=mailto:"aart@kvack.org">aart@kvack.org</a>


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic