Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #3
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);
        }
Example #4
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);
        }
Example #5
0
        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;
        }
Example #6
0
        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;
        }