1module Runtime.NativeSocketEndpoint
2
3import Compiler.MachineX86Native
4import Compiler.MachineX86NativeAssembly
5import Runtime.NativeDescriptor
6import Runtime.NativeSocketRoutine
7import Runtime.NativePhysicalNative
8import Std.List
9import Std.Natural
10
11-- Linux x86-64 endpoint operations. connect uses the stream ABI's fd/address/
12-- extent/timeout/attempt registers; accept uses fd/unused/1/timeout/attempts.
13-- Both require O_NONBLOCK before any potentially blocking operation. The
14-- caller retains descriptor ownership on error and must close/abandon it.
15-- A successful accept returns an owned nonblocking, close-on-exec descriptor.
16-- The common poll budget covers retries and readiness races; it is not yet a
17-- session-wide monotonic deadline. No retry makes a failed connection usable.
18-- Sources, checked 2026-10-02: Linux UAPI asm/unistd_64.h, asm-generic/fcntl.h,
19-- asm-generic/socket.h; https://man7.org/linux/man-pages/man2/connect.2.html
20-- and https://man7.org/linux/man-pages/man2/accept.2.html.
21-- The common pollfd storage becomes SO_ERROR(int) + socklen_t after poll:
22-- these lifetimes do not overlap and both views occupy exactly eight bytes.
23def nativeSocketNonblock : Nat =
24 2048
25
26def nativeSocketCloseOnExec : Nat =
27 524288
28
29def nativeSocketEndpointFlags =
30 (naturalAdd nativeSocketNonblock nativeSocketCloseOnExec)
31
32def nativeSocketRequireNonblocking =
33 (lambda unrestricted tail : (family X86NativeAssembly) .
34 (nativePhysicalNativeEmit
35 (nativePhysicalNativeMove
36 (constructor X86NativeRegister64 X86NativeRBX)
37 (constructor X86NativeRegister64 X86NativeRDI))
38 (nativePhysicalNativeEmit
39 (nativePhysicalNativeMoveImmediate32
40 (constructor X86NativeRegister64 X86NativeRSI)
41 (nativeSocketImmediate 3))
42 (nativePhysicalNativeEmit
43 (nativePhysicalNativeMoveImmediate32
44 (constructor X86NativeRegister64 X86NativeRAX)
45 (nativeSocketImmediate 72))
46 (nativePhysicalNativeEmit
47 nativePhysicalNativeSystemCallInstruction
48 (nativePhysicalNativeEmit
49 (nativePhysicalNativeTest
50 (constructor X86NativeRegister64 X86NativeRAX)
51 (constructor X86NativeRegister64 X86NativeRAX))
52 (nativePhysicalNativeJumpCondition
53 (constructor X86NativeCondition X86NativeConditionSign)
54 b"socket-return"
55 (nativePhysicalNativeEmit
56 (constructor
57 X86NativeInstruction
58 X86NativeAndImmediate64
59 (constructor X86NativeRegister64 X86NativeRAX)
60 (nativeSocketImmediate nativeSocketNonblock))
61 (nativePhysicalNativeEmit
62 (nativePhysicalNativeTest
63 (constructor X86NativeRegister64 X86NativeRAX)
64 (constructor X86NativeRegister64 X86NativeRAX))
65 (nativePhysicalNativeJumpCondition
66 (constructor X86NativeCondition X86NativeConditionZero)
67 b"socket-invalid"
68 tail))))))))))
69
70-- Initiate once, then wait only for EINPROGRESS. A failed connect never
71-- reuses an indeterminate socket by trying the address again.
72def nativeSocketConnectStart =
73 (lambda unrestricted tail : (family X86NativeAssembly) .
74 (nativePhysicalNativeEmit
75 (nativePhysicalNativeMove
76 (constructor X86NativeRegister64 X86NativeRBX)
77 (constructor X86NativeRegister64 X86NativeRDI))
78 (nativePhysicalNativeEmit
79 (nativePhysicalNativeMove
80 (constructor X86NativeRegister64 X86NativeR12)
81 (constructor X86NativeRegister64 X86NativeRSI))
82 (nativePhysicalNativeEmit
83 (nativePhysicalNativeMove
84 (constructor X86NativeRegister64 X86NativeR13)
85 (constructor X86NativeRegister64 X86NativeRDX))
86 (nativePhysicalNativeEmit
87 (nativePhysicalNativeMoveImmediate32
88 (constructor X86NativeRegister64 X86NativeRAX)
89 (nativeSocketImmediate 42))
90 (nativePhysicalNativeEmit
91 nativePhysicalNativeSystemCallInstruction
92 (nativePhysicalNativeEmit
93 (nativePhysicalNativeTest
94 (constructor X86NativeRegister64 X86NativeRAX)
95 (constructor X86NativeRegister64 X86NativeRAX))
96 (nativePhysicalNativeJumpCondition
97 (constructor X86NativeCondition X86NativeConditionZero)
98 b"socket-return"
99 (nativePhysicalNativeEmit
100 (nativePhysicalNativeCompareImmediate
101 (constructor X86NativeRegister64 X86NativeRAX)
102 (nativeSocketImmediate (naturalSaturatingSubtract 4294967296 115)))
103 (nativePhysicalNativeJumpCondition
104 (constructor X86NativeCondition X86NativeConditionZero)
105 b"socket-loop"
106 (nativePhysicalNativeJump b"socket-return" tail)))))))))))
107
108-- Writability includes refusal. Read the full int SO_ERROR, negate its errno,
109-- and only then report success. Reuse the no-longer-live pollfd stack bytes.
110def nativeSocketReadConnectStatus =
111 (lambda unrestricted tail : (family X86NativeAssembly) .
112 (nativePhysicalNativeEmit
113 (nativePhysicalNativeMoveImmediate32
114 (constructor X86NativeRegister64 X86NativeRAX)
115 (nativeSocketImmediate 0))
116 (nativePhysicalNativeEmit
117 (constructor
118 X86NativeInstruction
119 X86NativeStoreMemory32
120 (constructor X86NativeRegister64 X86NativeRSP)
121 (nativeSocketDisplacement nativeSocketPollSlot)
122 (constructor X86NativeRegister64 X86NativeRAX))
123 (nativePhysicalNativeEmit
124 (nativePhysicalNativeMoveImmediate32
125 (constructor X86NativeRegister64 X86NativeRAX)
126 (nativeSocketImmediate nativeSocketPollFdBytes))
127 (nativePhysicalNativeEmit
128 (constructor
129 X86NativeInstruction
130 X86NativeStoreMemory32
131 (constructor X86NativeRegister64 X86NativeRSP)
132 (nativeSocketDisplacement nativeSocketPollEventsSlot)
133 (constructor X86NativeRegister64 X86NativeRAX))
134 (nativePhysicalNativeEmit
135 (nativePhysicalNativeMove
136 (constructor X86NativeRegister64 X86NativeRBX)
137 (constructor X86NativeRegister64 X86NativeRDI))
138 (nativePhysicalNativeEmit
139 (nativePhysicalNativeMoveImmediate32
140 (constructor X86NativeRegister64 X86NativeRSI)
141 (nativeSocketImmediate 1))
142 (nativePhysicalNativeEmit
143 (nativePhysicalNativeMoveImmediate32
144 (constructor X86NativeRegister64 X86NativeRDX)
145 (nativeSocketImmediate 4))
146 (nativePhysicalNativeEmit
147 (nativePhysicalNativeMove
148 (constructor X86NativeRegister64 X86NativeRSP)
149 (constructor X86NativeRegister64 X86NativeR10))
150 (nativePhysicalNativeEmit
151 (nativePhysicalNativeAddImmediate
152 (constructor X86NativeRegister64 X86NativeR10)
153 (nativeSocketImmediate nativeSocketPollSlot))
154 (nativePhysicalNativeEmit
155 (nativePhysicalNativeMove
156 (constructor X86NativeRegister64 X86NativeRSP)
157 (constructor X86NativeRegister64 X86NativeR8))
158 (nativePhysicalNativeEmit
159 (nativePhysicalNativeAddImmediate
160 (constructor X86NativeRegister64 X86NativeR8)
161 (nativeSocketImmediate nativeSocketPollEventsSlot))
162 (nativePhysicalNativeEmit
163 (nativePhysicalNativeMoveImmediate32
164 (constructor X86NativeRegister64 X86NativeRAX)
165 (nativeSocketImmediate 55))
166 (nativePhysicalNativeEmit
167 nativePhysicalNativeSystemCallInstruction
168 (nativePhysicalNativeEmit
169 (nativePhysicalNativeCompareImmediate
170 (constructor X86NativeRegister64 X86NativeRAX)
171 (nativeSocketImmediate (naturalSaturatingSubtract 4294967296 4)))
172 (nativePhysicalNativeJumpCondition
173 (constructor X86NativeCondition X86NativeConditionZero)
174 b"socket-loop"
175 (nativePhysicalNativeEmit
176 (nativePhysicalNativeTest
177 (constructor X86NativeRegister64 X86NativeRAX)
178 (constructor X86NativeRegister64 X86NativeRAX))
179 (nativePhysicalNativeJumpCondition
180 (constructor X86NativeCondition X86NativeConditionSign)
181 b"socket-return"
182 (nativePhysicalNativeEmit
183 (constructor
184 X86NativeInstruction
185 X86NativeLoadMemory32ZeroExtend64
186 (constructor X86NativeRegister64 X86NativeR13)
187 (constructor X86NativeRegister64 X86NativeRSP)
188 (nativeSocketDisplacement nativeSocketPollEventsSlot))
189 (nativePhysicalNativeEmit
190 (nativePhysicalNativeCompareImmediate
191 (constructor X86NativeRegister64 X86NativeR13)
192 (nativeSocketImmediate nativeSocketPollFdBytes))
193 (nativePhysicalNativeJumpCondition
194 (constructor X86NativeCondition X86NativeConditionNotZero)
195 b"socket-invalid"
196 (nativePhysicalNativeEmit
197 (constructor
198 X86NativeInstruction
199 X86NativeLoadMemory32ZeroExtend64
200 (constructor X86NativeRegister64 X86NativeR13)
201 (constructor X86NativeRegister64 X86NativeRSP)
202 (nativeSocketDisplacement nativeSocketPollSlot))
203 (nativePhysicalNativeEmit
204 (constructor
205 X86NativeInstruction
206 X86NativeClear32
207 (constructor X86NativeRegister64 X86NativeRAX))
208 (nativePhysicalNativeEmit
209 (nativePhysicalNativeSubtract
210 (constructor X86NativeRegister64 X86NativeR13)
211 (constructor X86NativeRegister64 X86NativeRAX))
212 (nativePhysicalNativeJump b"socket-return" tail)))))))))))))))))))))))))
213
214def nativeSocketConnectAssembly =
215 (nativeSocketEntry
216 (nativeSocketRequireNonblocking
217 (nativeSocketConnectStart
218 (nativeSocketPoll
219 4
220 (nativeSocketReadConnectStatus
221 (nativeSocketReturn (constructor X86NativeAssembly X86NativeAssemblyEnd)))))))
222
223-- accept4 may race with another accept or surface a pending TCP error.
224-- These are the classes accept(2) documents as retryable for a nonblocking
225-- listener -- EINTR and EAGAIN, plus the pending network errors Linux passes
226-- through (ENETDOWN, EPROTO, ENOPROTOOPT, EHOSTDOWN, ENONET, EHOSTUNREACH,
227-- EOPNOTSUPP, ENETUNREACH) and ECONNABORTED. They retry through the bounded
228-- poll loop, in this order; every other result returns. The list is the one
229-- owner of that classification: each host realization of accept (x86-64 here,
230-- Platform.AArch64.SocketRoutine) folds over it. The errno numbers are
231-- asm-generic and identical on x86-64 and AArch64 Linux.
232def nativeSocketAcceptTransientErrors : (family StdList Nat) =
233 (constructor
234 StdList
235 StdListCons
236 Nat
237 4
238 (constructor
239 StdList
240 StdListCons
241 Nat
242 11
243 (constructor
244 StdList
245 StdListCons
246 Nat
247 100
248 (constructor
249 StdList
250 StdListCons
251 Nat
252 71
253 (constructor
254 StdList
255 StdListCons
256 Nat
257 92
258 (constructor
259 StdList
260 StdListCons
261 Nat
262 112
263 (constructor
264 StdList
265 StdListCons
266 Nat
267 64
268 (constructor
269 StdList
270 StdListCons
271 Nat
272 113
273 (constructor
274 StdList
275 StdListCons
276 Nat
277 95
278 (constructor
279 StdList
280 StdListCons
281 Nat
282 101
283 (constructor
284 StdList
285 StdListCons
286 Nat
287 103
288 (constructor StdList StdListEmpty Nat))))))))))))
289
290def nativeSocketRetryOn =
291 (lambda unrestricted errno : Nat .
292 (lambda unrestricted tail : (family X86NativeAssembly) .
293 (nativePhysicalNativeEmit
294 (nativePhysicalNativeCompareImmediate
295 (constructor X86NativeRegister64 X86NativeRAX)
296 (nativeSocketImmediate (naturalSaturatingSubtract 4294967296 errno)))
297 (nativePhysicalNativeJumpCondition
298 (constructor X86NativeCondition X86NativeConditionZero)
299 b"socket-loop"
300 tail))))
301
302def nativeSocketAcceptReady =
303 (lambda unrestricted tail : (family X86NativeAssembly) .
304 (nativePhysicalNativeEmit
305 (nativePhysicalNativeMove
306 (constructor X86NativeRegister64 X86NativeRBX)
307 (constructor X86NativeRegister64 X86NativeRDI))
308 (nativePhysicalNativeEmit
309 (nativePhysicalNativeMoveImmediate32
310 (constructor X86NativeRegister64 X86NativeRSI)
311 (nativeSocketImmediate 0))
312 (nativePhysicalNativeEmit
313 (nativePhysicalNativeMoveImmediate32
314 (constructor X86NativeRegister64 X86NativeRDX)
315 (nativeSocketImmediate 0))
316 (nativePhysicalNativeEmit
317 (nativePhysicalNativeMoveImmediate32
318 (constructor X86NativeRegister64 X86NativeR10)
319 (nativeSocketImmediate nativeSocketEndpointFlags))
320 (nativePhysicalNativeEmit
321 (nativePhysicalNativeMoveImmediate32
322 (constructor X86NativeRegister64 X86NativeRAX)
323 (nativeSocketImmediate 288))
324 (nativePhysicalNativeEmit
325 nativePhysicalNativeSystemCallInstruction
326 (stdListFold
327 Nat
328 (family X86NativeAssembly)
329 nativeSocketRetryOn
330 (nativePhysicalNativeJump b"socket-return" tail)
331 nativeSocketAcceptTransientErrors))))))))
332
333def nativeSocketAcceptAssembly =
334 (nativeSocketEntry
335 (nativeSocketRequireNonblocking
336 (nativeSocketPoll
337 1
338 (nativeSocketAcceptReady
339 (nativeSocketReturn (constructor X86NativeAssembly X86NativeAssemblyEnd))))))
340
341def nativeSocketDescriptorStatusAssembly =
342 nativeDescriptorStatusAssembly
343
344def nativeSocketConnectCode =
345 (compiler-native-encode (family X86NativeAssembly) nativeSocketConnectAssembly)
346
347def nativeSocketAcceptCode =
348 (compiler-native-encode (family X86NativeAssembly) nativeSocketAcceptAssembly)
349
350def nativeSocketDescriptorStatusCode =
351 nativeDescriptorStatusCodeThe compiler supplied declaration spans and resolved links from this source snapshot. This page does not assert that this file belongs to a checked closure.