|  | #include <sys/types.h> | 
|  | #include <sys/stat.h> | 
|  | #include <sys/mman.h> | 
|  | #include <unistd.h> | 
|  | #include <errno.h> | 
|  | #include <string.h> | 
|  |  | 
|  | #include "liburing.h" | 
|  | #include "barrier.h" | 
|  |  | 
|  | static int __io_uring_get_completion(struct io_uring *ring, | 
|  | struct io_uring_cqe **cqe_ptr, int wait) | 
|  | { | 
|  | struct io_uring_cq *cq = &ring->cq; | 
|  | const unsigned mask = *cq->kring_mask; | 
|  | unsigned head; | 
|  | int ret; | 
|  |  | 
|  | *cqe_ptr = NULL; | 
|  | head = *cq->khead; | 
|  | do { | 
|  | /* | 
|  | * It's necessary to use a read_barrier() before reading | 
|  | * the CQ tail, since the kernel updates it locklessly. The | 
|  | * kernel has the matching store barrier for the update. The | 
|  | * kernel also ensures that previous stores to CQEs are ordered | 
|  | * with the tail update. | 
|  | */ | 
|  | read_barrier(); | 
|  | if (head != *cq->ktail) { | 
|  | *cqe_ptr = &cq->cqes[head & mask]; | 
|  | break; | 
|  | } | 
|  | if (!wait) | 
|  | break; | 
|  | ret = io_uring_enter(ring->ring_fd, 0, 1, | 
|  | IORING_ENTER_GETEVENTS, NULL); | 
|  | if (ret < 0) | 
|  | return -errno; | 
|  | } while (1); | 
|  |  | 
|  | if (*cqe_ptr) { | 
|  | *cq->khead = head + 1; | 
|  | /* | 
|  | * Ensure that the kernel sees our new head, the kernel has | 
|  | * the matching read barrier. | 
|  | */ | 
|  | write_barrier(); | 
|  | } | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Return an IO completion, if one is readily available | 
|  | */ | 
|  | int io_uring_get_completion(struct io_uring *ring, | 
|  | struct io_uring_cqe **cqe_ptr) | 
|  | { | 
|  | return __io_uring_get_completion(ring, cqe_ptr, 0); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Return an IO completion, waiting for it if necessary | 
|  | */ | 
|  | int io_uring_wait_completion(struct io_uring *ring, | 
|  | struct io_uring_cqe **cqe_ptr) | 
|  | { | 
|  | return __io_uring_get_completion(ring, cqe_ptr, 1); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Submit sqes acquired from io_uring_get_sqe() to the kernel. | 
|  | * | 
|  | * Returns number of sqes submitted | 
|  | */ | 
|  | int io_uring_submit(struct io_uring *ring) | 
|  | { | 
|  | struct io_uring_sq *sq = &ring->sq; | 
|  | const unsigned mask = *sq->kring_mask; | 
|  | unsigned ktail, ktail_next, submitted; | 
|  | int ret; | 
|  |  | 
|  | /* | 
|  | * If we have pending IO in the kring, submit it first. We need a | 
|  | * read barrier here to match the kernels store barrier when updating | 
|  | * the SQ head. | 
|  | */ | 
|  | read_barrier(); | 
|  | if (*sq->khead != *sq->ktail) { | 
|  | submitted = *sq->kring_entries; | 
|  | goto submit; | 
|  | } | 
|  |  | 
|  | if (sq->sqe_head == sq->sqe_tail) | 
|  | return 0; | 
|  |  | 
|  | /* | 
|  | * Fill in sqes that we have queued up, adding them to the kernel ring | 
|  | */ | 
|  | submitted = 0; | 
|  | ktail = ktail_next = *sq->ktail; | 
|  | while (sq->sqe_head < sq->sqe_tail) { | 
|  | ktail_next++; | 
|  | read_barrier(); | 
|  |  | 
|  | sq->array[ktail & mask] = sq->sqe_head & mask; | 
|  | ktail = ktail_next; | 
|  |  | 
|  | sq->sqe_head++; | 
|  | submitted++; | 
|  | } | 
|  |  | 
|  | if (!submitted) | 
|  | return 0; | 
|  |  | 
|  | if (*sq->ktail != ktail) { | 
|  | /* | 
|  | * First write barrier ensures that the SQE stores are updated | 
|  | * with the tail update. This is needed so that the kernel | 
|  | * will never see a tail update without the preceeding sQE | 
|  | * stores being done. | 
|  | */ | 
|  | write_barrier(); | 
|  | *sq->ktail = ktail; | 
|  | /* | 
|  | * The kernel has the matching read barrier for reading the | 
|  | * SQ tail. | 
|  | */ | 
|  | write_barrier(); | 
|  | } | 
|  |  | 
|  | submit: | 
|  | ret = io_uring_enter(ring->ring_fd, submitted, 0, | 
|  | IORING_ENTER_GETEVENTS, NULL); | 
|  | if (ret < 0) | 
|  | return -errno; | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Return an sqe to fill. Application must later call io_uring_submit() | 
|  | * when it's ready to tell the kernel about it. The caller may call this | 
|  | * function multiple times before calling io_uring_submit(). | 
|  | * | 
|  | * Returns a vacant sqe, or NULL if we're full. | 
|  | */ | 
|  | struct io_uring_sqe *io_uring_get_sqe(struct io_uring *ring) | 
|  | { | 
|  | struct io_uring_sq *sq = &ring->sq; | 
|  | unsigned next = sq->sqe_tail + 1; | 
|  | struct io_uring_sqe *sqe; | 
|  |  | 
|  | /* | 
|  | * All sqes are used | 
|  | */ | 
|  | if (next - sq->sqe_head > *sq->kring_entries) | 
|  | return NULL; | 
|  |  | 
|  | sqe = &sq->sqes[sq->sqe_tail & *sq->kring_mask]; | 
|  | sq->sqe_tail = next; | 
|  | return sqe; | 
|  | } |