#include #include #include #include #include #include #include #include #include #include #include #include #include "liburing.h" struct io_uring_sqe* get_sqe(struct io_uring* ring) { struct io_uring_sqe* sqe = io_uring_get_sqe(ring); assert(sqe != NULL); return sqe; } void enqueue_nop(struct io_uring* ring) { struct io_uring_sqe* sqe = get_sqe(ring); io_uring_prep_nop(sqe); io_uring_sqe_set_data(sqe, (void*)1); io_uring_sqe_set_flags(sqe, IOSQE_ASYNC); } void enqueue_timeout(struct io_uring* ring) { struct io_uring_sqe* sqe = get_sqe(ring); static struct __kernel_timespec ts; ts.tv_sec = 1; ts.tv_nsec = 0; io_uring_prep_timeout(sqe, &ts, (unsigned)-1, 0); io_uring_sqe_set_data(sqe, (void*)2); } void enqueue_poll(struct io_uring* ring, int fd) { struct io_uring_sqe* sqe = get_sqe(ring); io_uring_prep_poll_add(sqe, fd, POLLIN | POLLERR | POLLHUP); io_uring_sqe_set_data(sqe, (void*)3); } int create_socket() { int s = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP); assert(s != -1); int flags = fcntl(s, F_GETFL, 0); assert(flags != -1); flags |= O_NONBLOCK; assert(fcntl(s, F_SETFL, flags) != -1); struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = 0x1236; addr.sin_addr.s_addr = 0x0100007fU; assert(bind(s, (struct sockaddr*)&addr, sizeof(addr)) != -1); assert(listen(s, 1024) != -1); return s; } int main(int argc, char *argv[]) { struct io_uring ring; int ret; ret = io_uring_queue_init(4, &ring, 0); if (ret) { fprintf(stderr, "ring setup failed\n"); return 1; } int s = create_socket(); enqueue_poll(&ring, s); enqueue_nop(&ring); enqueue_timeout(&ring); ret = io_uring_submit_and_wait(&ring, 1); if (ret == -1) { fprintf(stderr, "submit failed\n"); return 1; } struct io_uring_cqe* cqe; uint32_t head; uint32_t count = 0; io_uring_for_each_cqe(&ring, head, cqe) { if (io_uring_cqe_get_data(cqe) == (void*)2) fprintf(stderr, "Timeout triggered!\n"); count++; } io_uring_cq_advance(&ring, count); io_uring_queue_exit(&ring); return 0; }