#include #include #include #include #include #include #include int io_uring_setup(unsigned entries, io_uring_params*params) { return syscall(__NR_io_uring_setup, entries, params); } int io_uring_enter(int ring_fd, unsigned int to_submit, unsigned int min_complete, unsigned int flags, void*sig) { return (int) syscall(__NR_io_uring_enter, ring_fd, to_submit, min_complete, flags, 0); } typedef int* IntPtr; #define X(NAME) NAME = (int*)(p+params.sq_off.NAME) struct sqinfo { IntPtr head, tail, ring_mask, ring_entries, flags, dropped; int*array; void set(char*p, io_uring_params¶ms) { X(head); X(tail); X(ring_mask); X(ring_entries); X(flags); X(dropped); array = (int*)(p+params.sq_off.array); } }; #undef X #define X(NAME) NAME = (int*)(p+params.cq_off.NAME) struct cqinfo { IntPtr head, tail, ring_mask, ring_entries, overflow, flags; io_uring_cqe*cqes; void set(char*p, io_uring_params¶ms) { X(head); X(tail); X(ring_mask); X(ring_entries); X(overflow); X(flags); cqes = (io_uring_cqe*)(p+params.cq_off.cqes); } }; #undef X int main(int argc, char*argv[]) { int queue_size = 256; io_uring_params param{}; // zero init param.flags = IORING_SETUP_SQPOLL; int ringFD = io_uring_setup(queue_size, ¶m); assert(ringFD>0); assert(param.features & IORING_FEAT_SINGLE_MMAP); auto base_length = param.sq_off.array + param.sq_entries*4; char *base = (char*) mmap(0, base_length, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, ringFD, IORING_OFF_SQ_RING); assert(base != MAP_FAILED); auto sqes = (io_uring_sqe*)mmap(0, param.sq_entries * sizeof(io_uring_sqe), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE, ringFD, IORING_OFF_SQES); assert(sqes != MAP_FAILED); cqinfo cq; sqinfo sq; cq.set(base, param); sq.set(base, param); for(int i=0; i<*sq.ring_entries; i++) { memset(sqes+i, -1, sizeof(io_uring_sqe)); } for(int i=0; i<*cq.ring_entries; i++) { memset(cq.cqes+i, -1, sizeof(io_uring_cqe)); } // Take 10 items assert(*sq.tail == 0); auto p = &sqes[0]; memset(p, 0, sizeof(io_uring_sqe)*10); for(int i=0; i<10; i++) { sqes[i].opcode = IORING_OP_NOP; sqes[i].user_data = 0x1234+i; } __atomic_store_n(sq.tail, 10, __ATOMIC_RELEASE); //int res = io_uring_enter(ringFD, 10, 10, IORING_ENTER_SQ_WAIT, 0); int res = io_uring_enter(ringFD, 10, 10, IORING_ENTER_SQ_WAKEUP, 0); sleep(1); printf("cq tail is %d enter result was %d\n", __atomic_load_n(cq.tail, __ATOMIC_ACQUIRE), res); for(int i=0; i<11; i++) { printf("%X %d\n", cq.cqes[i].user_data, cq.cqes[i].res); } return 0; }