1 #ifndef _LIBAIO_H 2 #define _LIBAIO_H 3 4 // Don't include the actual header uapi/aio_abi.h 5 // since libaio redefines the structs for some reason. 6 // Instead override those definitions with the ones below. 7 #define __LINUX__AIO_ABI_H 8 9 #include <stdint.h> 10 11 #if __UINTPTR_MAX__ == UINT64_MAX 12 #define PADDED_PTR(x, y) x 13 #elif __UINTPTR_MAX__ == UINT32_MAX 14 #define PADDED_PTR(x, y) x; unsigned y 15 #endif 16 17 struct io_iocb_common { 18 PADDED_PTR(void *buf, __pad1); 19 __u64 nbytes; 20 __s64 offset; 21 __u64 reserved2; 22 __u32 flags; 23 __u32 resfd; 24 }; 25 26 struct iocb { 27 PADDED_PTR(void *data, __pad1); 28 __u32 key; 29 __u32 aio_rw_flags; 30 __u16 aio_lio_opcode; 31 __s16 aio_reqprio; 32 __u32 aio_fildes; 33 union { 34 struct io_iocb_common c; 35 } u; 36 }; 37 38 struct io_event { 39 PADDED_PTR(void *data, __pad1); 40 PADDED_PTR(struct iocb *obj, __pad2); 41 __s64 res; 42 __s64 res2; 43 }; 44 45 typedef unsigned long io_context_t; 46 typedef io_context_t aio_context_t; 47 48 #include <asyncio/AsyncIO.h> 49 50 #define IO_CMD_PREAD 0 51 #define IO_CMD_PWRITE 1 52 #define IO_CMD_FSYNC 2 53 #define IO_CMD_FDSYNC 3 54 #define IO_CMD_POLL 5 55 #define IO_CMD_NOOP 6 56 #define IO_CMD_PREADV 7 57 #define IO_CMD_PWRITEV 8 58 59 typedef void (*io_callback_t)(io_context_t ctx, struct iocb *iocb, long res, long res2); 60 61 static inline int redirect_error(int ret) { 62 return ret == -1 ? -errno : ret; 63 } 64 65 // libaio doesn't follow syscall convention, so errors are returned 66 // as negative values and errno isn't used. 67 68 static inline int libaio_setup(int maxevents, io_context_t *ctxp) { 69 int ret = io_setup(maxevents, ctxp); 70 return redirect_error(ret); 71 } 72 73 static inline int libaio_destroy(io_context_t ctx) { 74 int ret = io_destroy(ctx); 75 return redirect_error(ret); 76 } 77 78 static inline int libaio_submit(io_context_t ctx, long nr, struct iocb *ios[]) { 79 int ret = io_submit(ctx, nr, ios); 80 return redirect_error(ret); 81 } 82 83 static inline int libaio_cancel(io_context_t ctx, struct iocb *iocb, struct io_event *evt) { 84 int ret = io_cancel(ctx, iocb, evt); 85 return redirect_error(ret); 86 } 87 88 static inline int libaio_getevents(io_context_t ctx_id, long min_nr, long nr, struct io_event *events, struct timespec *timeout) { 89 int ret = io_getevents(ctx_id, min_nr, nr, events, timeout); 90 return redirect_error(ret); 91 } 92 93 static inline void io_set_callback(struct iocb *iocb, io_callback_t cb) 94 { 95 iocb->data = (void *)cb; 96 } 97 98 static inline int io_queue_init(int maxevents, io_context_t *ctxp) { 99 memset(ctxp, 0, sizeof(*ctxp)); 100 return libaio_setup(maxevents, ctxp); 101 } 102 103 // Override the system calls with their libaio versions. 104 105 #define io_setup(a, b) libaio_setup(a, b) 106 #define io_destroy(a) libaio_destroy(a) 107 #define io_submit(a, b, c) libaio_submit(a, b, c) 108 #define io_cancel(a, b, c) libaio_cancel(a, b, c) 109 #define io_getevents(a, b, c, d, e) libaio_getevents(a, b, c, d, e) 110 111 #define io_queue_release(a) io_destroy(a) 112 113 #endif 114