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.ChannelOption;
19 import io.netty.util.internal.PlatformDependent;
20 import io.netty.util.internal.SystemPropertyUtil;
21 import io.netty.util.internal.logging.InternalLogger;
22 import io.netty.util.internal.logging.InternalLoggerFactory;
23
24 public final class IoUring {
25
26 private static final Throwable UNAVAILABILITY_CAUSE;
27 private static final boolean IORING_CQE_F_SOCK_NONEMPTY_SUPPORTED;
28 private static final boolean IORING_SPLICE_SUPPORTED;
29 private static final boolean IORING_ACCEPT_NO_WAIT_SUPPORTED;
30 private static final boolean IORING_REGISTER_IOWQ_MAX_WORKERS_SUPPORTED;
31
32 static {
33 Throwable cause = null;
34 boolean socketNonEmptySupported = false;
35 boolean spliceSupported = false;
36 boolean acceptSupportNoWait = false;
37 boolean registerIowqWorkersSupported = false;
38 try {
39 if (SystemPropertyUtil.getBoolean("io.netty.transport.noNative", false)) {
40 cause = new UnsupportedOperationException(
41 "Native transport was explicit disabled with -Dio.netty.transport.noNative=true");
42 } else {
43 String kernelVersion = Native.kernelVersion();
44 Native.checkKernelVersion(kernelVersion);
45 Throwable unsafeCause = PlatformDependent.getUnsafeUnavailabilityCause();
46 if (unsafeCause == null) {
47 RingBuffer ringBuffer = null;
48 try {
49 ringBuffer = Native.createRingBuffer();
50 Native.checkAllIOSupported(ringBuffer.fd());
51 socketNonEmptySupported = Native.isIOUringCqeFSockNonEmptySupported(ringBuffer.fd());
52 spliceSupported = Native.isIOUringSupportSplice(ringBuffer.fd());
53
54 acceptSupportNoWait = (ringBuffer.features() & Native.IORING_FEAT_RECVSEND_BUNDLE) != 0;
55 registerIowqWorkersSupported = Native.isRegisterIOWQWorkerSupported(ringBuffer.fd());
56 } finally {
57 if (ringBuffer != null) {
58 try {
59 ringBuffer.close();
60 } catch (Exception ignore) {
61
62 }
63 }
64 }
65 } else {
66 cause = new UnsupportedOperationException("Unsafe is not supported", unsafeCause);
67 }
68 }
69 } catch (Throwable t) {
70 cause = t;
71 }
72 if (cause != null) {
73 InternalLogger logger = InternalLoggerFactory.getInstance(IoUring.class);
74 if (logger.isTraceEnabled()) {
75 logger.debug("IoUring support is not available", cause);
76 } else if (logger.isDebugEnabled()) {
77 logger.debug("IoUring support is not available: {}", cause.getMessage());
78 }
79 }
80 UNAVAILABILITY_CAUSE = cause;
81 IORING_CQE_F_SOCK_NONEMPTY_SUPPORTED = socketNonEmptySupported;
82 IORING_SPLICE_SUPPORTED = spliceSupported;
83 IORING_ACCEPT_NO_WAIT_SUPPORTED = acceptSupportNoWait;
84 IORING_REGISTER_IOWQ_MAX_WORKERS_SUPPORTED = registerIowqWorkersSupported;
85 }
86
87 public static boolean isAvailable() {
88 return UNAVAILABILITY_CAUSE == null;
89 }
90
91
92
93
94
95
96
97 public static boolean isTcpFastOpenClientSideAvailable() {
98 return isAvailable() && Native.IS_SUPPORTING_TCP_FASTOPEN_CLIENT;
99 }
100
101
102
103
104
105
106
107 public static boolean isTcpFastOpenServerSideAvailable() {
108 return isAvailable() && Native.IS_SUPPORTING_TCP_FASTOPEN_SERVER;
109 }
110
111 static boolean isIOUringCqeFSockNonEmptySupported() {
112 return IORING_CQE_F_SOCK_NONEMPTY_SUPPORTED;
113 }
114
115 static boolean isIOUringSpliceSupported() {
116 return IORING_SPLICE_SUPPORTED;
117 }
118
119 static boolean isIOUringAcceptNoWaitSupported() {
120 return IORING_ACCEPT_NO_WAIT_SUPPORTED;
121 }
122
123 static boolean isRegisterIowqMaxWorkersSupported() {
124 return IORING_REGISTER_IOWQ_MAX_WORKERS_SUPPORTED;
125 }
126
127 public static void ensureAvailability() {
128 if (UNAVAILABILITY_CAUSE != null) {
129 throw (Error) new UnsatisfiedLinkError(
130 "failed to load the required native library").initCause(UNAVAILABILITY_CAUSE);
131 }
132 }
133
134 public static Throwable unavailabilityCause() {
135 return UNAVAILABILITY_CAUSE;
136 }
137
138 private IoUring() {
139 }
140 }