cwist
Modern C web framework with libttak runtime
Loading...
Searching...
No Matches
uring_sqpoll.c
Go to the documentation of this file.
1#if defined(__linux__)
2#ifndef _GNU_SOURCE
3#define _GNU_SOURCE
4#endif
6#include <sys/syscall.h>
7#include <sys/mman.h>
8#include <unistd.h>
9#include <string.h>
10#include <errno.h>
11
19static inline int sqpoll_io_uring_setup(unsigned entries, struct io_uring_params *p) {
20 return (int)syscall(__NR_io_uring_setup, entries, p);
21}
22
36int cwist_io_uring_init_sqpoll(cwist_sqpoll_ring_t *r, unsigned entries,
37 unsigned sq_thread_idle_ms) {
38 if (!r || entries == 0) return -1;
39 memset(r, 0, sizeof(*r));
40
41 struct io_uring_params p;
42 memset(&p, 0, sizeof(p));
43 p.flags = IORING_SETUP_SQPOLL;
44 p.sq_thread_idle = sq_thread_idle_ms ? sq_thread_idle_ms : 2000;
45
46 int fd = sqpoll_io_uring_setup(entries, &p);
47 if (fd < 0) {
48 return -1;
49 }
50
51 r->ring_fd = fd;
52 r->entries = p.sq_entries;
53
54 size_t sq_sz = p.sq_off.array + p.sq_entries * sizeof(uint32_t);
57 if (sq_ptr == MAP_FAILED) {
58 close(fd);
59 return -1;
60 }
61 r->sq_ring_sz = sq_sz;
62
63 r->sq_head = (_Atomic uint32_t *)((uint8_t *)sq_ptr + p.sq_off.head);
64 r->sq_tail = (_Atomic uint32_t *)((uint8_t *)sq_ptr + p.sq_off.tail);
65 r->sq_ring_mask = (uint32_t *)((uint8_t *)sq_ptr + p.sq_off.ring_mask);
66 r->sq_array = (uint32_t *)((uint8_t *)sq_ptr + p.sq_off.array);
67
68 size_t sqes_sz = p.sq_entries * sizeof(struct io_uring_sqe);
69 void *sqes_ptr =
71 if (sqes_ptr == MAP_FAILED) {
73 close(fd);
74 return -1;
75 }
76 r->sqes_sz = sqes_sz;
77 r->sqes = (struct io_uring_sqe *)sqes_ptr;
78 r->active = true;
79
80 return 0;
81}
82
97bool cwist_io_uring_sqpoll_send(cwist_sqpoll_ring_t *r, int fd, const void *buf, size_t len,
98 uint64_t user_data) {
99 if (!r || !r->active) return false;
100
103
104 if (tail - head >= r->entries) {
105 return false;
106 }
107
108 uint32_t idx = tail & (*r->sq_ring_mask);
109 struct io_uring_sqe *sqe = &r->sqes[idx];
110
111 memset(sqe, 0, sizeof(*sqe));
112 sqe->opcode = IORING_OP_SEND;
113 sqe->fd = fd;
114 sqe->addr = (uint64_t)(uintptr_t)buf;
115 sqe->len = (uint32_t)len;
116 sqe->flags = 0;
117 sqe->user_data = user_data;
118
119 r->sq_array[idx] = idx;
120 atomic_store_explicit(r->sq_tail, tail + 1, memory_order_release);
121 return true;
122}
123
134 if (!r || !r->active) return;
135 if (r->sqes && r->sqes_sz) {
136 munmap(r->sqes, r->sqes_sz);
137 }
138 if (r->sq_head && r->sq_ring_sz) {
139 munmap((void *)r->sq_head, r->sq_ring_sz);
140 }
141 if (r->ring_fd >= 0) {
142 close(r->ring_fd);
143 }
144 memset(r, 0, sizeof(*r));
145}
146#endif
size_t head
Definition otel.c:57
size_t cap
Definition otel.c:56
Zero-syscall I/O engine powered by Linux io_uring SQPOLL.