*** empty log message ***

master
Marc Alexander Lehmann 2019-07-01 21:47:42 +00:00
parent dcfe78d01a
commit a242c41779
4 changed files with 108 additions and 54 deletions

View File

@ -7,6 +7,8 @@ TODO: revisit 59.x timer in the light of mdoenr powersaving
io_asubmit also retursn EINTR.
- cleanup: replace expect_true/false and noinline by their
libecb counterparts.
- move syscall infrastructure from ev_linuxaio.c to ev.c.
- prepare io_uring integration.
4.27 Thu Jun 27 22:43:44 CEST 2019
- linux aio backend almost completely rewritten to work around its

104
ev.c
View File

@ -334,6 +334,14 @@
# endif
#endif
#ifndef EV_USE_IOURING
# if __linux
# define EV_USE_IOURING 0
# else
# define EV_USE_IOURING 0
# endif
#endif
#ifndef EV_USE_INOTIFY
# if __linux && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 4))
# define EV_USE_INOTIFY EV_FEATURE_OS
@ -408,6 +416,7 @@
# define clock_gettime(id, ts) syscall (SYS_clock_gettime, (id), (ts))
# undef EV_USE_MONOTONIC
# define EV_USE_MONOTONIC 1
# define EV_NEED_SYSCALL 1
# else
# undef EV_USE_CLOCK_SYSCALL
# define EV_USE_CLOCK_SYSCALL 0
@ -443,6 +452,23 @@
# if !SYS_io_getevents || !EV_USE_EPOLL /* ev_linxaio uses ev_poll.c:ev_epoll_create */
# undef EV_USE_LINUXAIO
# define EV_USE_LINUXAIO 0
# else
# define EV_NEED_SYSCALL 1
# endif
#endif
#if EV_USE_IOURING
# include <sys/syscall.h>
# if !__alpha && !SYS_io_uring_setup
# define SYS_io_uring_setup 425
# define SYS_io_uring_enter 426
# define SYS_io_uring_wregister 427
# endif
# if SYS_io_uring_setup
# define EV_NEED_SYSCALL 1
# else
# undef EV_USE_IOURING
# define EV_USE_IOURING 0
# endif
#endif
@ -494,7 +520,66 @@ struct signalfd_siginfo
};
#endif
/**/
/*****************************************************************************/
#if EV_NEED_SYSCALL
#include <sys/syscall.h>
/*
* define some syscall wrappers for common architectures
* this is mostly for nice looks during debugging, not performance.
* our syscalls return < 0, not == -1, on error. which is good
* enough for linux aio.
* TODO: arm is also common nowadays, maybe even mips and x86
* TODO: after implementing this, it suddenly looks like overkill, but its hard to remove...
*/
#if __GNUC__ && __linux && ECB_AMD64 && !defined __OPTIMIZE_SIZE__
/* the costly errno access probably kills this for size optimisation */
#define ev_syscall(nr,narg,arg1,arg2,arg3,arg4,arg5) \
({ \
long res; \
register unsigned long r5 __asm__ ("r8" ); \
register unsigned long r4 __asm__ ("r10"); \
register unsigned long r3 __asm__ ("rdx"); \
register unsigned long r2 __asm__ ("rsi"); \
register unsigned long r1 __asm__ ("rdi"); \
if (narg >= 5) r5 = (unsigned long)(arg5); \
if (narg >= 4) r4 = (unsigned long)(arg4); \
if (narg >= 3) r3 = (unsigned long)(arg3); \
if (narg >= 2) r2 = (unsigned long)(arg2); \
if (narg >= 1) r1 = (unsigned long)(arg1); \
__asm__ __volatile__ ( \
"syscall\n\t" \
: "=a" (res) \
: "0" (nr), "r" (r1), "r" (r2), "r" (r3), "r" (r4), "r" (r5) \
: "cc", "r11", "cx", "memory"); \
errno = -res; \
res; \
})
#endif
#ifdef ev_syscall
#define ev_syscall0(nr) ev_syscall (nr, 0, 0, 0, 0, 0, 0
#define ev_syscall1(nr,arg1) ev_syscall (nr, 1, arg1, 0, 0, 0, 0)
#define ev_syscall2(nr,arg1,arg2) ev_syscall (nr, 2, arg1, arg2, 0, 0, 0)
#define ev_syscall3(nr,arg1,arg2,arg3) ev_syscall (nr, 3, arg1, arg2, arg3, 0, 0)
#define ev_syscall4(nr,arg1,arg2,arg3,arg4) ev_syscall (nr, 3, arg1, arg2, arg3, arg4, 0)
#define ev_syscall5(nr,arg1,arg2,arg3,arg4,arg5) ev_syscall (nr, 5, arg1, arg2, arg3, arg4, arg5)
#else
#define ev_syscall0(nr) syscall (nr)
#define ev_syscall1(nr,arg1) syscall (nr, arg1)
#define ev_syscall2(nr,arg1,arg2) syscall (nr, arg1, arg2)
#define ev_syscall3(nr,arg1,arg2,arg3) syscall (nr, arg1, arg2, arg3)
#define ev_syscall4(nr,arg1,arg2,arg3,arg4) syscall (nr, arg1, arg2, arg3, arg4)
#define ev_syscall5(nr,arg1,arg2,arg3,arg4,arg5) syscall (nr, arg1, arg2, arg3, arg4, arg5)
#endif
#endif
/*****************************************************************************/
#if EV_VERIFY >= 3
# define EV_FREQUENT_CHECK ev_verify (EV_A)
@ -2739,6 +2824,9 @@ childcb (EV_P_ ev_signal *sw, int revents)
#if EV_USE_LINUXAIO
# include "ev_linuxaio.c"
#endif
#if EV_USE_IOURING
# include "ev_iouring.c"
#endif
#if EV_USE_POLL
# include "ev_poll.c"
#endif
@ -2780,6 +2868,7 @@ ev_supported_backends (void) EV_NOEXCEPT
if (EV_USE_KQUEUE ) flags |= EVBACKEND_KQUEUE;
if (EV_USE_EPOLL ) flags |= EVBACKEND_EPOLL;
if (EV_USE_LINUXAIO) flags |= EVBACKEND_LINUXAIO;
if (EV_USE_IOURING ) flags |= EVBACKEND_IOURING;
if (EV_USE_POLL ) flags |= EVBACKEND_POLL;
if (EV_USE_SELECT ) flags |= EVBACKEND_SELECT;
@ -2810,6 +2899,10 @@ ev_recommended_backends (void) EV_NOEXCEPT
#if !EV_RECOMMEND_LINUXAIO
flags &= ~EVBACKEND_LINUXAIO;
#endif
/* TODO: linuxaio is super experimental */
#if !EV_RECOMMEND_IOURING
flags &= ~EVBACKEND_IOURING;
#endif
return flags;
}
@ -2963,6 +3056,9 @@ loop_init (EV_P_ unsigned int flags) EV_NOEXCEPT
#if EV_USE_KQUEUE
if (!backend && (flags & EVBACKEND_KQUEUE )) backend = kqueue_init (EV_A_ flags);
#endif
#if EV_USE_IOURING
if (!backend && (flags & EVBACKEND_IOURING )) backend = iouring_init (EV_A_ flags);
#endif
#if EV_USE_LINUXAIO
if (!backend && (flags & EVBACKEND_LINUXAIO)) backend = linuxaio_init (EV_A_ flags);
#endif
@ -3046,6 +3142,9 @@ ev_loop_destroy (EV_P)
#if EV_USE_KQUEUE
if (backend == EVBACKEND_KQUEUE ) kqueue_destroy (EV_A);
#endif
#if EV_USE_IOURING
if (backend == EVBACKEND_IOURING ) iouring_destroy (EV_A);
#endif
#if EV_USE_LINUXAIO
if (backend == EVBACKEND_LINUXAIO) linuxaio_destroy (EV_A);
#endif
@ -3113,6 +3212,9 @@ loop_fork (EV_P)
#if EV_USE_KQUEUE
if (backend == EVBACKEND_KQUEUE ) kqueue_fork (EV_A);
#endif
#if EV_USE_IOURING
if (backend == EVBACKEND_IOURING ) iouring_fork (EV_A);
#endif
#if EV_USE_LINUXAIO
if (backend == EVBACKEND_LINUXAIO) linuxaio_fork (EV_A);
#endif

5
ev.h
View File

@ -522,8 +522,9 @@ enum {
EVBACKEND_KQUEUE = 0x00000008U, /* bsd, broken on osx */
EVBACKEND_DEVPOLL = 0x00000010U, /* solaris 8 */ /* NYI */
EVBACKEND_PORT = 0x00000020U, /* solaris 10 */
EVBACKEND_LINUXAIO = 0x00000040U, /* Linuix AIO */
EVBACKEND_ALL = 0x0000007FU, /* all known backends */
EVBACKEND_LINUXAIO = 0x00000040U, /* linuix AIO */
EVBACKEND_IOURING = 0x00000080U, /* linux io_uring, TBD */
EVBACKEND_ALL = 0x000000FFU, /* all known backends */
EVBACKEND_MASK = 0x0000FFFFU /* all future backends */
};

View File

@ -118,57 +118,6 @@ struct aio_ring
struct io_event io_events[0];
};
/*
* define some syscall wrappers for common architectures
* this is mostly for nice looks during debugging, not performance.
* our syscalls return < 0, not == -1, on error. which is good
* enough for linux aio.
* TODO: arm is also common nowadays, maybe even mips and x86
* TODO: after implementing this, it suddenly looks like overkill, but its hard to remove...
*/
#if __GNUC__ && __linux && ECB_AMD64 && !defined __OPTIMIZE_SIZE__
/* the costly errno access probably kills this for size optimisation */
#define ev_syscall(nr,narg,arg1,arg2,arg3,arg4,arg5) \
({ \
long res; \
register unsigned long r5 __asm__ ("r8" ); \
register unsigned long r4 __asm__ ("r10"); \
register unsigned long r3 __asm__ ("rdx"); \
register unsigned long r2 __asm__ ("rsi"); \
register unsigned long r1 __asm__ ("rdi"); \
if (narg >= 5) r5 = (unsigned long)(arg5); \
if (narg >= 4) r4 = (unsigned long)(arg4); \
if (narg >= 3) r3 = (unsigned long)(arg3); \
if (narg >= 2) r2 = (unsigned long)(arg2); \
if (narg >= 1) r1 = (unsigned long)(arg1); \
__asm__ __volatile__ ( \
"syscall\n\t" \
: "=a" (res) \
: "0" (nr), "r" (r1), "r" (r2), "r" (r3), "r" (r4), "r" (r5) \
: "cc", "r11", "cx", "memory"); \
errno = -res; \
res; \
})
#endif
#ifdef ev_syscall
#define ev_syscall0(nr) ev_syscall (nr, 0, 0, 0, 0, 0, 0
#define ev_syscall1(nr,arg1) ev_syscall (nr, 1, arg1, 0, 0, 0, 0)
#define ev_syscall2(nr,arg1,arg2) ev_syscall (nr, 2, arg1, arg2, 0, 0, 0)
#define ev_syscall3(nr,arg1,arg2,arg3) ev_syscall (nr, 3, arg1, arg2, arg3, 0, 0)
#define ev_syscall4(nr,arg1,arg2,arg3,arg4) ev_syscall (nr, 3, arg1, arg2, arg3, arg4, 0)
#define ev_syscall5(nr,arg1,arg2,arg3,arg4,arg5) ev_syscall (nr, 5, arg1, arg2, arg3, arg4, arg5)
#else
#define ev_syscall0(nr) syscall (nr)
#define ev_syscall1(nr,arg1) syscall (nr, arg1)
#define ev_syscall2(nr,arg1,arg2) syscall (nr, arg1, arg2)
#define ev_syscall3(nr,arg1,arg2,arg3) syscall (nr, arg1, arg2, arg3)
#define ev_syscall4(nr,arg1,arg2,arg3,arg4) syscall (nr, arg1, arg2, arg3, arg4)
#define ev_syscall5(nr,arg1,arg2,arg3,arg4,arg5) syscall (nr, arg1, arg2, arg3, arg4, arg5)
#endif
inline_size
int
evsys_io_setup (unsigned nr_events, aio_context_t *ctx_idp)