1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
|
#pragma once
#ifdef LINUX_IO_URING
#include <linux/io_uring.h>
namespace os {
/**
* This file contains a thin wrapper over the native io_uring system calls on Linux.
*/
/**
* State for io_uring-based Linux IO.
*
* Each thread is expected to have one instance of this class.
*/
class LinuxIO {
public:
// Create.
LinuxIO();
// Destroy.
~LinuxIO();
// Attach an eventfd that should be signalled when events are available.
void attachEventfd(int fd);
// Submit a job.
void submit(const struct io_uring_sqe &job);
// Attempt to dequeue a completion.
bool get(struct io_uring_cqe &out);
private:
// File descriptor for the io_uring itself.
int uringfd;
// Description of an io_uring mmap:
struct Memory {
// Base of allocation and size. If size is zero, then we won't munmap.
void *base;
size_t size;
// Create and destroy.
Memory();
~Memory();
// Map the memory.
void map(int fd, size_t offset);
};
// Description of the submission queue.
struct SubmissionQueue : Memory {
void init(struct io_sqring_offsets &offsets);
uint32_t *head;
uint32_t *tail;
uint32_t *ringMask;
uint32_t *ringEntries;
uint32_t *flags;
uint32_t *sqes;
};
// Description of the submission array.
struct SubmissionArray : Memory {
struct io_uring_sqe &operator [](size_t id) {
return reinterpret_cast<struct io_uring_sqe *>(base)[id];
}
};
// Description of the completion queue.
struct CompletionQueue : Memory {
void init(struct io_cqring_offsets &offsets);
uint32_t *head;
uint32_t *tail;
uint32_t *ringMask;
uint32_t *ringEntries;
uint32_t *flags;
struct io_uring_cqe *cqes;
};
// Map of the submission queue.
SubmissionQueue submission;
// Map of the array for the submission queue.
SubmissionArray submissionArray;
// Map of the completion queue.
CompletionQueue completion;
};
}
#endif
|