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