blob: 0dec40035080239f355361fa457548e73c0eb994 [file] [log] [blame]
William A. Kennington III5c20da22021-06-18 16:44:55 -07001#include <liburing.h>
Jerry Zhu8efeaa32021-08-10 14:54:00 +00002
William A. Kennington III5c20da22021-06-18 16:44:55 -07003#include <sys/eventfd.h>
4
5#include <stdplus/fd/managed.hpp>
6#include <stdplus/fd/ops.hpp>
7#include <stdplus/io_uring.hpp>
8#include <stdplus/util/cexec.hpp>
9
10#include <algorithm>
11
12namespace stdplus
13{
14
William A. Kennington III43e38182021-08-19 17:29:48 -070015__kernel_timespec chronoToKTS(std::chrono::nanoseconds t) noexcept
16{
17 __kernel_timespec ts;
18 ts.tv_sec = std::chrono::floor<std::chrono::seconds>(t).count();
19 ts.tv_nsec = (t % std::chrono::seconds(1)).count();
20 return ts;
21}
22
William A. Kennington III80562592021-08-19 18:42:04 -070023IoUring::IoUring(size_t queue_size, int flags)
William A. Kennington III5c20da22021-06-18 16:44:55 -070024{
William A. Kennington III80562592021-08-19 18:42:04 -070025 CHECK_RET(io_uring_queue_init(queue_size, &ring, flags),
26 "io_uring_queue_init");
William A. Kennington III5c20da22021-06-18 16:44:55 -070027}
28
Jerry Zhu8efeaa32021-08-10 14:54:00 +000029IoUring::IoUring(size_t queue_size, io_uring_params& params)
30{
31 CHECK_RET(io_uring_queue_init_params(queue_size, &ring, &params),
32 "io_uring_queue_init_params");
33}
34
William A. Kennington III5c20da22021-06-18 16:44:55 -070035IoUring::~IoUring()
36{
37 io_uring_queue_exit(&ring);
38 io_uring_cqe cqe{};
39 cqe.res = -ECANCELED;
40 for (auto h : handlers)
41 {
42 h->handleCQE(cqe);
43 }
44}
45
William A. Kennington IIIabc6be72021-08-17 01:58:27 -070046IoUring::FileHandle::FileHandle(unsigned slot, IoUring& ring) :
47 slot(slot, &ring)
48{
49}
50
51void IoUring::FileHandle::drop(unsigned&& slot, IoUring*& ring)
52{
53 ring->updateFile(slot, -1);
54}
55
William A. Kennington III1afd7732021-08-20 00:49:10 -070056void IoUring::reserveFiles(size_t num)
57{
58 auto new_size = std::max<size_t>(7, num + filesAllocated);
59 if (files.size() < new_size)
60 {
61 io_uring_unregister_files(&ring);
62 files.resize(new_size, -1);
63 CHECK_RET(io_uring_register_files(&ring, files.data(), files.size()),
64 "io_uring_register_files");
65 }
66}
67
William A. Kennington IIIabc6be72021-08-17 01:58:27 -070068[[nodiscard]] IoUring::FileHandle IoUring::registerFile(int fd)
69{
70 unsigned slot = 0;
71 for (; slot < files.size(); slot++)
72 {
73 if (files[slot] == -1)
74 {
75 updateFile(slot, fd);
76 return FileHandle(slot, *this);
77 }
78 }
79
80 io_uring_unregister_files(&ring);
William A. Kennington III7fc86da2021-08-19 17:47:40 -070081 files.resize(std::max<size_t>(7, files.size() * 2 + 1), -1);
William A. Kennington III1afd7732021-08-20 00:49:10 -070082 setFile(slot, fd);
William A. Kennington IIIabc6be72021-08-17 01:58:27 -070083 CHECK_RET(io_uring_register_files(&ring, files.data(), files.size()),
84 "io_uring_register_files");
85 return FileHandle(slot, *this);
86}
87
William A. Kennington III5c20da22021-06-18 16:44:55 -070088io_uring_sqe& IoUring::getSQE()
89{
90 return *CHECK_ERRNO(io_uring_get_sqe(&ring), "io_uring_get_sqe");
91}
92
93void IoUring::setHandler(io_uring_sqe& sqe, CQEHandler* h) noexcept
94{
95 auto oldh = reinterpret_cast<CQEHandler*>(sqe.user_data);
96 if (oldh == h)
97 {
98 return;
99 }
100 io_uring_cqe cqe{};
101 cqe.res = -ECANCELED;
102 dropHandler(oldh, cqe);
103 if (h != nullptr)
104 {
105 handlers.push_back(h);
106 }
107 io_uring_sqe_set_data(&sqe, h);
108}
109
110void IoUring::cancelHandler(CQEHandler& h)
111{
112 io_uring_prep_cancel(&getSQE(), &h, 0);
113 submit();
114}
115
116void IoUring::submit()
117{
118 CHECK_RET(io_uring_submit(&ring), "io_uring_submit");
119}
120
121void IoUring::process() noexcept
122{
123 io_uring_cqe* cqe;
124 while (io_uring_peek_cqe(&ring, &cqe) == 0)
125 {
126 auto h = reinterpret_cast<CQEHandler*>(cqe->user_data);
127 dropHandler(h, *cqe);
128 io_uring_cqe_seen(&ring, cqe);
129 }
130}
131
William A. Kennington III43e38182021-08-19 17:29:48 -0700132void IoUring::wait()
133{
134 io_uring_cqe* cqe;
135 CHECK_RET(io_uring_wait_cqe(&ring, &cqe), "io_uring_wait_cqe");
136}
137
138void IoUring::wait(std::chrono::nanoseconds timeout)
139{
140 io_uring_cqe* cqe;
141 auto kts = chronoToKTS(timeout);
142 CHECK_RET(io_uring_wait_cqe_timeout(&ring, &cqe, &kts),
143 "io_uring_wait_cqe_timeout");
144}
145
William A. Kennington IIIa4f71f92022-08-18 14:17:00 -0700146ManagedFd& IoUring::getEventFd()
William A. Kennington III5c20da22021-06-18 16:44:55 -0700147{
148 if (event_fd)
149 {
150 return *event_fd;
151 }
William A. Kennington IIIa4f71f92022-08-18 14:17:00 -0700152 ManagedFd efd(CHECK_RET(eventfd(0, EFD_NONBLOCK), "eventfd"));
William A. Kennington III5c20da22021-06-18 16:44:55 -0700153 CHECK_RET(io_uring_register_eventfd(&ring, efd.get()),
154 "io_uring_register_eventfd");
155 return *(event_fd = std::move(efd));
156}
157
158void IoUring::processEvents()
159{
160 auto& efd = getEventFd();
161 std::byte b[8];
William A. Kennington IIIa4f71f92022-08-18 14:17:00 -0700162 while (!fd::read(efd, b).empty())
William A. Kennington III5c20da22021-06-18 16:44:55 -0700163 {
164 process();
165 }
166}
167
168void IoUring::dropHandler(CQEHandler* h, io_uring_cqe& cqe) noexcept
169{
170 if (h == nullptr)
171 {
172 return;
173 }
174 auto it = std::find(handlers.begin(), handlers.end(), h);
175 if (it != handlers.end() - 1)
176 {
177 std::swap(*it, handlers.back());
178 }
179 handlers.pop_back();
180 h->handleCQE(cqe);
181}
182
William A. Kennington III1afd7732021-08-20 00:49:10 -0700183void IoUring::setFile(unsigned slot, int fd) noexcept
184{
185 if (files[slot] == -1 && files[slot] != fd)
186 {
187 filesAllocated++;
188 }
189 else if (fd == -1 && files[slot] != fd)
190 {
191 filesAllocated--;
192 }
193 files[slot] = fd;
194}
195
William A. Kennington IIIabc6be72021-08-17 01:58:27 -0700196void IoUring::updateFile(unsigned slot, int fd)
197{
William A. Kennington III1afd7732021-08-20 00:49:10 -0700198 setFile(slot, fd);
William A. Kennington IIIabc6be72021-08-17 01:58:27 -0700199 CHECK_RET(io_uring_register_files_update(&ring, slot, &files[slot], 1),
200 "io_uring_register_files_update");
201}
202
William A. Kennington III5c20da22021-06-18 16:44:55 -0700203} // namespace stdplus