1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.channel.uring;
17
18 import io.netty.channel.DefaultFileRegion;
19 import io.netty.util.internal.ObjectUtil;
20 import io.netty.util.internal.logging.InternalLogger;
21 import io.netty.util.internal.logging.InternalLoggerFactory;
22 import io.netty.channel.unix.FileDescriptor;
23 import io.netty.channel.unix.PeerCredentials;
24 import io.netty.channel.unix.Unix;
25 import io.netty.util.internal.ClassInitializerUtil;
26 import io.netty.util.internal.NativeLibraryLoader;
27 import io.netty.util.internal.PlatformDependent;
28 import io.netty.util.internal.SystemPropertyUtil;
29 import io.netty.util.internal.ThrowableUtil;
30
31 import java.io.File;
32 import java.io.IOException;
33 import java.nio.channels.Selector;
34 import java.nio.file.Path;
35 import java.util.Arrays;
36 import java.util.Locale;
37
38 final class Native {
39 private static final InternalLogger logger = InternalLoggerFactory.getInstance(Native.class);
40 static final int DEFAULT_RING_SIZE = Math.max(64, SystemPropertyUtil.getInt("io.netty.iouring.ringSize", 4096));
41
42 static {
43 Selector selector = null;
44 try {
45
46
47
48
49 selector = Selector.open();
50 } catch (IOException ignore) {
51
52 }
53
54
55
56
57
58
59 ClassInitializerUtil.tryLoadClasses(
60 Native.class,
61
62 PeerCredentials.class, java.io.FileDescriptor.class
63 );
64
65 File tmpDir = PlatformDependent.tmpdir();
66 Path tmpFile = tmpDir.toPath().resolve("netty_io_uring.tmp");
67 try {
68
69
70 Native.createFile(tmpFile.toString());
71 } catch (UnsatisfiedLinkError ignore) {
72
73 loadNativeLibrary();
74 } finally {
75 tmpFile.toFile().delete();
76 try {
77 if (selector != null) {
78 selector.close();
79 }
80 } catch (IOException ignore) {
81
82 }
83 }
84 Unix.registerInternal(Native::registerUnix);
85 }
86
87 static final int SOCK_NONBLOCK = NativeStaticallyReferencedJniMethods.sockNonblock();
88 static final int SOCK_CLOEXEC = NativeStaticallyReferencedJniMethods.sockCloexec();
89 static final short AF_INET = (short) NativeStaticallyReferencedJniMethods.afInet();
90 static final short AF_INET6 = (short) NativeStaticallyReferencedJniMethods.afInet6();
91 static final int SIZEOF_SOCKADDR_STORAGE = NativeStaticallyReferencedJniMethods.sizeofSockaddrStorage();
92 static final int SIZEOF_SOCKADDR_IN = NativeStaticallyReferencedJniMethods.sizeofSockaddrIn();
93 static final int SIZEOF_SOCKADDR_IN6 = NativeStaticallyReferencedJniMethods.sizeofSockaddrIn6();
94 static final int SOCKADDR_IN_OFFSETOF_SIN_FAMILY =
95 NativeStaticallyReferencedJniMethods.sockaddrInOffsetofSinFamily();
96 static final int SOCKADDR_IN_OFFSETOF_SIN_PORT = NativeStaticallyReferencedJniMethods.sockaddrInOffsetofSinPort();
97 static final int SOCKADDR_IN_OFFSETOF_SIN_ADDR = NativeStaticallyReferencedJniMethods.sockaddrInOffsetofSinAddr();
98 static final int IN_ADDRESS_OFFSETOF_S_ADDR = NativeStaticallyReferencedJniMethods.inAddressOffsetofSAddr();
99 static final int SOCKADDR_IN6_OFFSETOF_SIN6_FAMILY =
100 NativeStaticallyReferencedJniMethods.sockaddrIn6OffsetofSin6Family();
101 static final int SOCKADDR_IN6_OFFSETOF_SIN6_PORT =
102 NativeStaticallyReferencedJniMethods.sockaddrIn6OffsetofSin6Port();
103 static final int SOCKADDR_IN6_OFFSETOF_SIN6_FLOWINFO =
104 NativeStaticallyReferencedJniMethods.sockaddrIn6OffsetofSin6Flowinfo();
105 static final int SOCKADDR_IN6_OFFSETOF_SIN6_ADDR =
106 NativeStaticallyReferencedJniMethods.sockaddrIn6OffsetofSin6Addr();
107 static final int SOCKADDR_IN6_OFFSETOF_SIN6_SCOPE_ID =
108 NativeStaticallyReferencedJniMethods.sockaddrIn6OffsetofSin6ScopeId();
109 static final int IN6_ADDRESS_OFFSETOF_S6_ADDR = NativeStaticallyReferencedJniMethods.in6AddressOffsetofS6Addr();
110 static final int SIZEOF_SIZE_T = NativeStaticallyReferencedJniMethods.sizeofSizeT();
111 static final int SIZEOF_IOVEC = NativeStaticallyReferencedJniMethods.sizeofIovec();
112 static final int CMSG_SPACE = NativeStaticallyReferencedJniMethods.cmsgSpace();
113 static final int CMSG_LEN = NativeStaticallyReferencedJniMethods.cmsgLen();
114 static final int CMSG_OFFSETOF_CMSG_LEN = NativeStaticallyReferencedJniMethods.cmsghdrOffsetofCmsgLen();
115 static final int CMSG_OFFSETOF_CMSG_LEVEL = NativeStaticallyReferencedJniMethods.cmsghdrOffsetofCmsgLevel();
116 static final int CMSG_OFFSETOF_CMSG_TYPE = NativeStaticallyReferencedJniMethods.cmsghdrOffsetofCmsgType();
117
118 static final int IO_URING_BUFFER_RING_TAIL = NativeStaticallyReferencedJniMethods.ioUringBufferRingOffsetTail();
119
120 static final int IOVEC_OFFSETOF_IOV_BASE = NativeStaticallyReferencedJniMethods.iovecOffsetofIovBase();
121 static final int IOVEC_OFFSETOF_IOV_LEN = NativeStaticallyReferencedJniMethods.iovecOffsetofIovLen();
122 static final int SIZEOF_MSGHDR = NativeStaticallyReferencedJniMethods.sizeofMsghdr();
123 static final int MSGHDR_OFFSETOF_MSG_NAME = NativeStaticallyReferencedJniMethods.msghdrOffsetofMsgName();
124 static final int MSGHDR_OFFSETOF_MSG_NAMELEN = NativeStaticallyReferencedJniMethods.msghdrOffsetofMsgNamelen();
125 static final int MSGHDR_OFFSETOF_MSG_IOV = NativeStaticallyReferencedJniMethods.msghdrOffsetofMsgIov();
126 static final int MSGHDR_OFFSETOF_MSG_IOVLEN = NativeStaticallyReferencedJniMethods.msghdrOffsetofMsgIovlen();
127 static final int MSGHDR_OFFSETOF_MSG_CONTROL = NativeStaticallyReferencedJniMethods.msghdrOffsetofMsgControl();
128 static final int MSGHDR_OFFSETOF_MSG_CONTROLLEN =
129 NativeStaticallyReferencedJniMethods.msghdrOffsetofMsgControllen();
130 static final int MSGHDR_OFFSETOF_MSG_FLAGS = NativeStaticallyReferencedJniMethods.msghdrOffsetofMsgFlags();
131 static final int POLLIN = NativeStaticallyReferencedJniMethods.pollin();
132 static final int POLLOUT = NativeStaticallyReferencedJniMethods.pollout();
133 static final int POLLRDHUP = NativeStaticallyReferencedJniMethods.pollrdhup();
134 static final int ERRNO_ECANCELED_NEGATIVE = -NativeStaticallyReferencedJniMethods.ecanceled();
135 static final int ERRNO_ETIME_NEGATIVE = -NativeStaticallyReferencedJniMethods.etime();
136 static final int ERRNO_NOBUFS_NEGATIVE = -NativeStaticallyReferencedJniMethods.enobufs();
137
138 static final int PAGE_SIZE = NativeStaticallyReferencedJniMethods.pageSize();
139
140 static final int SIZEOF_IOURING_BUF = NativeStaticallyReferencedJniMethods.sizeofIoUringBuf();
141 static final int IOURING_BUFFER_OFFSETOF_ADDR = NativeStaticallyReferencedJniMethods.ioUringBufferOffsetAddr();
142 static final int IOURING_BUFFER_OFFSETOF_LEN = NativeStaticallyReferencedJniMethods.ioUringBufferOffsetLen();
143 static final int IOURING_BUFFER_OFFSETOF_BID = NativeStaticallyReferencedJniMethods.ioUringBufferOffsetBid();
144
145
146
147
148 static final byte IORING_OP_NOP = 0;
149 static final byte IORING_OP_READV = 1;
150 static final byte IORING_OP_WRITEV = 2;
151 static final byte IORING_OP_FSYNC = 3;
152 static final byte IORING_OP_READ_FIXED = 4;
153 static final byte IORING_OP_WRITE_FIXED = 5;
154 static final byte IORING_OP_POLL_ADD = 6;
155 static final byte IORING_OP_POLL_REMOVE = 7;
156 static final byte IORING_OP_SYNC_FILE_RANGE = 8;
157 static final byte IORING_OP_SENDMSG = 9;
158 static final byte IORING_OP_RECVMSG = 10;
159 static final byte IORING_OP_TIMEOUT = 11;
160 static final byte IORING_OP_TIMEOUT_REMOVE = 12;
161 static final byte IORING_OP_ACCEPT = 13;
162 static final byte IORING_OP_ASYNC_CANCEL = 14;
163 static final byte IORING_OP_LINK_TIMEOUT = 15;
164 static final byte IORING_OP_CONNECT = 16;
165 static final byte IORING_OP_FALLOCATE = 17;
166 static final byte IORING_OP_OPENAT = 18;
167 static final byte IORING_OP_CLOSE = 19;
168 static final byte IORING_OP_FILES_UPDATE = 20;
169 static final byte IORING_OP_STATX = 21;
170 static final byte IORING_OP_READ = 22;
171 static final byte IORING_OP_WRITE = 23;
172 static final byte IORING_OP_FADVISE = 24;
173 static final byte IORING_OP_MADVISE = 25;
174 static final byte IORING_OP_SEND = 26;
175 static final byte IORING_OP_RECV = 27;
176 static final byte IORING_OP_OPENAT2 = 28;
177 static final byte IORING_OP_EPOLL_CTL = 29;
178 static final byte IORING_OP_SPLICE = 30;
179 static final byte IORING_OP_PROVIDE_BUFFERS = 31;
180 static final byte IORING_OP_REMOVE_BUFFERS = 32;
181 static final byte IORING_OP_TEE = 33;
182 static final byte IORING_OP_SHUTDOWN = 34;
183 static final byte IORING_OP_RENAMEAT = 35;
184 static final byte IORING_OP_UNLINKAT = 36;
185 static final byte IORING_OP_MKDIRAT = 37;
186 static final byte IORING_OP_SYMLINKAT = 38;
187 static final byte IORING_OP_LINKAT = 39;
188 static final byte IORING_OP_MSG_RING = 40;
189 static final byte IORING_OP_FSETXATTR = 41;
190 static final byte IORING_OP_SETXATTR = 42;
191 static final byte IORING_OP_FGETXATTR = 43;
192 static final byte IORING_OP_GETXATTR = 44;
193 static final byte IORING_OP_SOCKET = 45;
194 static final byte IORING_OP_URING_CMD = 46;
195 static final byte IORING_OP_SEND_ZC = 47;
196 static final byte IORING_OP_SENDMSG_ZC = 48;
197 static final byte IORING_OP_READ_MULTISHOT = 49;
198 static final byte IORING_OP_WAITID = 50;
199 static final byte IORING_OP_FUTEX_WAIT = 51;
200 static final byte IORING_OP_FUTEX_WAKE = 52;
201 static final byte IORING_OP_FUTEX_WAITV = 53;
202 static final byte IORING_OP_FIXED_FD_INSTALL = 54;
203 static final byte IORING_OP_FTRUNCATE = 55;
204 static final byte IORING_OP_BIND = 56;
205 static final byte IORING_CQE_F_BUFFER = 1 << 0;
206 static final byte IORING_CQE_F_MORE = 1 << 1;
207 static final byte IORING_CQE_F_SOCK_NONEMPTY = 1 << 2;
208 static final byte IORING_CQE_F_BUF_MORE = 1 << 4;
209
210 static final int IORING_SETUP_CQSIZE = 1 << 3;
211 static final int IORING_SETUP_CLAMP = 1 << 4;
212
213 static final int IORING_SETUP_R_DISABLED = 1 << 6;
214 static final int IORING_SETUP_SUBMIT_ALL = 1 << 7;
215 static final int IORING_SETUP_SINGLE_ISSUER = 1 << 12;
216 static final int IORING_SETUP_DEFER_TASKRUN = 1 << 13;
217 static final int IORING_CQE_BUFFER_SHIFT = 16;
218
219 static final short IORING_POLL_ADD_MULTI = 1 << 0;
220
221 static final short IORING_RECVSEND_POLL_FIRST = 1 << 0;
222 static final short IORING_RECVSEND_BUNDLE = 1 << 4;
223 static final short IORING_RECV_MULTISHOT = 1 << 1;
224
225 static final short IORING_ACCEPT_MULTISHOT = 1 << 0;
226 static final short IORING_ACCEPT_DONTWAIT = 1 << 1;
227 static final short IORING_ACCEPT_POLL_FIRST = 1 << 2;
228
229 static final int IORING_FEAT_RECVSEND_BUNDLE = 1 << 14;
230 static final int SPLICE_F_MOVE = 1;
231
232 static final int IOU_PBUF_RING_INC = 2;
233 static String opToStr(byte op) {
234 switch (op) {
235 case IORING_OP_NOP: return "NOP";
236 case IORING_OP_READV: return "READV";
237 case IORING_OP_WRITEV: return "WRITEV";
238 case IORING_OP_FSYNC: return "FSYNC";
239 case IORING_OP_READ_FIXED: return "READ_FIXED";
240 case IORING_OP_WRITE_FIXED: return "WRITE_FIXED";
241 case IORING_OP_POLL_ADD: return "POLL_ADD";
242 case IORING_OP_POLL_REMOVE: return "POLL_REMOVE";
243 case IORING_OP_SYNC_FILE_RANGE: return "SYNC_FILE_RANGE";
244 case IORING_OP_SENDMSG: return "SENDMSG";
245 case IORING_OP_RECVMSG: return "RECVMSG";
246 case IORING_OP_TIMEOUT: return "TIMEOUT";
247 case IORING_OP_TIMEOUT_REMOVE: return "TIMEOUT_REMOVE";
248 case IORING_OP_ACCEPT: return "ACCEPT";
249 case IORING_OP_ASYNC_CANCEL: return "ASYNC_CANCEL";
250 case IORING_OP_LINK_TIMEOUT: return "LINK_TIMEOUT";
251 case IORING_OP_CONNECT: return "CONNECT";
252 case IORING_OP_FALLOCATE: return "FALLOCATE";
253 case IORING_OP_OPENAT: return "OPENAT";
254 case IORING_OP_CLOSE: return "CLOSE";
255 case IORING_OP_FILES_UPDATE: return "FILES_UPDATE";
256 case IORING_OP_STATX: return "STATX";
257 case IORING_OP_READ: return "READ";
258 case IORING_OP_WRITE: return "WRITE";
259 case IORING_OP_FADVISE: return "FADVISE";
260 case IORING_OP_MADVISE: return "MADVISE";
261 case IORING_OP_SEND: return "SEND";
262 case IORING_OP_RECV: return "RECV";
263 case IORING_OP_OPENAT2: return "OPENAT2";
264 case IORING_OP_EPOLL_CTL: return "EPOLL_CTL";
265 case IORING_OP_SPLICE: return "SPLICE";
266 case IORING_OP_PROVIDE_BUFFERS: return "PROVIDE_BUFFERS";
267 case IORING_OP_REMOVE_BUFFERS: return "REMOVE_BUFFERS";
268 case IORING_OP_TEE: return "TEE";
269 case IORING_OP_SHUTDOWN: return "SHUTDOWN";
270 case IORING_OP_RENAMEAT: return "RENAMEAT";
271 case IORING_OP_UNLINKAT: return "UNLINKAT";
272 case IORING_OP_MKDIRAT: return "MKDIRAT";
273 case IORING_OP_SYMLINKAT: return "SYMLINKAT";
274 case IORING_OP_LINKAT: return "LINKAT";
275 default: return "[OP CODE " + op + ']';
276 }
277 }
278
279 static final int IORING_ENTER_GETEVENTS = NativeStaticallyReferencedJniMethods.ioringEnterGetevents();
280 static final int IORING_ENTER_REGISTERED_RING = 1 << 4;
281 static final int IOSQE_ASYNC = NativeStaticallyReferencedJniMethods.iosqeAsync();
282 static final int IOSQE_LINK = NativeStaticallyReferencedJniMethods.iosqeLink();
283 static final int IOSQE_IO_DRAIN = NativeStaticallyReferencedJniMethods.iosqeDrain();
284 static final int IOSQE_BUFFER_SELECT = NativeStaticallyReferencedJniMethods.iosqeBufferSelect();
285 static final int MSG_DONTWAIT = NativeStaticallyReferencedJniMethods.msgDontwait();
286 static final int MSG_FASTOPEN = NativeStaticallyReferencedJniMethods.msgFastopen();
287 static final int SOL_UDP = NativeStaticallyReferencedJniMethods.solUdp();
288 static final int UDP_SEGMENT = NativeStaticallyReferencedJniMethods.udpSegment();
289 private static final int TFO_ENABLED_CLIENT_MASK = 0x1;
290 private static final int TFO_ENABLED_SERVER_MASK = 0x2;
291 private static final int TCP_FASTOPEN_MODE = NativeStaticallyReferencedJniMethods.tcpFastopenMode();
292
293
294
295
296 static final boolean IS_SUPPORTING_TCP_FASTOPEN_CLIENT =
297 (TCP_FASTOPEN_MODE & TFO_ENABLED_CLIENT_MASK) == TFO_ENABLED_CLIENT_MASK;
298
299
300
301
302 static final boolean IS_SUPPORTING_TCP_FASTOPEN_SERVER =
303 (TCP_FASTOPEN_MODE & TFO_ENABLED_SERVER_MASK) == TFO_ENABLED_SERVER_MASK;
304
305 private static final int[] REQUIRED_IORING_OPS = {
306 IORING_OP_POLL_ADD,
307 IORING_OP_TIMEOUT,
308 IORING_OP_ACCEPT,
309 IORING_OP_READ,
310 IORING_OP_WRITE,
311 IORING_OP_POLL_REMOVE,
312 IORING_OP_CONNECT,
313 IORING_OP_CLOSE,
314 IORING_OP_WRITEV,
315 IORING_OP_SENDMSG,
316 IORING_OP_RECVMSG,
317 IORING_OP_ASYNC_CANCEL,
318 IORING_OP_RECV,
319 IORING_OP_NOP,
320 IORING_OP_SHUTDOWN,
321 IORING_OP_SEND
322 };
323
324 static int setupFlags() {
325 int flags = Native.IORING_SETUP_R_DISABLED | Native.IORING_SETUP_CLAMP;
326 if (IoUring.isSetupSubmitAllSupported()) {
327 flags |= Native.IORING_SETUP_SUBMIT_ALL;
328 }
329
330
331 if (IoUring.isSetupSingleIssuerSupported()) {
332 flags |= Native.IORING_SETUP_SINGLE_ISSUER;
333 }
334 if (IoUring.isSetupDeferTaskrunSupported()) {
335 flags |= Native.IORING_SETUP_DEFER_TASKRUN;
336 }
337 return flags;
338 }
339
340 static RingBuffer createRingBuffer(int ringSize, int setupFlags) {
341 return createRingBuffer(ringSize, ringSize * 2, setupFlags);
342 }
343
344 static RingBuffer createRingBuffer(int ringSize, int cqeSize, int setupFlags) {
345 ObjectUtil.checkPositive(ringSize, "ringSize");
346 ObjectUtil.checkPositive(cqeSize, "cqeSize");
347 long[] values = ioUringSetup(ringSize, cqeSize, setupFlags);
348 assert values.length == 22;
349 CompletionQueue completionQueue = new CompletionQueue(
350 values[0],
351 values[1],
352 values[2],
353 values[3],
354 values[4],
355 values[5],
356 (int) values[6],
357 values[7],
358 (int) values[8],
359 (int) values[9]);
360 SubmissionQueue submissionQueue = new SubmissionQueue(
361 values[10],
362 values[11],
363 values[12],
364 values[13],
365 values[14],
366 values[15],
367 values[16],
368 values[17],
369 (int) values[18],
370 values[19],
371 (int) values[20]);
372 return new RingBuffer(submissionQueue, completionQueue, (int) values[21]);
373 }
374
375 static void checkAllIOSupported(int ringFd) {
376 if (!ioUringProbe(ringFd, REQUIRED_IORING_OPS)) {
377 throw new UnsupportedOperationException("Not all operations are supported: "
378 + Arrays.toString(REQUIRED_IORING_OPS));
379 }
380 }
381
382 static boolean isRecvMultishotSupported() {
383
384 return Native.ioUringSetupSupportsFlags(Native.IORING_SETUP_SINGLE_ISSUER);
385 }
386
387 static boolean isAcceptMultishotSupported(int ringFd) {
388
389 return ioUringProbe(ringFd, new int[] { Native.IORING_OP_SOCKET });
390 }
391
392 static boolean isCqeFSockNonEmptySupported(int ringFd) {
393
394 return ioUringProbe(ringFd, new int[] { Native.IORING_OP_SOCKET });
395 }
396
397 static boolean isSpliceSupported(int ringFd) {
398
399 return ioUringProbe(ringFd, new int[] { Native.IORING_OP_SPLICE });
400 }
401
402 static boolean isPollAddMultiShotSupported(int ringfd) {
403
404 return isCqeFSockNonEmptySupported(ringfd);
405 }
406
407
408
409
410
411
412 static boolean isRegisterIoWqWorkerSupported(int ringFd) {
413
414 int result = ioUringRegisterIoWqMaxWorkers(ringFd, 0, 0);
415 if (result >= 0) {
416 return true;
417 }
418
419 return false;
420 }
421
422 static boolean isRegisterBufferRingSupported(int ringFd, int flags) {
423 int entries = 2;
424 short bgid = 1;
425 long result = ioUringRegisterBuffRing(ringFd, entries, bgid, flags);
426 if (result >= 0) {
427 ioUringUnRegisterBufRing(ringFd, result, entries, bgid);
428 return true;
429 }
430
431 return false;
432 }
433
434 static void checkKernelVersion(String kernelVersion) {
435 boolean enforceKernelVersion = SystemPropertyUtil.getBoolean(
436 "io.netty.transport.iouring.enforceKernelVersion", true);
437 boolean kernelSupported = checkKernelVersion(kernelVersion, 5, 9);
438 if (!kernelSupported) {
439 if (enforceKernelVersion) {
440 throw new UnsupportedOperationException(
441 "you need at least kernel version 5.9, current kernel version: " + kernelVersion);
442 } else {
443 logger.debug("Detected kernel " + kernelVersion + " does not match minimum version of 5.9, " +
444 "trying to use io_uring anyway");
445 }
446 }
447 }
448
449 private static boolean checkKernelVersion(String kernelVersion, int major, int minor) {
450 String[] versionComponents = kernelVersion.split("\\.");
451 if (versionComponents.length < 3) {
452 return false;
453 }
454 int nativeMajor;
455 try {
456 nativeMajor = Integer.parseInt(versionComponents[0]);
457 } catch (NumberFormatException e) {
458 return false;
459 }
460
461 if (nativeMajor < major) {
462 return false;
463 }
464
465 if (nativeMajor > major) {
466 return true;
467 }
468
469 int nativeMinor;
470 try {
471 nativeMinor = Integer.parseInt(versionComponents[1]);
472 } catch (NumberFormatException e) {
473 return false;
474 }
475
476 return nativeMinor >= minor;
477 }
478
479 static native boolean ioUringSetupSupportsFlags(int setupFlags);
480 private static native boolean ioUringProbe(int ringFd, int[] ios);
481 private static native long[] ioUringSetup(int entries, int cqeSize, int setupFlags);
482
483 static native int ioUringRegisterIoWqMaxWorkers(int ringFd, int maxBoundedValue, int maxUnboundedValue);
484 static native int ioUringRegisterEnableRings(int ringFd);
485 static native int ioUringRegisterRingFds(int ringFds);
486
487 static native long ioUringRegisterBuffRing(int ringFd, int entries, short bufferGroup, int flags);
488 static native int ioUringUnRegisterBufRing(int ringFd, long ioUringBufRingAddr, int entries, int bufferGroupId);
489
490 static native int ioUringEnter(int ringFd, int toSubmit, int minComplete, int flags);
491
492 static native void eventFdWrite(int fd, long value);
493
494 static int getFd(DefaultFileRegion fileChannel) {
495 return getFd0(fileChannel);
496 }
497
498 private static native int getFd0(Object fileChannel);
499
500 static FileDescriptor newBlockingEventFd() {
501 return new FileDescriptor(blockingEventFd());
502 }
503
504 static native void ioUringExit(long submissionQueueArrayAddress, int submissionQueueRingEntries,
505 long submissionQueueRingAddress, int submissionQueueRingSize,
506 long completionQueueRingAddress, int completionQueueRingSize,
507 int ringFd, int enterRingFd);
508
509 private static native int blockingEventFd();
510
511
512 static native int createFile(String name);
513
514 private static native int registerUnix();
515
516 static native long cmsghdrData(long hdrAddr);
517
518 static native String kernelVersion();
519
520 private Native() {
521
522 }
523
524
525 private static void loadNativeLibrary() {
526 String name = PlatformDependent.normalizedOs().toLowerCase(Locale.ROOT).trim();
527 if (!name.startsWith("linux")) {
528 throw new IllegalStateException("Only supported on Linux");
529 }
530 String staticLibName = "netty_transport_native_io_uring";
531 String sharedLibName = staticLibName + '_' + PlatformDependent.normalizedArch();
532 ClassLoader cl = PlatformDependent.getClassLoader(Native.class);
533 try {
534 NativeLibraryLoader.load(sharedLibName, cl);
535 } catch (UnsatisfiedLinkError e1) {
536 try {
537 NativeLibraryLoader.load(staticLibName, cl);
538 logger.info("Failed to load io_uring");
539 } catch (UnsatisfiedLinkError e2) {
540 ThrowableUtil.addSuppressed(e1, e2);
541 throw e1;
542 }
543 }
544 }
545 }