Isn't kqueue for sockets still readiness based? I know most runtimes (like libuv) just use it in the same fashion as epoll, and await readability/writeability through the queue. Not sure if it also has completion based options.
You're quite right, I muddled things up (and now the edit window has elapsed). epoll is the Linux equivalent of kqueue, IOCP, and Event Ports (all readiness based). Not sure how I screwed that one up...
IOCP is actually submission+completion based and thereby closer to io_uring than to epoll. The main difference between IOCP and io_uring at this point seems to be the use of a ringbuffer based submit interface instead of a syscall based one. But that is more of a performance optimization than a huge difference in the programming model.