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_ACCEPT_MULTISHOT_SUPPORTED;
31 private static final boolean IORING_RECV_MULTISHOT_SUPPORTED;
32 private static final boolean IORING_RECVSEND_BUNDLE_SUPPORTED;
33 private static final boolean IORING_POLL_ADD_MULTISHOT_SUPPORTED;
34 private static final boolean IORING_REGISTER_IOWQ_MAX_WORKERS_SUPPORTED;
35 private static final boolean IORING_SETUP_SUBMIT_ALL_SUPPORTED;
36 private static final boolean IORING_SETUP_CQ_SIZE_SUPPORTED;
37 private static final boolean IORING_SETUP_SINGLE_ISSUER_SUPPORTED;
38 private static final boolean IORING_SETUP_DEFER_TASKRUN_SUPPORTED;
39 private static final boolean IORING_REGISTER_BUFFER_RING_SUPPORTED;
40 private static final boolean IORING_REGISTER_BUFFER_RING_INC_SUPPORTED;
41
42 private static final InternalLogger logger;
43
44 static {
45 logger = InternalLoggerFactory.getInstance(IoUring.class);
46 Throwable cause = null;
47 boolean socketNonEmptySupported = false;
48 boolean spliceSupported = false;
49 boolean acceptSupportNoWait = false;
50 boolean acceptMultishotSupported = false;
51 boolean recvsendBundleSupported = false;
52 boolean recvMultishotSupported = false;
53 boolean pollAddMultishotSupported = false;
54 boolean registerIowqWorkersSupported = false;
55 boolean submitAllSupported = false;
56 boolean setUpCqSizeSupported = false;
57 boolean singleIssuerSupported = false;
58 boolean deferTaskrunSupported = false;
59 boolean registerBufferRingSupported = false;
60 boolean registerBufferRingIncSupported = false;
61
62 try {
63 if (SystemPropertyUtil.getBoolean("io.netty.transport.noNative", false)) {
64 cause = new UnsupportedOperationException(
65 "Native transport was explicit disabled with -Dio.netty.transport.noNative=true");
66 } else {
67 String kernelVersion = Native.kernelVersion();
68 Native.checkKernelVersion(kernelVersion);
69 Throwable unsafeCause = PlatformDependent.getUnsafeUnavailabilityCause();
70 if (unsafeCause == null) {
71 RingBuffer ringBuffer = null;
72 try {
73 ringBuffer = Native.createRingBuffer(1, 0);
74 Native.checkAllIOSupported(ringBuffer.fd());
75 socketNonEmptySupported = Native.isCqeFSockNonEmptySupported(ringBuffer.fd());
76 spliceSupported = Native.isSpliceSupported(ringBuffer.fd());
77 recvsendBundleSupported = (ringBuffer.features() & Native.IORING_FEAT_RECVSEND_BUNDLE) != 0;
78
79 acceptSupportNoWait = recvsendBundleSupported;
80 acceptMultishotSupported = Native.isAcceptMultishotSupported(ringBuffer.fd());
81 recvMultishotSupported = Native.isRecvMultishotSupported();
82 pollAddMultishotSupported = Native.isPollAddMultiShotSupported(ringBuffer.fd());
83 registerIowqWorkersSupported = Native.isRegisterIoWqWorkerSupported(ringBuffer.fd());
84 submitAllSupported = Native.ioUringSetupSupportsFlags(Native.IORING_SETUP_SUBMIT_ALL);
85 setUpCqSizeSupported = Native.ioUringSetupSupportsFlags(Native.IORING_SETUP_CQSIZE);
86 singleIssuerSupported = Native.ioUringSetupSupportsFlags(Native.IORING_SETUP_SINGLE_ISSUER);
87
88
89 deferTaskrunSupported = Native.ioUringSetupSupportsFlags(
90 Native.IORING_SETUP_SINGLE_ISSUER | Native.IORING_SETUP_DEFER_TASKRUN);
91 registerBufferRingSupported = Native.isRegisterBufferRingSupported(ringBuffer.fd(), 0);
92 registerBufferRingIncSupported = Native.isRegisterBufferRingSupported(ringBuffer.fd(),
93 Native.IOU_PBUF_RING_INC);
94 } finally {
95 if (ringBuffer != null) {
96 try {
97 ringBuffer.close();
98 } catch (Exception ignore) {
99
100 }
101 }
102 }
103 } else {
104 cause = new UnsupportedOperationException("Unsafe is not supported", unsafeCause);
105 }
106 }
107 } catch (Throwable t) {
108 cause = t;
109 }
110 if (cause != null) {
111 if (logger.isTraceEnabled()) {
112 logger.debug("IoUring support is not available", cause);
113 } else if (logger.isDebugEnabled()) {
114 logger.debug("IoUring support is not available: {}", cause.getMessage());
115 }
116 } else {
117 if (logger.isDebugEnabled()) {
118 logger.debug("IoUring support is available (" +
119 "CQE_F_SOCK_NONEMPTY_SUPPORTED={}, " +
120 "SPLICE_SUPPORTED={}, " +
121 "ACCEPT_NO_WAIT_SUPPORTED={}, " +
122 "ACCEPT_MULTISHOT_SUPPORTED={}, " +
123 "POLL_ADD_MULTISHOT_SUPPORTED={} " +
124 "RECV_MULTISHOT_SUPPORTED={}, " +
125 "IORING_RECVSEND_BUNDLE_SUPPORTED={}, " +
126 "REGISTER_IOWQ_MAX_WORKERS_SUPPORTED={}, " +
127 "SETUP_SUBMIT_ALL_SUPPORTED={}, " +
128 "SETUP_SINGLE_ISSUER_SUPPORTED={}, " +
129 "SETUP_DEFER_TASKRUN_SUPPORTED={}, " +
130 "REGISTER_BUFFER_RING_SUPPORTED={}, " +
131 "REGISTER_BUFFER_RING_INC_SUPPORTED={}" +
132 ")", socketNonEmptySupported, spliceSupported, acceptSupportNoWait, acceptMultishotSupported,
133 pollAddMultishotSupported, recvMultishotSupported, recvsendBundleSupported,
134 registerIowqWorkersSupported, submitAllSupported, singleIssuerSupported, deferTaskrunSupported,
135 registerBufferRingSupported, registerBufferRingIncSupported);
136 }
137 }
138 UNAVAILABILITY_CAUSE = cause;
139 IORING_CQE_F_SOCK_NONEMPTY_SUPPORTED = socketNonEmptySupported;
140 IORING_SPLICE_SUPPORTED = spliceSupported;
141 IORING_ACCEPT_NO_WAIT_SUPPORTED = acceptSupportNoWait;
142 IORING_ACCEPT_MULTISHOT_SUPPORTED = acceptMultishotSupported;
143 IORING_RECV_MULTISHOT_SUPPORTED = recvMultishotSupported;
144 IORING_RECVSEND_BUNDLE_SUPPORTED = recvsendBundleSupported;
145 IORING_POLL_ADD_MULTISHOT_SUPPORTED = pollAddMultishotSupported;
146 IORING_REGISTER_IOWQ_MAX_WORKERS_SUPPORTED = registerIowqWorkersSupported;
147 IORING_SETUP_SUBMIT_ALL_SUPPORTED = submitAllSupported;
148 IORING_SETUP_CQ_SIZE_SUPPORTED = setUpCqSizeSupported;
149 IORING_SETUP_SINGLE_ISSUER_SUPPORTED = singleIssuerSupported;
150 IORING_SETUP_DEFER_TASKRUN_SUPPORTED = deferTaskrunSupported;
151 IORING_REGISTER_BUFFER_RING_SUPPORTED = registerBufferRingSupported;
152 IORING_REGISTER_BUFFER_RING_INC_SUPPORTED = registerBufferRingIncSupported;
153 }
154
155 public static boolean isAvailable() {
156 return UNAVAILABILITY_CAUSE == null;
157 }
158
159
160
161
162
163
164
165 public static boolean isTcpFastOpenClientSideAvailable() {
166 return isAvailable() && Native.IS_SUPPORTING_TCP_FASTOPEN_CLIENT;
167 }
168
169
170
171
172
173
174
175 public static boolean isTcpFastOpenServerSideAvailable() {
176 return isAvailable() && Native.IS_SUPPORTING_TCP_FASTOPEN_SERVER;
177 }
178
179 static boolean isCqeFSockNonEmptySupported() {
180 return IORING_CQE_F_SOCK_NONEMPTY_SUPPORTED;
181 }
182
183 static boolean isSpliceSupported() {
184 return IORING_SPLICE_SUPPORTED;
185 }
186
187 static boolean isAcceptNoWaitSupported() {
188 return IORING_ACCEPT_NO_WAIT_SUPPORTED;
189 }
190
191 static boolean isAcceptMultishotSupported() {
192 return IORING_ACCEPT_MULTISHOT_SUPPORTED;
193 }
194
195 static boolean isRecvMultishotSupported() {
196 return IORING_RECV_MULTISHOT_SUPPORTED;
197 }
198
199 static boolean isRecvsendBundleSupported() {
200 return IORING_RECVSEND_BUNDLE_SUPPORTED;
201 }
202
203 static boolean isPollAddMultishotSupported() {
204 return IORING_POLL_ADD_MULTISHOT_SUPPORTED;
205 }
206
207 static boolean isRegisterIowqMaxWorkersSupported() {
208 return IORING_REGISTER_IOWQ_MAX_WORKERS_SUPPORTED;
209 }
210
211 static boolean isSetupCqeSizeSupported() {
212 return IORING_SETUP_CQ_SIZE_SUPPORTED;
213 }
214
215 static boolean isSetupSubmitAllSupported() {
216 return IORING_SETUP_SUBMIT_ALL_SUPPORTED;
217 }
218
219 static boolean isSetupSingleIssuerSupported() {
220 return IORING_SETUP_SINGLE_ISSUER_SUPPORTED;
221 }
222
223 static boolean isSetupDeferTaskrunSupported() {
224 return IORING_SETUP_DEFER_TASKRUN_SUPPORTED;
225 }
226
227 public static boolean isRegisterBufferRingSupported() {
228 return IORING_REGISTER_BUFFER_RING_SUPPORTED;
229 }
230
231 public static boolean isRegisterBufferRingIncSupported() {
232 return IORING_REGISTER_BUFFER_RING_INC_SUPPORTED;
233 }
234
235 public static void ensureAvailability() {
236 if (UNAVAILABILITY_CAUSE != null) {
237 throw (Error) new UnsatisfiedLinkError(
238 "failed to load the required native library").initCause(UNAVAILABILITY_CAUSE);
239 }
240 }
241
242 public static Throwable unavailabilityCause() {
243 return UNAVAILABILITY_CAUSE;
244 }
245
246 private IoUring() {
247 }
248 }