| #ifndef _LIBAIO_H |
| #define _LIBAIO_H |
| |
| // Don't include the actual header uapi/aio_abi.h |
| // since libaio redefines the structs for some reason. |
| // Instead override those definitions with the ones below. |
| #define __LINUX__AIO_ABI_H |
| |
| #include <stdint.h> |
| |
| #if __UINTPTR_MAX__ == UINT64_MAX |
| #define PADDED_PTR(x, y) x |
| #elif __UINTPTR_MAX__ == UINT32_MAX |
| #define PADDED_PTR(x, y) x; unsigned y |
| #endif |
| |
| struct io_iocb_common { |
| PADDED_PTR(void *buf, __pad1); |
| __u64 nbytes; |
| __s64 offset; |
| __u64 reserved2; |
| __u32 flags; |
| __u32 resfd; |
| }; |
| |
| struct iocb { |
| PADDED_PTR(void *data, __pad1); |
| __u32 key; |
| __u32 aio_rw_flags; |
| __u16 aio_lio_opcode; |
| __s16 aio_reqprio; |
| __u32 aio_fildes; |
| union { |
| struct io_iocb_common c; |
| } u; |
| }; |
| |
| struct io_event { |
| PADDED_PTR(void *data, __pad1); |
| PADDED_PTR(struct iocb *obj, __pad2); |
| __s64 res; |
| __s64 res2; |
| }; |
| |
| typedef unsigned long io_context_t; |
| typedef io_context_t aio_context_t; |
| |
| #include <asyncio/AsyncIO.h> |
| |
| #define IO_CMD_PREAD 0 |
| #define IO_CMD_PWRITE 1 |
| #define IO_CMD_FSYNC 2 |
| #define IO_CMD_FDSYNC 3 |
| #define IO_CMD_POLL 5 |
| #define IO_CMD_NOOP 6 |
| #define IO_CMD_PREADV 7 |
| #define IO_CMD_PWRITEV 8 |
| |
| typedef void (*io_callback_t)(io_context_t ctx, struct iocb *iocb, long res, long res2); |
| |
| static inline int redirect_error(int ret) { |
| return ret == -1 ? -errno : ret; |
| } |
| |
| // libaio doesn't follow syscall convention, so errors are returned |
| // as negative values and errno isn't used. |
| |
| static inline int libaio_setup(int maxevents, io_context_t *ctxp) { |
| int ret = io_setup(maxevents, ctxp); |
| return redirect_error(ret); |
| } |
| |
| static inline int libaio_destroy(io_context_t ctx) { |
| int ret = io_destroy(ctx); |
| return redirect_error(ret); |
| } |
| |
| static inline int libaio_submit(io_context_t ctx, long nr, struct iocb *ios[]) { |
| int ret = io_submit(ctx, nr, ios); |
| return redirect_error(ret); |
| } |
| |
| static inline int libaio_cancel(io_context_t ctx, struct iocb *iocb, struct io_event *evt) { |
| int ret = io_cancel(ctx, iocb, evt); |
| return redirect_error(ret); |
| } |
| |
| static inline int libaio_getevents(io_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct timespec *timeout) { |
| int ret = io_getevents(ctx_id, min_nr, nr, events, timeout); |
| return redirect_error(ret); |
| } |
| |
| static inline void io_set_callback(struct iocb *iocb, io_callback_t cb) |
| { |
| iocb->data = (void *)cb; |
| } |
| |
| static inline int io_queue_init(int maxevents, io_context_t *ctxp) { |
| memset(ctxp, 0, sizeof(*ctxp)); |
| return libaio_setup(maxevents, ctxp); |
| } |
| |
| // Override the system calls with their libaio versions. |
| |
| #define io_setup(a, b) libaio_setup(a, b) |
| #define io_destroy(a) libaio_destroy(a) |
| #define io_submit(a, b, c) libaio_submit(a, b, c) |
| #define io_cancel(a, b, c) libaio_cancel(a, b, c) |
| #define io_getevents(a, b, c, d, e) libaio_getevents(a, b, c, d, e) |
| |
| #define io_queue_release(a) io_destroy(a) |
| |
| #endif |