Skip to content

Instantly share code, notes, and snippets.

@victorstewart
Last active February 4, 2023 04:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save victorstewart/98814b65ed702c33480487c05b40eb56 to your computer and use it in GitHub Desktop.
Save victorstewart/98814b65ed702c33480487c05b40eb56 to your computer and use it in GitHub Desktop.
fastpoll accept test
#ifndef IORING_OP_SHUTDOWN
#define IORING_OP_SHUTDOWN IORING_OP_TEE + 1
#endif
#include <errno.h>
#include <linux/io_uring.h>
#include <liburing/src/include/liburing.h>
#include <sys/un.h>
#include <sys/socket.h>
#include <unistd.h> // unlink
#include <string>
// clang++ -fuse-ld=lld --std=gnu++2a -I/folder/with/liburing /path/to/liburing.a -o accept.test accept.test.cpp -g
class UnixSocket {
public:
int fd;
struct sockaddr_un address = {};
socklen_t addressLen;
UnixSocket(const char *socketpath)
{
fd = socket(AF_UNIX, SOCK_STREAM, 0);
addressLen = sizeof(struct sockaddr_un);
address.sun_family = AF_UNIX;
memcpy(address.sun_path, socketpath, strlen(socketpath));
unlink(address.sun_path);
bind(fd, (struct sockaddr *)&address, addressLen);
listen(fd, SOMAXCONN);
}
~UnixSocket()
{
close(fd);
}
};
class AcceptServer {
public:
struct io_uring ring;
int *socketfds = new int[10];
void setup(int fd, bool useSQPOLL)
{
int cpu_pin = sched_getcpu();
cpu_set_t affinity;
CPU_SET(cpu_pin, &affinity);
sched_setaffinity(0, sizeof(affinity), &affinity);
struct io_uring_params params = {};
if (useSQPOLL)
{
params.flags = IORING_SETUP_SQPOLL | IORING_SETUP_SQ_AFF;
params.sq_thread_idle = 2000; // ms
params.sq_thread_cpu = cpu_pin;
}
io_uring_queue_init_params(1024, &ring, &params);
memset(socketfds, 0xff, sizeof(int) * 10); // make sparse with -1
socketfds[fd] = fd;
io_uring_register_files(&ring, socketfds, 10);
}
void queueAccept(UnixSocket *socket, bool useFixedFileFlag)
{
struct io_uring_sqe *sqe = io_uring_get_sqe(&ring);
io_uring_prep_accept(sqe, socket->fd, (struct sockaddr *)&(socket->address), &(socket->addressLen), 0);
if (useFixedFileFlag) io_uring_sqe_set_flags(sqe, IOSQE_FIXED_FILE);
}
int run(bool useSQPOLL, bool useFixedFileFlag)
{
UnixSocket *socket = new UnixSocket("hot.socket");
setup(socket->fd, useSQPOLL);
int acceptResult = 0;
queueAccept(socket, useFixedFileFlag);
struct io_uring_cqe *cqe = NULL;
struct __kernel_timespec timeout = {.tv_sec = 2, .tv_nsec = 0};
// if accept works... this should timeout
if (io_uring_wait_cqe_timeout(&ring, &cqe, &timeout) != -ETIME)
{
// failed
acceptResult = cqe->res;
}
io_uring_queue_exit(&ring);
delete socket;
return acceptResult;
}
};
int main (int argc, char *argv[])
{
AcceptServer *server = new AcceptServer();
auto printResult = [&] (const char *testname, int result) -> void {
if (result == 0) printf("%s -> SUCCESS: timeout as expected\n", testname);
else printf("%s -> FAILURE: failed with error = %d\n", testname, result);
};
printResult("with SQPOLL with FIXED FLAG", server->run(true, true));
// only relevant >=5.11
//printResult("with SQPOLL without FIXED FLAG", server->run(true, false));
printResult("without SQPOLL with FIXED FLAG", server->run(false, true));
printResult("without SQPOLL without FIXED FLAG", server->run(false, false));
delete server;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment