private void RemovePinFromPoll(int bcmPinNumber, ref int pollFileDescriptor, bool closePinValueFileDescriptor, bool closePollFileDescriptor) { //Console.WriteLine($"Removing pin from poll: {bcmPinNumber}"); int fd = _pinValueFileDescriptors[bcmPinNumber]; var ev = new epoll_event { events = PollEvents.EPOLLIN | PollEvents.EPOLLET | PollEvents.EPOLLPRI, }; //Console.WriteLine($"poll_fd = {pollFileDescriptor}, pin_value_fd = {fd}"); int r = epoll_ctl(pollFileDescriptor, PollOperations.EPOLL_CTL_DEL, fd, ref ev); if (r == -1) { throw Utils.CreateIOException("Error initializing pin interrupts", r); } if (closePinValueFileDescriptor) { close(fd); _pinValueFileDescriptors[bcmPinNumber] = -1; } if (closePollFileDescriptor) { close(pollFileDescriptor); pollFileDescriptor = -1; } }
private void RemovePinFromPoll(int pinNumber, ref int valueFileDescriptor, ref int pollFileDescriptor, bool closePinValueFileDescriptor, bool closePollFileDescriptor, bool cancelEventDetectionThread) { epoll_event epollEvent = new epoll_event { events = PollEvents.EPOLLIN | PollEvents.EPOLLET | PollEvents.EPOLLPRI }; int result = Interop.epoll_ctl(pollFileDescriptor, PollOperations.EPOLL_CTL_DEL, valueFileDescriptor, ref epollEvent); if (result == -1) { throw new IOException("Error while trying to initialize pin interrupts."); } if (closePinValueFileDescriptor) { Interop.close(valueFileDescriptor); valueFileDescriptor = -1; } if (closePollFileDescriptor) { if (cancelEventDetectionThread) { s_eventThreadCancellationTokenSource.Cancel(); while (_eventDetectionThread != null && _eventDetectionThread.IsAlive) { Thread.Sleep(TimeSpan.FromMilliseconds(10)); // Wait until the event detection thread is aborted. } } Interop.close(pollFileDescriptor); pollFileDescriptor = -1; } }
void EpollWait() { Dictionary <int, LinuxSocket> sockmap; lock (typeof(LinuxSocket)) { if (epollfd == -1) { epollfd = epoll_create1(0x80000); if (epollfd == -1) { throw new PosixException("epoll_create1"); } epollfds = 0; epollsockets = new Dictionary <int, LinuxSocket>(); } sockmap = epollsockets; if (epollthread == null) { epollthread = new Thread(EpollLoop); epollthread.IsBackground = true; epollthread.Start(); } } lock (sockmap) sockmap[handle] = this; lock (this) { uint mode = (1 << 30); //ONESHOT if (recvqhead != null) { mode |= 0x001; } if (sendqhead != null) { mode |= 0x004; } if ((mode & 0x005) == 0) { return; } epoll_event evt = new epoll_event() { Events = mode, Data = (UInt64)handle }; int ret = epoll_ctl(epollfd, 1, handle, ref evt); //ADD if (ret != -1) { Interlocked.Increment(ref epollfds); } if (ret == -1 && Marshal.GetLastWin32Error() == 17) { ret = epoll_ctl(epollfd, 3, handle, ref evt); //MODIFY } if (ret == -1) { throw new PosixException("epoll_ctl"); } } }
private void AddPinToPoll(int bcmPinNumber, ref int pollFileDescriptor, out bool closePinValueFileDescriptor) { //Console.WriteLine($"Adding pin to poll: {bcmPinNumber}"); if (pollFileDescriptor == -1) { pollFileDescriptor = epoll_create(1); if (pollFileDescriptor < 0) { throw Utils.CreateIOException("Error initializing pin interrupts", pollFileDescriptor); } } closePinValueFileDescriptor = false; int fd = _pinValueFileDescriptors[bcmPinNumber]; if (fd <= 0) { string valuePath = $"{GpioPath}/gpio{bcmPinNumber}/value"; fd = open(valuePath, FileOpenFlags.O_RDONLY | FileOpenFlags.O_NONBLOCK); //Console.WriteLine($"{valuePath} open result: {fd}"); if (fd < 0) { throw Utils.CreateIOException("Error initializing pin interrupts", fd); } _pinValueFileDescriptors[bcmPinNumber] = fd; closePinValueFileDescriptor = true; } var ev = new epoll_event { events = PollEvents.EPOLLIN | PollEvents.EPOLLET | PollEvents.EPOLLPRI, data = new epoll_data() { //fd = fd bcmPinNumber = bcmPinNumber } }; //Console.WriteLine($"poll_fd = {pollFileDescriptor}, pin_value_fd = {fd}"); int r = epoll_ctl(pollFileDescriptor, PollOperations.EPOLL_CTL_ADD, fd, ref ev); if (r == -1) { throw Utils.CreateIOException("Error initializing pin interrupts", r); } // Ignore first time because it returns the current state epoll_wait(pollFileDescriptor, out _, 1, 0); }
public static unsafe PosixResult EPollControl(int epoll, int operation, int fd, int events, int data) { epoll_event ev = default(epoll_event); ev.events = events; ev.data.fd = data; int rv = epoll_ctl(epoll, operation, fd, &ev); return(PosixResult.FromReturnValue(rv)); }
public unsafe void Control(int op, int fd, int events, int key) { epoll_event ev = default; ev.events = events; ev.data.fd = key; int rv = epoll_ctl(_epollFd, op, fd, &ev); if (rv != 0) { PlatformException.Throw(); } }
private TcpConnection(Dispatcher dispatcher, int socket) { this.dispatcher = dispatcher; this.connection = socket; contextPair.readContext = null; contextPair.writeContext = null; epoll_event connectionEvent = new epoll_event(); connectionEvent.events = EPOLLONESHOT; connectionEvent.data.ptr = null; if (epoll_ctl(dispatcher.getEpoll(), EPOLL_CTL_ADD, socket, connectionEvent) == -1) { throw new System.Exception("TcpConnection::TcpConnection, epoll_ctl failed, " + lastErrorMessage()); } }
private void AddPinToPoll(int pinNumber, ref int valueFileDescriptor, ref int pollFileDescriptor, out bool closePinValueFileDescriptor) { if (pollFileDescriptor == -1) { pollFileDescriptor = Interop.epoll_create(1); if (pollFileDescriptor < 0) { throw new IOException("Error while trying to initialize pin interrupts (epoll_create failed)."); } } closePinValueFileDescriptor = false; if (valueFileDescriptor == -1) { string valuePath = Path.Combine(GpioBasePath, $"gpio{pinNumber + s_pinOffset}", "value"); valueFileDescriptor = Interop.open(valuePath, FileOpenFlags.O_RDONLY | FileOpenFlags.O_NONBLOCK); if (valueFileDescriptor < 0) { throw new IOException($"Error while trying to open pin value file {valuePath}."); } closePinValueFileDescriptor = true; } epoll_event epollEvent = new epoll_event { events = PollEvents.EPOLLIN | PollEvents.EPOLLET | PollEvents.EPOLLPRI, data = new epoll_data() { pinNumber = pinNumber } }; int result = Interop.epoll_ctl(pollFileDescriptor, PollOperations.EPOLL_CTL_ADD, valueFileDescriptor, ref epollEvent); if (result == -1) { throw new IOException("Error while trying to initialize pin interrupts (epoll_ctl failed)."); } // Ignore first time because it will always return the current state. Interop.epoll_wait(pollFileDescriptor, out _, 1, 0); }
public X11PlatformThreading(AvaloniaX11Platform platform) { _platform = platform; _display = platform.Display; _eventHandlers = platform.Windows; _mainThread = Thread.CurrentThread; var fd = XLib.XConnectionNumber(_display); var ev = new epoll_event() { events = EPOLLIN, data = { u32 = (int)EventCodes.X11 } }; _epoll = epoll_create1(0); if (_epoll == -1) { throw new X11Exception("epoll_create1 failed"); } if (epoll_ctl(_epoll, EPOLL_CTL_ADD, fd, ref ev) == -1) { throw new X11Exception("Unable to attach X11 connection handle to epoll"); } var fds = stackalloc int[2]; pipe2(fds, O_NONBLOCK); _sigread = fds[0]; _sigwrite = fds[1]; ev = new epoll_event { events = EPOLLIN, data = { u32 = (int)EventCodes.Signal } }; if (epoll_ctl(_epoll, EPOLL_CTL_ADD, _sigread, ref ev) == -1) { throw new X11Exception("Unable to attach signal pipe to epoll"); } }
//public void Connect(IPAddress[] addresses, int port); //public void Connect(string host, int port); protected virtual void Dispose(bool disposing) { int fd = handle; handle = -1; if (fd != -1) { Dictionary <int, LinuxSocket> sockmap; lock (typeof(LinuxSocket)) { if (epollfd != -1) { epoll_event evt = new epoll_event(); epoll_ctl(epollfd, 2, fd, ref evt); } sockmap = epollsockets; } if (sockmap != null) { lock (sockmap) sockmap.Remove(fd); } close(fd); } }
public void Initialize(IScreenInfoProvider info, Action <RawInputEventArgs> onInput) { _onInput = onInput; _epoll = epoll_create1(0); for (var c = 0; c < _deviceDescriptions.Length; c++) { var description = _deviceDescriptions[c]; var dev = EvDevDevice.Open(description.Path); EvDevDeviceHandler handler; if (description is EvDevTouchScreenDeviceDescription touch) { handler = new EvDevSingleTouchScreen(dev, touch, info) { InputRoot = _inputRoot } } ; else { throw new Exception("Unknown device description type " + description.GetType().FullName); } handler.OnEvent += OnRawEvent; _handlers.Add(handler); var ev = new epoll_event { events = EPOLLIN, data = { u32 = (uint)c } }; epoll_ctl(_epoll, EPOLL_CTL_ADD, dev.Fd, ref ev); } new Thread(InputThread) { IsBackground = true }.Start(); }
extern static int epoll_ctl(int epfd, int op, int fd, ref epoll_event __event);
public void sleep(std::chrono.nanoseconds duration) { Debug.Assert(dispatcher != null); Debug.Assert(context == null); if (dispatcher.interrupted()) { throw InterruptedException(); } if (duration.count() == 0) { dispatcher.yield(); } else { timer = dispatcher.getTimer(); var seconds = std::chrono.duration_cast <std::chrono.seconds>(duration); itimerspec expires = new itimerspec(); expires.it_interval.tv_nsec = expires.it_interval.tv_sec = 0; expires.it_value.tv_sec = seconds.count(); expires.it_value.tv_nsec = std::chrono.duration_cast <std::chrono.nanoseconds>(duration - seconds).count(); timerfd_settime(timer, 0, expires, null); ContextPair contextPair = new ContextPair(); OperationContext timerContext = new OperationContext(); timerContext.interrupted = false; timerContext.context = dispatcher.getCurrentContext(); contextPair.writeContext = null; contextPair.readContext = timerContext; epoll_event timerEvent = new epoll_event(); timerEvent.events = EPOLLIN | EPOLLONESHOT; timerEvent.data.ptr = contextPair; if (epoll_ctl(dispatcher.getEpoll(), EPOLL_CTL_MOD, timer, timerEvent) == -1) { throw new System.Exception("Timer::sleep, epoll_ctl failed, " + lastErrorMessage()); } dispatcher.getCurrentContext().interruptProcedure = () => { Debug.Assert(dispatcher != null); Debug.Assert(context != null); OperationContext timerContext = (OperationContext)context; if (!timerContext.interrupted) { uint64_t value = 0; if (global::read(timer, value, sizeof(uint64_t)) == -1) { //C++ TO C# CONVERTER TODO TASK: There is no equivalent to most C++ 'pragma' directives in C#: //#pragma GCC diagnostic push //C++ TO C# CONVERTER TODO TASK: There is no equivalent to most C++ 'pragma' directives in C#: //#pragma GCC diagnostic ignored "-Wlogical-op" if (errno == EAGAIN || errno == EWOULDBLOCK) { //C++ TO C# CONVERTER TODO TASK: There is no equivalent to most C++ 'pragma' directives in C#: //#pragma GCC diagnostic pop timerContext.interrupted = true; dispatcher.pushContext(timerContext.context); } else { throw new System.Exception("Timer::sleep, interrupt procedure, read failed, " + lastErrorMessage()); } } else { Debug.Assert(value > 0); dispatcher.pushContext(timerContext.context); } epoll_event timerEvent = new epoll_event(); timerEvent.events = EPOLLONESHOT; timerEvent.data.ptr = null; if (epoll_ctl(dispatcher.getEpoll(), EPOLL_CTL_MOD, timer, timerEvent) == -1) { throw new System.Exception("Timer::sleep, interrupt procedure, epoll_ctl failed, " + lastErrorMessage()); } } }; context = timerContext; dispatcher.dispatch(); dispatcher.getCurrentContext().interruptProcedure = null; Debug.Assert(dispatcher != null); Debug.Assert(timerContext.context == dispatcher.getCurrentContext()); Debug.Assert(contextPair.writeContext == null); Debug.Assert(context == &timerContext); context = null; timerContext.context = null; dispatcher.pushTimer(timer); if (timerContext.interrupted) { throw InterruptedException(); } } }
static void EpollLoop() { epoll_event[] events = new epoll_event[8]; try { Dictionary <int, LinuxSocket> sockmap = epollsockets; if (sockmap == null) { return; } while (true) { int ret = epoll_wait(epollfd, events, events.Length, 1000); if (ret == -1 && Marshal.GetLastWin32Error() == 4) { continue; //Interrupted by signal } if (ret == -1) { throw new PosixException("epoll_wait"); } for (int i = 0; i < ret; i++) { Interlocked.Decrement(ref epollfds); LinuxSocket sock; lock (sockmap) if (!sockmap.TryGetValue((int)events[i].Data, out sock)) { sock = null; } UInt32 evt = events[i].Events; if (sock != null) { sock.EpollEvent((evt & 0x001) != 0, (evt & 0x004) != 0, (evt & 0x008) != 0, (evt & 0x010) != 0); } } if (sockmap.Count == 0) { lock (typeof(LinuxSocket)) { if (sockmap.Count != 0) { continue; } close(epollfd); epollfd = -1; epollthread = null; epollsockets = null; break; } } } } catch { lock (typeof(LinuxSocket)) { if (epollfd != -1) { close(epollfd); } epollfd = -1; epollthread = null; epollsockets = null; } throw; } }
static extern int epoll_ctl(int epfd, int op, int fd, [In] ref epoll_event @event);
private static extern int epoll_ctl(int epfd, int op, int fd, ref epoll_event __event);
public static extern unsafe int epoll_ctl(int epfd, int op, int fd, epoll_event* @event);
public TcpConnection connect(Ipv4Address address, uint16_t port) { Debug.Assert(dispatcher != null); Debug.Assert(context == null); if (dispatcher.interrupted()) { throw InterruptedException(); } string message; int connection = global::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (connection == -1) { message = "socket failed, " + lastErrorMessage(); } else { sockaddr_in bindAddress = new sockaddr_in(); bindAddress.sin_family = AF_INET; bindAddress.sin_port = 0; bindAddress.sin_addr.s_addr = INADDR_ANY; //C++ TO C# CONVERTER TODO TASK: There is no equivalent to 'reinterpret_cast' in C#: if (bind(connection, reinterpret_cast <sockaddr>(bindAddress), sizeof(sockaddr_in)) != 0) { message = "bind failed, " + lastErrorMessage(); } else { int flags = fcntl(connection, F_GETFL, 0); if (flags == -1 || fcntl(connection, F_SETFL, flags | O_NONBLOCK) == -1) { message = "fcntl failed, " + lastErrorMessage(); } else { sockaddr_in addressData = new sockaddr_in(); addressData.sin_family = AF_INET; addressData.sin_port = htons(port); addressData.sin_addr.s_addr = htonl(address.getValue()); //C++ TO C# CONVERTER TODO TASK: There is no equivalent to 'reinterpret_cast' in C#: int result = global::connect(connection, reinterpret_cast <sockaddr>(addressData), sizeof(sockaddr_in)); if (result == -1) { if (errno == EINPROGRESS) { ContextPair contextPair = new ContextPair(); TcpConnectorContextExt connectorContext = new TcpConnectorContextExt(); connectorContext.interrupted = false; connectorContext.context = dispatcher.getCurrentContext(); connectorContext.connection = connection; contextPair.readContext = null; contextPair.writeContext = connectorContext; epoll_event connectEvent = new epoll_event(); connectEvent.events = EPOLLOUT | EPOLLRDHUP | EPOLLERR | EPOLLONESHOT; connectEvent.data.ptr = contextPair; if (epoll_ctl(dispatcher.getEpoll(), EPOLL_CTL_ADD, connection, connectEvent) == -1) { message = "epoll_ctl failed, " + lastErrorMessage(); } else { context = connectorContext; dispatcher.getCurrentContext().interruptProcedure = () => { TcpConnectorContextExt connectorContext1 = (TcpConnectorContextExt)context; if (!connectorContext1.interrupted) { if (close(connectorContext1.connection) == -1) { throw new System.Exception("TcpListener::stop, close failed, " + lastErrorMessage()); } connectorContext1.interrupted = true; dispatcher.pushContext(connectorContext1.context); } }; dispatcher.dispatch(); dispatcher.getCurrentContext().interruptProcedure = null; Debug.Assert(dispatcher != null); Debug.Assert(connectorContext.context == dispatcher.getCurrentContext()); Debug.Assert(contextPair.readContext == null); Debug.Assert(context == connectorContext); context = null; connectorContext.context = null; if (connectorContext.interrupted) { throw InterruptedException(); } if (epoll_ctl(dispatcher.getEpoll(), EPOLL_CTL_DEL, connection, null) == -1) { message = "epoll_ctl failed, " + lastErrorMessage(); } else { if ((connectorContext.events & (EPOLLERR | EPOLLHUP)) != 0) { int result = close(connection); if (result != 0) { } Debug.Assert(result != -1); throw new System.Exception("TcpConnector::connect, connection failed"); } int retval = -1; socklen_t retValLen = sizeof(int); int s = getsockopt(connection, SOL_SOCKET, SO_ERROR, retval, retValLen); if (s == -1) { message = "getsockopt failed, " + lastErrorMessage(); } else { if (retval != 0) { message = "getsockopt failed, " + lastErrorMessage(); } else { return(new TcpConnection(dispatcher, connection)); } } } } } } else { return(new TcpConnection(dispatcher, connection)); } } } int result = close(connection); if (result != 0) { } Debug.Assert(result != -1); } throw new System.Exception("TcpConnector::connect, " + message); }
internal static extern int epoll_wait(int epfd, out epoll_event events, int maxevents, int timeout);
public TcpListener(Dispatcher dispatcher, Ipv4Address addr, uint16_t port) { this.dispatcher = dispatcher; string message; listener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listener == -1) { message = "socket failed, " + lastErrorMessage(); } else { int flags = fcntl(listener, F_GETFL, 0); if (flags == -1 || fcntl(listener, F_SETFL, flags | O_NONBLOCK) == -1) { message = "fcntl failed, " + lastErrorMessage(); } else { int on = 1; if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, on, sizeof(int)) == -1) { message = "setsockopt failed, " + lastErrorMessage(); } else { sockaddr_in address = new sockaddr_in(); address.sin_family = AF_INET; address.sin_port = htons(port); address.sin_addr.s_addr = htonl(addr.getValue()); //C++ TO C# CONVERTER TODO TASK: There is no equivalent to 'reinterpret_cast' in C#: if (bind(listener, reinterpret_cast <sockaddr>(address), sizeof(sockaddr_in)) != 0) { message = "bind failed, " + lastErrorMessage(); } else if (listen(listener, SOMAXCONN) != 0) { message = "listen failed, " + lastErrorMessage(); } else { epoll_event listenEvent = new epoll_event(); listenEvent.events = EPOLLONESHOT; listenEvent.data.ptr = null; if (epoll_ctl(dispatcher.getEpoll(), EPOLL_CTL_ADD, listener, listenEvent) == -1) { message = "epoll_ctl failed, " + lastErrorMessage(); } else { context = null; return; } } } } int result = close(listener); if (result != 0) { } Debug.Assert(result != -1); } throw new System.Exception("TcpListener::TcpListener, " + message); }
public Dispatcher() { string message; epoll = global::epoll_create1(0); if (epoll == -1) { message = "epoll_create1 failed, " + lastErrorMessage(); } else { mainContext.ucontext = new ucontext_t(); //C++ TO C# CONVERTER TODO TASK: There is no equivalent to 'reinterpret_cast' in C#: if (getcontext(reinterpret_cast <ucontext_t>(mainContext.ucontext)) == -1) { message = "getcontext failed, " + lastErrorMessage(); } else { remoteSpawnEvent = eventfd(0, O_NONBLOCK); if (remoteSpawnEvent == -1) { message = "eventfd failed, " + lastErrorMessage(); } else { remoteSpawnEventContext.writeContext = null; remoteSpawnEventContext.readContext = null; epoll_event remoteSpawnEventEpollEvent = new epoll_event(); remoteSpawnEventEpollEvent.events = EPOLLIN; remoteSpawnEventEpollEvent.data.ptr = remoteSpawnEventContext; if (epoll_ctl(epoll, EPOLL_CTL_ADD, remoteSpawnEvent, remoteSpawnEventEpollEvent) == -1) { message = "epoll_ctl failed, " + lastErrorMessage(); } else { //C++ TO C# CONVERTER TODO TASK: There is no equivalent to 'reinterpret_cast' in C#: *reinterpret_cast <pthread_mutex_t>(this.mutex) = pthread_mutex_t(PTHREAD_MUTEX_INITIALIZER); mainContext.interrupted = false; mainContext.group = contextGroup; mainContext.groupPrev = null; mainContext.groupNext = null; mainContext.inExecutionQueue = false; contextGroup.firstContext = null; contextGroup.lastContext = null; contextGroup.firstWaiter = null; contextGroup.lastWaiter = null; currentContext = mainContext; firstResumingContext = null; firstReusableContext = null; runningContextCount = 0; return; } var result = close(remoteSpawnEvent); if (result) { } Debug.Assert(result == 0); } } var result = close(epoll); if (result) { } Debug.Assert(result == 0); } throw new System.Exception("Dispatcher::Dispatcher, " + message); }
internal static unsafe void Run(int portNumber, bool executeOnEpollThread) { int socketFileDescriptor = socket(AF_INET, SOCK_STREAM, 0); if (socketFileDescriptor < 0) { Environment.FailFast($"Failed to create socket, socket returned {socketFileDescriptor}"); } sockaddr_in socketAddress = new sockaddr_in { sin_family = AF_INET, sin_port = htons((ushort)portNumber), sin_addr = INADDR_ANY }; int bindResult = bind(socketFileDescriptor, (sockaddr *)&socketAddress, sizeof(sockaddr_in)); if (bindResult < 0) { Environment.FailFast($"Failed to bind, bind returned {bindResult}"); } int listenResult = listen(socketFileDescriptor, BACKLOG); if (listenResult < 0) { Environment.FailFast($"Failed to start listening, listen returned {listenResult}"); } int epollFileDescriptor = epoll_create(MAX_EVENTS); if (epollFileDescriptor < 0) { Environment.FailFast($"Failed to create epoll, epoll_create returned {epollFileDescriptor}"); } epoll_event epollAddSocketEvent = new epoll_event { events = EPOLLIN, data = new epoll_data_t { fd = socketFileDescriptor } }; if (epoll_ctl(epollFileDescriptor, EPOLL_CTL_ADD, socketFileDescriptor, &epollAddSocketEvent) == -1) { Environment.FailFast("Failed to add new socket file descriptor to epoll"); } epoll_event[] epollEvents = new epoll_event[MAX_EVENTS]; byte[] messageBuffer = new byte[MAX_MESSAGE_LENGTH]; fixed(epoll_event *pinnedEvents = epollEvents) fixed(byte *pinnedMessageBuffer = messageBuffer) { while (true) { int eventsCount = epoll_wait(epollFileDescriptor, pinnedEvents, MAX_EVENTS, -1); if (eventsCount == -1) { Environment.FailFast("epoll_wait returned -1"); } for (int i = 0; i < eventsCount; i++) { int currentSocketFileDescriptor = epollEvents[i].data.fd; if (currentSocketFileDescriptor == socketFileDescriptor) { sockaddr_in clientAddress; socklen_t clientAddressSize = sizeof(sockaddr_in); int acceptResult = accept4(socketFileDescriptor, (sockaddr *)&clientAddress, &clientAddressSize, SOCK_NONBLOCK); if (acceptResult == -1) { Environment.FailFast($"accept4 returned {acceptResult}"); } epollAddSocketEvent.events = EPOLLIN | EPOLLET; epollAddSocketEvent.data.fd = acceptResult; if (epoll_ctl(epollFileDescriptor, EPOLL_CTL_ADD, acceptResult, &epollAddSocketEvent) == -1) { Environment.FailFast("Failed to add socket to epoll"); } } else if (executeOnEpollThread) { ssize_t bytesRead = recv(currentSocketFileDescriptor, pinnedMessageBuffer, MAX_MESSAGE_LENGTH, 0); send(currentSocketFileDescriptor, pinnedMessageBuffer, (size_t)bytesRead, 0); } else { ThreadPool.UnsafeQueueUserWorkItem <int>(Copy, currentSocketFileDescriptor, false); } } } } }
public static extern unsafe int epoll_wait(int epfd, epoll_event* events, int maxevents, int timeout);
internal static extern int epoll_ctl(int epfd, PollOperations op, int fd, ref epoll_event events);
public TcpConnection accept() { Debug.Assert(dispatcher != null); Debug.Assert(context == null); if (dispatcher.interrupted()) { throw InterruptedException(); } ContextPair contextPair = new ContextPair(); OperationContext listenerContext = new OperationContext(); listenerContext.interrupted = false; listenerContext.context = dispatcher.getCurrentContext(); contextPair.writeContext = null; contextPair.readContext = listenerContext; epoll_event listenEvent = new epoll_event(); listenEvent.events = EPOLLIN | EPOLLONESHOT; listenEvent.data.ptr = contextPair; string message; if (epoll_ctl(dispatcher.getEpoll(), EPOLL_CTL_MOD, listener, listenEvent) == -1) { message = "epoll_ctl failed, " + lastErrorMessage(); } else { context = listenerContext; dispatcher.getCurrentContext().interruptProcedure = () => { Debug.Assert(dispatcher != null); Debug.Assert(context != null); OperationContext listenerContext = (OperationContext)context; if (!listenerContext.interrupted) { epoll_event listenEvent = new epoll_event(); listenEvent.events = EPOLLONESHOT; listenEvent.data.ptr = null; if (epoll_ctl(dispatcher.getEpoll(), EPOLL_CTL_MOD, listener, listenEvent) == -1) { throw new System.Exception("TcpListener::accept, interrupt procedure, epoll_ctl failed, " + lastErrorMessage()); } listenerContext.interrupted = true; dispatcher.pushContext(listenerContext.context); } }; dispatcher.dispatch(); dispatcher.getCurrentContext().interruptProcedure = null; Debug.Assert(dispatcher != null); Debug.Assert(listenerContext.context == dispatcher.getCurrentContext()); Debug.Assert(contextPair.writeContext == null); Debug.Assert(context == &listenerContext); context = null; listenerContext.context = null; if (listenerContext.interrupted) { throw InterruptedException(); } if ((listenerContext.events & (EPOLLERR | EPOLLHUP)) != 0) { throw new System.Exception("TcpListener::accept, accepting failed"); } sockaddr inAddr = new sockaddr(); socklen_t inLen = sizeof(sockaddr); int connection = global::accept(listener, inAddr, inLen); if (connection == -1) { message = "accept failed, " + lastErrorMessage(); } else { int flags = fcntl(connection, F_GETFL, 0); if (flags == -1 || fcntl(connection, F_SETFL, flags | O_NONBLOCK) == -1) { message = "fcntl failed, " + lastErrorMessage(); } else { return(new TcpConnection(dispatcher, connection)); } int result = close(connection); if (result != 0) { } Debug.Assert(result != -1); } } throw new System.Exception("TcpListener::accept, " + message); }