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 
redirect_error(int ret)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 
libaio_setup(int maxevents,io_context_t * ctxp)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 
libaio_destroy(io_context_t ctx)73 static inline int libaio_destroy(io_context_t ctx) {
74     int ret = io_destroy(ctx);
75     return redirect_error(ret);
76 }
77 
libaio_submit(io_context_t ctx,long nr,struct iocb * ios[])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 
libaio_cancel(io_context_t ctx,struct iocb * iocb,struct io_event * evt)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 
libaio_getevents(io_context_t ctx_id,long min_nr,long nr,struct io_event * events,struct timespec * timeout)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 
io_set_callback(struct iocb * iocb,io_callback_t cb)93 static inline void io_set_callback(struct iocb *iocb, io_callback_t cb)
94 {
95     iocb->data = (void *)cb;
96 }
97 
io_queue_init(int maxevents,io_context_t * ctxp)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