private unsafe void AcceptThreadStart(object state) { try { var socket = _socket; using (socket) { using (EPoll epoll = EPoll.Create()) { int epollFd = epoll.DangerousGetHandle().ToInt32(); const int acceptKey = 0; const int pipeKey = 1; // accept socket epoll.Control(EPollOperation.Add, _socket, EPollEvents.Readable, new EPollData { Int1 = acceptKey, Int2 = acceptKey }); // add pipe epoll.Control(EPollOperation.Add, _pipeEnds.ReadEnd, EPollEvents.Readable, new EPollData { Int1 = pipeKey, Int2 = pipeKey }); const int EventBufferLength = 1; int notPacked = !EPoll.PackedEvents ? 1 : 0; var buffer = stackalloc int[EventBufferLength * (3 + notPacked)]; int * key = &buffer[2]; bool running = true; int nextHandler = 0; var handlers = _handlers; do { int numEvents = EPollInterop.EPollWait(epollFd, buffer, EventBufferLength, timeout: EPoll.TimeoutInfinite).Value; if (numEvents == 1) { if (*key == acceptKey) { var handler = handlers[nextHandler]; nextHandler = (nextHandler + 1) % handlers.Length; socket.TryAcceptAndSendHandleTo(handler); } else { running = false; } } } while (running); } } _stoppedTcs.TrySetResult(null); } catch (Exception e) { _stoppedTcs.SetException(e); } finally { Cleanup(); } }
public void Initialize() { // These members need to be Disposed EPoll = EPoll.Create(); EPollFd = EPoll.DangerousGetHandle().ToInt32(); PipeFactory = new PipeFactory(); PipeEnds = PipeEnd.CreatePair(blocking: false); }
public unsafe ThreadContext(TransportThread transportThread) { _transportThread = transportThread; _connectionDispatcher = transportThread.ConnectionDispatcher; _sockets = new Dictionary <int, TSocket>(); _logger = _transportThread.LoggerFactory.CreateLogger($"{nameof(RedHatX)}.{nameof(TransportThread)}.{_transportThread.ThreadId}"); _acceptSockets = new List <TSocket>(); _transportOptions = transportThread.TransportOptions; _scheduledSendAdding = new List <ScheduledSend>(1024); _scheduledSendRunning = new List <ScheduledSend>(1024); _epollState = EPollBlocked; if (_transportOptions.AioReceive | _transportOptions.AioSend) { _aioEventsMemory = AllocMemory(sizeof(AioEvent) * EventBufferLength); _aioCbsMemory = AllocMemory(sizeof(AioCb) * EventBufferLength); _aioCbsTableMemory = AllocMemory(sizeof(AioCb *) * EventBufferLength); _ioVectorTableMemory = AllocMemory(sizeof(IOVector) * IoVectorsPerAioSocket * EventBufferLength); for (int i = 0; i < EventBufferLength; i++) { AioCbsTable[i] = &AioCbs[i]; } if (_transportOptions.AioSend) { _aioSendBuffers = new ReadOnlySequence <byte> [EventBufferLength]; } } int maxMemoryHandleCount = TSocket.MaxIOVectorReceiveLength; if (_transportOptions.AioReceive || _transportOptions.AioSend) { maxMemoryHandleCount = Math.Max(maxMemoryHandleCount, EventBufferLength); } if (_transportOptions.DeferSend) { maxMemoryHandleCount = Math.Max(maxMemoryHandleCount, TSocket.MaxIOVectorSendLength); } MemoryHandles = new MemoryHandle[maxMemoryHandleCount]; // These members need to be Disposed _epoll = EPoll.Create(); _epollFd = _epoll.DangerousGetHandle().ToInt32(); MemoryPool = CreateMemoryPool(); _pipeEnds = PipeEnd.CreatePair(blocking: false); if (_aioEventsMemory != IntPtr.Zero) { AioInterop.IoSetup(EventBufferLength, out _aioContext).ThrowOnError(); } }
public static extern PosixResult EPollCreate(out EPoll epoll);
public static PosixResult EPollControl(EPoll epoll, EPollOperation operation, SafeHandle fd, EPollEvents events, long data) => EPollControl(epoll.DangerousGetHandle().ToInt32(), operation, fd.DangerousGetHandle().ToInt32(), events, data);
public static unsafe PosixResult EPollWait(EPoll epoll, void *events, int maxEvents, int timeout) => EPollWait(epoll.DangerousGetHandle().ToInt32(), events, maxEvents, timeout);