private void PollWrite(IoUringConnectionContext context) { var socket = context.Socket; Debug.WriteLine($"Adding write poll on {(int)socket}"); _ring.PreparePollAdd(socket, (ushort)POLLOUT, Mask(socket, WritePollMask)); }
private void PollRead(IoUringConnectionContext context) { var socket = context.Socket; Debug.WriteLine($"Adding read poll on {(int)socket}"); _ring.PreparePollAdd(socket, (ushort)POLLIN, Mask(socket, ReadPollMask)); }
private void ReadFromApp(IoUringConnectionContext context) { var readResult = context.Output.ReadAsync(); context.ReadResult = readResult; if (readResult.IsCompleted) { Debug.WriteLine($"Read from app for {(int)context.Socket} synchronously"); context.ReadFromAppSynchronously(); PollWrite(context); } else { readResult.GetAwaiter().UnsafeOnCompleted(context.OnReadFromApp); } }
private void FlushRead(IoUringConnectionContext context) { var flushResult = context.Input.FlushAsync(); context.FlushResult = flushResult; if (flushResult.IsCompleted) { Debug.WriteLine($"Flushed read from {(int)context.Socket} synchronously"); context.FlushedToAppSynchronously(); PollRead(context); } else { flushResult.GetAwaiter().UnsafeOnCompleted(context.OnFlushedToApp); } }
private void CompleteWritePoll(IoUringConnectionContext context, int result) { if (result < 0) { if (-result != EAGAIN || -result != EINTR) { throw new ErrnoException(-result); } Debug.WriteLine("Polled write for nothing"); PollWrite(context); return; } Debug.WriteLine($"Completed write poll on {(int)context.Socket}"); Write(context); }
private void CompleteRead(IoUringConnectionContext context, int result) { if (result > 0) { Debug.WriteLine($"Read {result} bytes from {(int)context.Socket}"); context.Input.Advance(result); FlushRead(context); } else if (result < 0) { if (-result != EAGAIN || -result != EWOULDBLOCK || -result != EINTR) { throw new ErrnoException(-result); } Debug.WriteLine("Read for nothing"); } }
private void CompleteWrite(IoUringConnectionContext context, int result) { try { if (result > 0) { var lastWrite = context.LastWrite; SequencePosition end; if (lastWrite.Length == result) { Debug.WriteLine($"Wrote all {result} bytes to {(int)context.Socket}"); end = lastWrite.End; } else { Debug.WriteLine($"Wrote some {result} bytes to {(int)context.Socket}"); end = lastWrite.GetPosition(result); } context.Output.AdvanceTo(end); ReadFromApp(context); } else if (result < 0) { if (-result != EAGAIN && -result != EWOULDBLOCK && -result != EINTR) { throw new ErrnoException(-result); } Debug.WriteLine("Wrote for nothing"); } } finally { var writeHandles = context.WriteHandles; for (int i = 0; i < writeHandles.Length; i++) { writeHandles[i].Dispose(); } } }
private unsafe void Read(IoUringConnectionContext context) { var maxBufferSize = _memoryPool.MaxBufferSize; var writer = context.Input; var readHandles = context.ReadHandles; var readVecs = context.ReadVecs; var memory = writer.GetMemory(maxBufferSize); var handle = memory.Pin(); readVecs[0].iov_base = handle.Pointer; readVecs[0].iov_len = memory.Length; readHandles[0] = handle; var socket = context.Socket; Debug.WriteLine($"Adding read on {(int)socket}"); _ring.PrepareReadV(socket, readVecs, 1, 0, 0, Mask(socket, ReadMask)); }
private unsafe void Write(IoUringConnectionContext context) { var result = context.ReadResult.Result; var socket = context.Socket; if (result.IsCanceled || result.IsCompleted) { context.DisposeAsync(); _connections.Remove(socket); socket.Close(); } var writeHandles = context.WriteHandles; var writeVecs = context.WriteVecs; var buffer = result.Buffer; int ctr = 0; foreach (var memory in buffer) { var handle = memory.Pin(); writeVecs[ctr].iov_base = handle.Pointer; writeVecs[ctr].iov_len = memory.Length; writeHandles[ctr] = handle; ctr++; if (ctr == IoUringConnectionContext.WriteIOVecCount) { break; } } context.LastWrite = buffer; Debug.WriteLine($"Adding write on {(int)socket}"); _ring.PrepareWriteV(socket, writeVecs, ctr, 0, 0, Mask(socket, WriteMask)); }
private void CompleteAcceptPoll() { var socket = _acceptSocket.Accept(out var endPoint); if (socket == -1) { Debug.WriteLine("Polled accept for nothing"); goto AcceptAgain; } Debug.WriteLine($"Accepted {(int)socket}"); // TODO: move server endpoint and memory pool to thread context IoUringConnectionContext context = new IoUringConnectionContext(socket, _endPoint, endPoint, _memoryPool, _threadContext); _connections[socket] = context; _acceptQueue.TryWrite(context); PollRead(context); ReadFromApp(context); AcceptAgain: Accept(); }