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