Loading...
1#ifndef LIB_URING_H
2#define LIB_URING_H
3
4#ifdef __cplusplus
5extern "C" {
6#endif
7
8#include <sys/uio.h>
9#include <signal.h>
10#include <string.h>
11#include "../../include/uapi/linux/io_uring.h"
12#include <inttypes.h>
13#include <linux/swab.h>
14#include "barrier.h"
15
16/*
17 * Library interface to io_uring
18 */
19struct io_uring_sq {
20 unsigned *khead;
21 unsigned *ktail;
22 unsigned *kring_mask;
23 unsigned *kring_entries;
24 unsigned *kflags;
25 unsigned *kdropped;
26 unsigned *array;
27 struct io_uring_sqe *sqes;
28
29 unsigned sqe_head;
30 unsigned sqe_tail;
31
32 size_t ring_sz;
33};
34
35struct io_uring_cq {
36 unsigned *khead;
37 unsigned *ktail;
38 unsigned *kring_mask;
39 unsigned *kring_entries;
40 unsigned *koverflow;
41 struct io_uring_cqe *cqes;
42
43 size_t ring_sz;
44};
45
46struct io_uring {
47 struct io_uring_sq sq;
48 struct io_uring_cq cq;
49 int ring_fd;
50};
51
52/*
53 * System calls
54 */
55extern int io_uring_setup(unsigned entries, struct io_uring_params *p);
56extern int io_uring_enter(int fd, unsigned to_submit,
57 unsigned min_complete, unsigned flags, sigset_t *sig);
58extern int io_uring_register(int fd, unsigned int opcode, void *arg,
59 unsigned int nr_args);
60
61/*
62 * Library interface
63 */
64extern int io_uring_queue_init(unsigned entries, struct io_uring *ring,
65 unsigned flags);
66extern int io_uring_queue_mmap(int fd, struct io_uring_params *p,
67 struct io_uring *ring);
68extern void io_uring_queue_exit(struct io_uring *ring);
69extern int io_uring_peek_cqe(struct io_uring *ring,
70 struct io_uring_cqe **cqe_ptr);
71extern int io_uring_wait_cqe(struct io_uring *ring,
72 struct io_uring_cqe **cqe_ptr);
73extern int io_uring_submit(struct io_uring *ring);
74extern struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring);
75
76/*
77 * Must be called after io_uring_{peek,wait}_cqe() after the cqe has
78 * been processed by the application.
79 */
80static inline void io_uring_cqe_seen(struct io_uring *ring,
81 struct io_uring_cqe *cqe)
82{
83 if (cqe) {
84 struct io_uring_cq *cq = &ring->cq;
85
86 (*cq->khead)++;
87 /*
88 * Ensure that the kernel sees our new head, the kernel has
89 * the matching read barrier.
90 */
91 write_barrier();
92 }
93}
94
95/*
96 * Command prep helpers
97 */
98static inline void io_uring_sqe_set_data(struct io_uring_sqe *sqe, void *data)
99{
100 sqe->user_data = (unsigned long) data;
101}
102
103static inline void *io_uring_cqe_get_data(struct io_uring_cqe *cqe)
104{
105 return (void *) (uintptr_t) cqe->user_data;
106}
107
108static inline void io_uring_prep_rw(int op, struct io_uring_sqe *sqe, int fd,
109 const void *addr, unsigned len,
110 off_t offset)
111{
112 memset(sqe, 0, sizeof(*sqe));
113 sqe->opcode = op;
114 sqe->fd = fd;
115 sqe->off = offset;
116 sqe->addr = (unsigned long) addr;
117 sqe->len = len;
118}
119
120static inline void io_uring_prep_readv(struct io_uring_sqe *sqe, int fd,
121 const struct iovec *iovecs,
122 unsigned nr_vecs, off_t offset)
123{
124 io_uring_prep_rw(IORING_OP_READV, sqe, fd, iovecs, nr_vecs, offset);
125}
126
127static inline void io_uring_prep_read_fixed(struct io_uring_sqe *sqe, int fd,
128 void *buf, unsigned nbytes,
129 off_t offset)
130{
131 io_uring_prep_rw(IORING_OP_READ_FIXED, sqe, fd, buf, nbytes, offset);
132}
133
134static inline void io_uring_prep_writev(struct io_uring_sqe *sqe, int fd,
135 const struct iovec *iovecs,
136 unsigned nr_vecs, off_t offset)
137{
138 io_uring_prep_rw(IORING_OP_WRITEV, sqe, fd, iovecs, nr_vecs, offset);
139}
140
141static inline void io_uring_prep_write_fixed(struct io_uring_sqe *sqe, int fd,
142 const void *buf, unsigned nbytes,
143 off_t offset)
144{
145 io_uring_prep_rw(IORING_OP_WRITE_FIXED, sqe, fd, buf, nbytes, offset);
146}
147
148static inline void io_uring_prep_poll_add(struct io_uring_sqe *sqe, int fd,
149 unsigned poll_mask)
150{
151 memset(sqe, 0, sizeof(*sqe));
152 sqe->opcode = IORING_OP_POLL_ADD;
153 sqe->fd = fd;
154#if __BYTE_ORDER == __BIG_ENDIAN
155 poll_mask = __swahw32(poll_mask);
156#endif
157 sqe->poll_events = poll_mask;
158}
159
160static inline void io_uring_prep_poll_remove(struct io_uring_sqe *sqe,
161 void *user_data)
162{
163 memset(sqe, 0, sizeof(*sqe));
164 sqe->opcode = IORING_OP_POLL_REMOVE;
165 sqe->addr = (unsigned long) user_data;
166}
167
168static inline void io_uring_prep_fsync(struct io_uring_sqe *sqe, int fd,
169 unsigned fsync_flags)
170{
171 memset(sqe, 0, sizeof(*sqe));
172 sqe->opcode = IORING_OP_FSYNC;
173 sqe->fd = fd;
174 sqe->fsync_flags = fsync_flags;
175}
176
177static inline void io_uring_prep_nop(struct io_uring_sqe *sqe)
178{
179 memset(sqe, 0, sizeof(*sqe));
180 sqe->opcode = IORING_OP_NOP;
181}
182
183#ifdef __cplusplus
184}
185#endif
186
187#endif
1#ifndef LIB_URING_H
2#define LIB_URING_H
3
4#ifdef __cplusplus
5extern "C" {
6#endif
7
8#include <sys/uio.h>
9#include <signal.h>
10#include <string.h>
11#include "../../include/uapi/linux/io_uring.h"
12#include <inttypes.h>
13#include "barrier.h"
14
15/*
16 * Library interface to io_uring
17 */
18struct io_uring_sq {
19 unsigned *khead;
20 unsigned *ktail;
21 unsigned *kring_mask;
22 unsigned *kring_entries;
23 unsigned *kflags;
24 unsigned *kdropped;
25 unsigned *array;
26 struct io_uring_sqe *sqes;
27
28 unsigned sqe_head;
29 unsigned sqe_tail;
30
31 size_t ring_sz;
32};
33
34struct io_uring_cq {
35 unsigned *khead;
36 unsigned *ktail;
37 unsigned *kring_mask;
38 unsigned *kring_entries;
39 unsigned *koverflow;
40 struct io_uring_cqe *cqes;
41
42 size_t ring_sz;
43};
44
45struct io_uring {
46 struct io_uring_sq sq;
47 struct io_uring_cq cq;
48 int ring_fd;
49};
50
51/*
52 * System calls
53 */
54extern int io_uring_setup(unsigned entries, struct io_uring_params *p);
55extern int io_uring_enter(int fd, unsigned to_submit,
56 unsigned min_complete, unsigned flags, sigset_t *sig);
57extern int io_uring_register(int fd, unsigned int opcode, void *arg,
58 unsigned int nr_args);
59
60/*
61 * Library interface
62 */
63extern int io_uring_queue_init(unsigned entries, struct io_uring *ring,
64 unsigned flags);
65extern int io_uring_queue_mmap(int fd, struct io_uring_params *p,
66 struct io_uring *ring);
67extern void io_uring_queue_exit(struct io_uring *ring);
68extern int io_uring_peek_cqe(struct io_uring *ring,
69 struct io_uring_cqe **cqe_ptr);
70extern int io_uring_wait_cqe(struct io_uring *ring,
71 struct io_uring_cqe **cqe_ptr);
72extern int io_uring_submit(struct io_uring *ring);
73extern struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring);
74
75/*
76 * Must be called after io_uring_{peek,wait}_cqe() after the cqe has
77 * been processed by the application.
78 */
79static inline void io_uring_cqe_seen(struct io_uring *ring,
80 struct io_uring_cqe *cqe)
81{
82 if (cqe) {
83 struct io_uring_cq *cq = &ring->cq;
84
85 (*cq->khead)++;
86 /*
87 * Ensure that the kernel sees our new head, the kernel has
88 * the matching read barrier.
89 */
90 write_barrier();
91 }
92}
93
94/*
95 * Command prep helpers
96 */
97static inline void io_uring_sqe_set_data(struct io_uring_sqe *sqe, void *data)
98{
99 sqe->user_data = (unsigned long) data;
100}
101
102static inline void *io_uring_cqe_get_data(struct io_uring_cqe *cqe)
103{
104 return (void *) (uintptr_t) cqe->user_data;
105}
106
107static inline void io_uring_prep_rw(int op, struct io_uring_sqe *sqe, int fd,
108 const void *addr, unsigned len,
109 off_t offset)
110{
111 memset(sqe, 0, sizeof(*sqe));
112 sqe->opcode = op;
113 sqe->fd = fd;
114 sqe->off = offset;
115 sqe->addr = (unsigned long) addr;
116 sqe->len = len;
117}
118
119static inline void io_uring_prep_readv(struct io_uring_sqe *sqe, int fd,
120 const struct iovec *iovecs,
121 unsigned nr_vecs, off_t offset)
122{
123 io_uring_prep_rw(IORING_OP_READV, sqe, fd, iovecs, nr_vecs, offset);
124}
125
126static inline void io_uring_prep_read_fixed(struct io_uring_sqe *sqe, int fd,
127 void *buf, unsigned nbytes,
128 off_t offset)
129{
130 io_uring_prep_rw(IORING_OP_READ_FIXED, sqe, fd, buf, nbytes, offset);
131}
132
133static inline void io_uring_prep_writev(struct io_uring_sqe *sqe, int fd,
134 const struct iovec *iovecs,
135 unsigned nr_vecs, off_t offset)
136{
137 io_uring_prep_rw(IORING_OP_WRITEV, sqe, fd, iovecs, nr_vecs, offset);
138}
139
140static inline void io_uring_prep_write_fixed(struct io_uring_sqe *sqe, int fd,
141 const void *buf, unsigned nbytes,
142 off_t offset)
143{
144 io_uring_prep_rw(IORING_OP_WRITE_FIXED, sqe, fd, buf, nbytes, offset);
145}
146
147static inline void io_uring_prep_poll_add(struct io_uring_sqe *sqe, int fd,
148 short poll_mask)
149{
150 memset(sqe, 0, sizeof(*sqe));
151 sqe->opcode = IORING_OP_POLL_ADD;
152 sqe->fd = fd;
153 sqe->poll_events = poll_mask;
154}
155
156static inline void io_uring_prep_poll_remove(struct io_uring_sqe *sqe,
157 void *user_data)
158{
159 memset(sqe, 0, sizeof(*sqe));
160 sqe->opcode = IORING_OP_POLL_REMOVE;
161 sqe->addr = (unsigned long) user_data;
162}
163
164static inline void io_uring_prep_fsync(struct io_uring_sqe *sqe, int fd,
165 unsigned fsync_flags)
166{
167 memset(sqe, 0, sizeof(*sqe));
168 sqe->opcode = IORING_OP_FSYNC;
169 sqe->fd = fd;
170 sqe->fsync_flags = fsync_flags;
171}
172
173static inline void io_uring_prep_nop(struct io_uring_sqe *sqe)
174{
175 memset(sqe, 0, sizeof(*sqe));
176 sqe->opcode = IORING_OP_NOP;
177}
178
179#ifdef __cplusplus
180}
181#endif
182
183#endif