18c2ecf20Sopenharmony_ci#ifndef LIB_URING_H
28c2ecf20Sopenharmony_ci#define LIB_URING_H
38c2ecf20Sopenharmony_ci
48c2ecf20Sopenharmony_ci#ifdef __cplusplus
58c2ecf20Sopenharmony_ciextern "C" {
68c2ecf20Sopenharmony_ci#endif
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <sys/uio.h>
98c2ecf20Sopenharmony_ci#include <signal.h>
108c2ecf20Sopenharmony_ci#include <string.h>
118c2ecf20Sopenharmony_ci#include "../../include/uapi/linux/io_uring.h"
128c2ecf20Sopenharmony_ci#include <inttypes.h>
138c2ecf20Sopenharmony_ci#include <linux/swab.h>
148c2ecf20Sopenharmony_ci#include "barrier.h"
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci/*
178c2ecf20Sopenharmony_ci * Library interface to io_uring
188c2ecf20Sopenharmony_ci */
198c2ecf20Sopenharmony_cistruct io_uring_sq {
208c2ecf20Sopenharmony_ci	unsigned *khead;
218c2ecf20Sopenharmony_ci	unsigned *ktail;
228c2ecf20Sopenharmony_ci	unsigned *kring_mask;
238c2ecf20Sopenharmony_ci	unsigned *kring_entries;
248c2ecf20Sopenharmony_ci	unsigned *kflags;
258c2ecf20Sopenharmony_ci	unsigned *kdropped;
268c2ecf20Sopenharmony_ci	unsigned *array;
278c2ecf20Sopenharmony_ci	struct io_uring_sqe *sqes;
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci	unsigned sqe_head;
308c2ecf20Sopenharmony_ci	unsigned sqe_tail;
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci	size_t ring_sz;
338c2ecf20Sopenharmony_ci};
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_cistruct io_uring_cq {
368c2ecf20Sopenharmony_ci	unsigned *khead;
378c2ecf20Sopenharmony_ci	unsigned *ktail;
388c2ecf20Sopenharmony_ci	unsigned *kring_mask;
398c2ecf20Sopenharmony_ci	unsigned *kring_entries;
408c2ecf20Sopenharmony_ci	unsigned *koverflow;
418c2ecf20Sopenharmony_ci	struct io_uring_cqe *cqes;
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci	size_t ring_sz;
448c2ecf20Sopenharmony_ci};
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_cistruct io_uring {
478c2ecf20Sopenharmony_ci	struct io_uring_sq sq;
488c2ecf20Sopenharmony_ci	struct io_uring_cq cq;
498c2ecf20Sopenharmony_ci	int ring_fd;
508c2ecf20Sopenharmony_ci};
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci/*
538c2ecf20Sopenharmony_ci * System calls
548c2ecf20Sopenharmony_ci */
558c2ecf20Sopenharmony_ciextern int io_uring_setup(unsigned entries, struct io_uring_params *p);
568c2ecf20Sopenharmony_ciextern int io_uring_enter(int fd, unsigned to_submit,
578c2ecf20Sopenharmony_ci	unsigned min_complete, unsigned flags, sigset_t *sig);
588c2ecf20Sopenharmony_ciextern int io_uring_register(int fd, unsigned int opcode, void *arg,
598c2ecf20Sopenharmony_ci	unsigned int nr_args);
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/*
628c2ecf20Sopenharmony_ci * Library interface
638c2ecf20Sopenharmony_ci */
648c2ecf20Sopenharmony_ciextern int io_uring_queue_init(unsigned entries, struct io_uring *ring,
658c2ecf20Sopenharmony_ci	unsigned flags);
668c2ecf20Sopenharmony_ciextern int io_uring_queue_mmap(int fd, struct io_uring_params *p,
678c2ecf20Sopenharmony_ci	struct io_uring *ring);
688c2ecf20Sopenharmony_ciextern void io_uring_queue_exit(struct io_uring *ring);
698c2ecf20Sopenharmony_ciextern int io_uring_peek_cqe(struct io_uring *ring,
708c2ecf20Sopenharmony_ci	struct io_uring_cqe **cqe_ptr);
718c2ecf20Sopenharmony_ciextern int io_uring_wait_cqe(struct io_uring *ring,
728c2ecf20Sopenharmony_ci	struct io_uring_cqe **cqe_ptr);
738c2ecf20Sopenharmony_ciextern int io_uring_submit(struct io_uring *ring);
748c2ecf20Sopenharmony_ciextern struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring);
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci/*
778c2ecf20Sopenharmony_ci * Must be called after io_uring_{peek,wait}_cqe() after the cqe has
788c2ecf20Sopenharmony_ci * been processed by the application.
798c2ecf20Sopenharmony_ci */
808c2ecf20Sopenharmony_cistatic inline void io_uring_cqe_seen(struct io_uring *ring,
818c2ecf20Sopenharmony_ci				     struct io_uring_cqe *cqe)
828c2ecf20Sopenharmony_ci{
838c2ecf20Sopenharmony_ci	if (cqe) {
848c2ecf20Sopenharmony_ci		struct io_uring_cq *cq = &ring->cq;
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci		(*cq->khead)++;
878c2ecf20Sopenharmony_ci		/*
888c2ecf20Sopenharmony_ci		 * Ensure that the kernel sees our new head, the kernel has
898c2ecf20Sopenharmony_ci		 * the matching read barrier.
908c2ecf20Sopenharmony_ci		 */
918c2ecf20Sopenharmony_ci		write_barrier();
928c2ecf20Sopenharmony_ci	}
938c2ecf20Sopenharmony_ci}
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci/*
968c2ecf20Sopenharmony_ci * Command prep helpers
978c2ecf20Sopenharmony_ci */
988c2ecf20Sopenharmony_cistatic inline void io_uring_sqe_set_data(struct io_uring_sqe *sqe, void *data)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	sqe->user_data = (unsigned long) data;
1018c2ecf20Sopenharmony_ci}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_cistatic inline void *io_uring_cqe_get_data(struct io_uring_cqe *cqe)
1048c2ecf20Sopenharmony_ci{
1058c2ecf20Sopenharmony_ci	return (void *) (uintptr_t) cqe->user_data;
1068c2ecf20Sopenharmony_ci}
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_cistatic inline void io_uring_prep_rw(int op, struct io_uring_sqe *sqe, int fd,
1098c2ecf20Sopenharmony_ci				    const void *addr, unsigned len,
1108c2ecf20Sopenharmony_ci				    off_t offset)
1118c2ecf20Sopenharmony_ci{
1128c2ecf20Sopenharmony_ci	memset(sqe, 0, sizeof(*sqe));
1138c2ecf20Sopenharmony_ci	sqe->opcode = op;
1148c2ecf20Sopenharmony_ci	sqe->fd = fd;
1158c2ecf20Sopenharmony_ci	sqe->off = offset;
1168c2ecf20Sopenharmony_ci	sqe->addr = (unsigned long) addr;
1178c2ecf20Sopenharmony_ci	sqe->len = len;
1188c2ecf20Sopenharmony_ci}
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_cistatic inline void io_uring_prep_readv(struct io_uring_sqe *sqe, int fd,
1218c2ecf20Sopenharmony_ci				       const struct iovec *iovecs,
1228c2ecf20Sopenharmony_ci				       unsigned nr_vecs, off_t offset)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	io_uring_prep_rw(IORING_OP_READV, sqe, fd, iovecs, nr_vecs, offset);
1258c2ecf20Sopenharmony_ci}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cistatic inline void io_uring_prep_read_fixed(struct io_uring_sqe *sqe, int fd,
1288c2ecf20Sopenharmony_ci					    void *buf, unsigned nbytes,
1298c2ecf20Sopenharmony_ci					    off_t offset)
1308c2ecf20Sopenharmony_ci{
1318c2ecf20Sopenharmony_ci	io_uring_prep_rw(IORING_OP_READ_FIXED, sqe, fd, buf, nbytes, offset);
1328c2ecf20Sopenharmony_ci}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_cistatic inline void io_uring_prep_writev(struct io_uring_sqe *sqe, int fd,
1358c2ecf20Sopenharmony_ci					const struct iovec *iovecs,
1368c2ecf20Sopenharmony_ci					unsigned nr_vecs, off_t offset)
1378c2ecf20Sopenharmony_ci{
1388c2ecf20Sopenharmony_ci	io_uring_prep_rw(IORING_OP_WRITEV, sqe, fd, iovecs, nr_vecs, offset);
1398c2ecf20Sopenharmony_ci}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_cistatic inline void io_uring_prep_write_fixed(struct io_uring_sqe *sqe, int fd,
1428c2ecf20Sopenharmony_ci					     const void *buf, unsigned nbytes,
1438c2ecf20Sopenharmony_ci					     off_t offset)
1448c2ecf20Sopenharmony_ci{
1458c2ecf20Sopenharmony_ci	io_uring_prep_rw(IORING_OP_WRITE_FIXED, sqe, fd, buf, nbytes, offset);
1468c2ecf20Sopenharmony_ci}
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_cistatic inline void io_uring_prep_poll_add(struct io_uring_sqe *sqe, int fd,
1498c2ecf20Sopenharmony_ci					  unsigned poll_mask)
1508c2ecf20Sopenharmony_ci{
1518c2ecf20Sopenharmony_ci	memset(sqe, 0, sizeof(*sqe));
1528c2ecf20Sopenharmony_ci	sqe->opcode = IORING_OP_POLL_ADD;
1538c2ecf20Sopenharmony_ci	sqe->fd = fd;
1548c2ecf20Sopenharmony_ci#if __BYTE_ORDER == __BIG_ENDIAN
1558c2ecf20Sopenharmony_ci	poll_mask = __swahw32(poll_mask);
1568c2ecf20Sopenharmony_ci#endif
1578c2ecf20Sopenharmony_ci	sqe->poll_events = poll_mask;
1588c2ecf20Sopenharmony_ci}
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_cistatic inline void io_uring_prep_poll_remove(struct io_uring_sqe *sqe,
1618c2ecf20Sopenharmony_ci					     void *user_data)
1628c2ecf20Sopenharmony_ci{
1638c2ecf20Sopenharmony_ci	memset(sqe, 0, sizeof(*sqe));
1648c2ecf20Sopenharmony_ci	sqe->opcode = IORING_OP_POLL_REMOVE;
1658c2ecf20Sopenharmony_ci	sqe->addr = (unsigned long) user_data;
1668c2ecf20Sopenharmony_ci}
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_cistatic inline void io_uring_prep_fsync(struct io_uring_sqe *sqe, int fd,
1698c2ecf20Sopenharmony_ci				       unsigned fsync_flags)
1708c2ecf20Sopenharmony_ci{
1718c2ecf20Sopenharmony_ci	memset(sqe, 0, sizeof(*sqe));
1728c2ecf20Sopenharmony_ci	sqe->opcode = IORING_OP_FSYNC;
1738c2ecf20Sopenharmony_ci	sqe->fd = fd;
1748c2ecf20Sopenharmony_ci	sqe->fsync_flags = fsync_flags;
1758c2ecf20Sopenharmony_ci}
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_cistatic inline void io_uring_prep_nop(struct io_uring_sqe *sqe)
1788c2ecf20Sopenharmony_ci{
1798c2ecf20Sopenharmony_ci	memset(sqe, 0, sizeof(*sqe));
1808c2ecf20Sopenharmony_ci	sqe->opcode = IORING_OP_NOP;
1818c2ecf20Sopenharmony_ci}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci#ifdef __cplusplus
1848c2ecf20Sopenharmony_ci}
1858c2ecf20Sopenharmony_ci#endif
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci#endif
188