private static bool TranslateToLinuxFd(Thread current, PollCompletion poll_entry, ByteBufferRef b) { Contract.Requires(b.Length >= poll_entry.fdMaps.Length * pollfd.Size); var proc = current.Parent; var nfds = poll_entry.fdMaps.Length; for (var i = 0; i < nfds; ++i) { Contract.Assert(i < nfds && nfds * pollfd.Size <= b.Length); Contract.Assert(i + 1 <= nfds && (i + 1) * pollfd.Size <= nfds * pollfd.Size); Contract.Assert((i + 1) * pollfd.Size <= nfds * pollfd.Size && nfds * pollfd.Size <= b.Length); var poll_struct = pollfd.Deserialize(b, i * pollfd.Size); var file = proc.LookupFile(poll_struct.fd); if (file == null) { return(false); } // DEBUG if (file.inode.LinuxFd < 0) { Arch.Console.Write("Poll: transalte fd linux fd < 0 for fd="); Arch.Console.Write(poll_struct.fd); Arch.Console.Write(" kind="); Arch.Console.Write((int)file.inode.kind); Arch.Console.WriteLine(); } poll_entry.fdMaps[i] = poll_struct.fd; poll_struct.fd = file.inode.LinuxFd; poll_struct.Write(b, i * pollfd.Size); } return(true); }
public const int SYS_SENDMMSG = 20; /* sys_sendmmsg(2) */ public static int Poll(Thread current, ref Arch.ExceptionRegisters regs, UserPtr fds, int nfds, int timeout) { if (nfds < 0) { return(-ErrorCode.EINVAL); } var pollfd_size = pollfd.Size * nfds; var buf = Globals.AllocateAlignedCompletionBuffer(pollfd_size); if (!buf.isValid) { return(-ErrorCode.ENOMEM); } var poll_entry = new PollCompletion(current, fds, nfds, buf); if (fds.Read(current, buf, pollfd_size) != 0) { poll_entry.Dispose(); return(-ErrorCode.EFAULT); } Contract.Assert(buf.Length >= pollfd_size); if (!TranslateToLinuxFd(current, poll_entry, buf)) { poll_entry.Dispose(); return(-ErrorCode.EBADF); } var ret = Arch.IPCStubs.PollAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), nfds, timeout); if (ret < 0) { poll_entry.Dispose(); return(ret); } Globals.CompletionQueue.Enqueue(poll_entry); current.SaveState(ref regs); current.AsyncReturn = true; return(0); }
public static void HandlePollAsync(PollCompletion entry, int ret) { var current = entry.thr; var proc = current.Parent; if (ret <= 0) { entry.Dispose(); current.ReturnFromCompletion(ret); return; } var b = entry.buf; if (b.Length < ret * pollfd.Size) { ret = -ErrorCode.ENOMEM; entry.Dispose(); current.ReturnFromCompletion(ret); Utils.Panic(); return; } // Translate fds back into fd in ExpressOS for (var i = 0; i < ret; ++i) { Contract.Assert(i < ret && ret * pollfd.Size <= b.Length); Contract.Assert(i + 1 <= ret && (i + 1) * pollfd.Size <= ret * pollfd.Size); Contract.Assert((i + 1) * pollfd.Size <= ret * pollfd.Size && ret * pollfd.Size <= b.Length); var poll_struct = pollfd.Deserialize(b, i * pollfd.Size); var expressos_fd = -1; for (var j = 0; j < entry.fdMaps.Length; ++j) { var file = proc.LookupFile(entry.fdMaps[j]); if (file == null) { continue; } if (file.inode.LinuxFd == poll_struct.fd) { expressos_fd = entry.fdMaps[j]; break; } } if (expressos_fd == -1) { // DEBUG Arch.Console.Write("poll_async: cannot find ExpressOS fd for fd "); Arch.Console.Write(poll_struct.fd); Arch.Console.Write(" i="); Arch.Console.Write(i); Arch.Console.Write(" poll_ret="); Arch.Console.Write(ret); Arch.Console.Write(" nfds="); Arch.Console.Write(entry.fdMaps.Length); Arch.Console.WriteLine(); ret = -ErrorCode.EBADF; break; } // Write result back var p_user_entry = entry.userFdBuf + i * pollfd.Size; p_user_entry.Write(current, expressos_fd); (p_user_entry + pollfd.OFFSET_OF_REVENTS).Write(current, poll_struct.revents); } entry.Dispose(); current.ReturnFromCompletion(ret); }
public static void HandlePollAsync(PollCompletion entry, int ret) { var current = entry.thr; var proc = current.Parent; if (ret <= 0) { entry.Dispose(); current.ReturnFromCompletion(ret); return; } var b = entry.buf; if (b.Length < ret * pollfd.Size) { ret = -ErrorCode.ENOMEM; entry.Dispose(); current.ReturnFromCompletion(ret); Utils.Panic(); return; } // Translate fds back into fd in ExpressOS for (var i = 0; i < ret; ++i) { Contract.Assert(i < ret && ret * pollfd.Size <= b.Length); Contract.Assert(i + 1 <= ret && (i + 1) * pollfd.Size <= ret * pollfd.Size); Contract.Assert((i + 1) * pollfd.Size <= ret * pollfd.Size && ret * pollfd.Size <= b.Length); var poll_struct = pollfd.Deserialize(b, i * pollfd.Size); var expressos_fd = -1; for (var j = 0; j < entry.fdMaps.Length; ++j) { var file = proc.LookupFile(entry.fdMaps[j]); if (file == null) continue; if (file.inode.LinuxFd == poll_struct.fd) { expressos_fd = entry.fdMaps[j]; break; } } if (expressos_fd == -1) { // DEBUG Arch.Console.Write("poll_async: cannot find ExpressOS fd for fd "); Arch.Console.Write(poll_struct.fd); Arch.Console.Write(" i="); Arch.Console.Write(i); Arch.Console.Write(" poll_ret="); Arch.Console.Write(ret); Arch.Console.Write(" nfds="); Arch.Console.Write(entry.fdMaps.Length); Arch.Console.WriteLine(); ret = -ErrorCode.EBADF; break; } // Write result back var p_user_entry = entry.userFdBuf + i * pollfd.Size; p_user_entry.Write(current, expressos_fd); (p_user_entry + pollfd.OFFSET_OF_REVENTS).Write(current, poll_struct.revents); } entry.Dispose(); current.ReturnFromCompletion(ret); }
private static bool TranslateToLinuxFd(Thread current, PollCompletion poll_entry, ByteBufferRef b) { Contract.Requires(b.Length >= poll_entry.fdMaps.Length * pollfd.Size); var proc = current.Parent; var nfds = poll_entry.fdMaps.Length; for (var i = 0; i < nfds; ++i) { Contract.Assert(i < nfds && nfds * pollfd.Size <= b.Length); Contract.Assert(i + 1 <= nfds && (i + 1) * pollfd.Size <= nfds * pollfd.Size); Contract.Assert((i + 1) * pollfd.Size <= nfds * pollfd.Size && nfds * pollfd.Size <= b.Length); var poll_struct = pollfd.Deserialize(b, i * pollfd.Size); var file = proc.LookupFile(poll_struct.fd); if (file == null) return false; // DEBUG if (file.inode.LinuxFd < 0) { Arch.Console.Write("Poll: transalte fd linux fd < 0 for fd="); Arch.Console.Write(poll_struct.fd); Arch.Console.Write(" kind="); Arch.Console.Write((int)file.inode.kind); Arch.Console.WriteLine(); } poll_entry.fdMaps[i] = poll_struct.fd; poll_struct.fd = file.inode.LinuxFd; poll_struct.Write(b, i * pollfd.Size); } return true; }
public static int Poll(Thread current, ref Arch.ExceptionRegisters regs, UserPtr fds, int nfds, int timeout) { if (nfds < 0) return -ErrorCode.EINVAL; var pollfd_size = pollfd.Size * nfds; var buf = Globals.AllocateAlignedCompletionBuffer(pollfd_size); if (!buf.isValid) return -ErrorCode.ENOMEM; var poll_entry = new PollCompletion(current, fds, nfds, buf); if (fds.Read(current, buf, pollfd_size) != 0) { poll_entry.Dispose(); return -ErrorCode.EFAULT; } Contract.Assert(buf.Length >= pollfd_size); if (!TranslateToLinuxFd(current, poll_entry, buf)) { poll_entry.Dispose(); return -ErrorCode.EBADF; } var ret = Arch.IPCStubs.PollAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), nfds, timeout); if (ret < 0) { poll_entry.Dispose(); return ret; } Globals.CompletionQueue.Enqueue(poll_entry); current.SaveState(ref regs); current.AsyncReturn = true; return 0; }