public static int Access(Thread current, ref Arch.ExceptionRegisters regs, UserPtr filenamePtr, int mode)
        {
            // XXX: This is vfs related, now let's assume that we're dealing with pass through fs.

            var buf = Globals.AllocateAlignedCompletionBuffer(PATH_MAX);

            if (!buf.isValid)
            {
                return(-ErrorCode.ENOMEM);
            }

            var ret = filenamePtr.ReadString(current, buf);

            var accessCompletion = new BridgeCompletion(current, buf);

            ret = Arch.IPCStubs.AccessAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), mode);

            if (ret < 0)
            {
                accessCompletion.Dispose();
                return(ret);
            }

            Globals.CompletionQueue.Enqueue(accessCompletion);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return(0);
        }
Exemple #2
0
        private static int Recv(Thread current, ref Arch.ExceptionRegisters regs, UserPtr ptr_label, UserPtr userBuf, uint size)
        {
            Contract.Requires(current.VBinderState.Owner == current);

            if (!current.Parent.Space.VerifyWrite(userBuf, size) || !current.Parent.Space.VerifyWrite(ptr_label, sizeof(int)))
            {
                return(-ErrorCode.EFAULT);
            }

            var b = current.VBinderState.NoPendingMessages();

            if (b)
            {
                var entry = new VBinderCompletion(current, ptr_label, userBuf, size);
                current.VBinderState.Completion = entry;

                current.SaveState(ref regs);
                current.AsyncReturn = true;
                return(0);
            }
            else
            {
                var msg = current.VBinderState.TakeMessage();

                Contract.Assert(msg.GhostTarget == current);

                var length = msg.Length;
                ptr_label.Write(current.Parent, msg.label);
                userBuf.Write(current, new Pointer(msg.payload.Location), length);
                msg.Recycle();
                return(length);
            }
        }
        public static int Access(Thread current, ref Arch.ExceptionRegisters regs, UserPtr filenamePtr, int mode)
        {
            // XXX: This is vfs related, now let's assume that we're dealing with pass through fs.

            var buf = Globals.AllocateAlignedCompletionBuffer(PATH_MAX);

            if (!buf.isValid)
                return -ErrorCode.ENOMEM;

            var ret = filenamePtr.ReadString(current, buf);

            var accessCompletion = new BridgeCompletion(current, buf);

            ret = Arch.IPCStubs.AccessAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), mode);

            if (ret < 0)
            {
                accessCompletion.Dispose();
                return ret;
            }

            Globals.CompletionQueue.Enqueue(accessCompletion);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return 0;
        }
Exemple #4
0
        private static int Socket(Thread current, ref Arch.ExceptionRegisters regs, int domain, int type, int protocol)
        {
            var proc = current.Parent;

            Arch.IPCStubs.SocketAsync(proc.helperPid, current.impl._value.thread._value, domain, type, protocol);

            var completion = new SocketCompletion(current);

            Globals.CompletionQueue.Enqueue(completion);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return(0);
        }
Exemple #5
0
        private static int BindOrConnect(int type, Thread current, ref Arch.ExceptionRegisters regs, int sockfd, UserPtr sockaddr, int addrlen)
        {
            Contract.Requires(type == SYS_BIND || type == SYS_CONNECT);

            var proc = current.Parent;
            var file = proc.LookupFile(sockfd);

            if (file == null)
            {
                return(-ErrorCode.EBADF);
            }

            if (file.inode.kind != GenericINode.INodeKind.SocketINodeKind)
            {
                return(-ErrorCode.ENOTSOCK);
            }

            if (addrlen > Globals.LinuxIPCBuffer.Length)
            {
                return(-ErrorCode.EINVAL);
            }

            var buf = Globals.AllocateAlignedCompletionBuffer(addrlen);

            if (!buf.isValid)
            {
                return(-ErrorCode.ENOMEM);
            }

            var completion = new BridgeCompletion(current, buf);

            if (sockaddr.Read(current, buf, addrlen) != 0)
            {
                completion.Dispose();
                return(-ErrorCode.EFAULT);
            }

            if (type == SYS_BIND)
            {
                Arch.IPCStubs.BindAsync(proc.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), file.inode.LinuxFd, addrlen);
            }
            else if (type == SYS_CONNECT)
            {
                Arch.IPCStubs.ConnectAsync(proc.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), file.inode.LinuxFd, addrlen);
            }

            Globals.CompletionQueue.Enqueue(completion);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return(0);
        }
Exemple #6
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);
        }
Exemple #7
0
        private static int Getsockopt(Thread current, ref Arch.ExceptionRegisters regs, int sockfd, int level, int optname, UserPtr optval, UserPtr p_optlen)
        {
            var proc = current.Parent;
            var file = proc.LookupFile(sockfd);

            if (file == null)
            {
                return(-ErrorCode.EBADF);
            }

            if (file.inode.kind != GenericINode.INodeKind.SocketINodeKind)
            {
                return(-ErrorCode.ENOTSOCK);
            }

            uint optlen = 0;

            if (p_optlen.Read(current, out optlen) != 0)
            {
                return(-ErrorCode.EFAULT);
            }

            if (optlen > Globals.LinuxIPCBuffer.Length)
            {
                return(-ErrorCode.EINVAL);
            }

            var buf = Globals.AllocateAlignedCompletionBuffer((int)optlen);

            if (!buf.isValid)
            {
                return(-ErrorCode.ENOMEM);
            }

            var completion = new GetSockParamCompletion(current, optval, p_optlen, buf);

            Arch.IPCStubs.GetSockoptAsync(proc.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), file.inode.LinuxFd, level, optname, (int)optlen);

            Globals.CompletionQueue.Enqueue(completion);
            current.SaveState(ref regs);
            current.AsyncReturn = true;

            return(0);
        }
Exemple #8
0
        public static int Nanosleep(Thread current, ref Arch.ExceptionRegisters regs, UserPtr rqtp, UserPtr rmtp)
        {
            timespec ts;
            timespec trem;

            trem.tv_sec  = 0;
            trem.tv_nsec = 0;

            if (rqtp.Read(current, out ts) != 0 || rmtp.Write(current, ref trem) != 0)
            {
                return(-ErrorCode.EFAULT);
            }

            Globals.TimeoutQueue.Enqueue(ts.ToMilliseconds(), current);
            var c = new SleepCompletion(current);

            Globals.CompletionQueue.Enqueue(c);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return(0);
        }
Exemple #9
0
        private static int Wait(Thread current, ref Arch.ExceptionRegisters regs, UserPtr uaddr, int flags, int val, bool hasTimeout, timespec ts, uint bitset)
        {
            int old_val;

            if (uaddr.Read(current, out old_val) != 0)
            {
                return(-ErrorCode.EFAULT);
            }

            if (old_val != val)
            {
                return(-ErrorCode.EWOULDBLOCK);
            }

            //Arch.Console.Write("wait: addr=");
            //Arch.Console.Write(uaddr.Value.ToUInt32());
            //Arch.Console.Write(" thr=");
            //Arch.Console.Write(current.Tid);
            //Arch.Console.WriteLine();

            TimerQueueNode node;
            var            futex_entry = new FutexCompletionEntry(current, uaddr, bitset);

            Globals.FutexLists.InsertAtTail(futex_entry);

            if (hasTimeout)
            {
                node = Globals.TimeoutQueue.Enqueue(ts.ToMilliseconds(), current);
                futex_entry.timeoutNode = node;
            }

            Globals.CompletionQueue.Enqueue(futex_entry);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return(0);
        }
Exemple #10
0
        private static int Socket(Thread current, ref Arch.ExceptionRegisters regs, int domain, int type, int protocol)
        {
            var proc = current.Parent;
            Arch.IPCStubs.SocketAsync(proc.helperPid, current.impl._value.thread._value, domain, type, protocol);

            var completion = new SocketCompletion(current);

            Globals.CompletionQueue.Enqueue(completion);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return 0;
        }
Exemple #11
0
        public static int Open(Thread current, ref Arch.ExceptionRegisters regs, UserPtr filenamePtr, int flags, int mode)
        {
            // TODO: Deal with current path
            var filenameBuf = new byte[PATH_MAX];
            var ret = filenamePtr.ReadString(current, filenameBuf);

            var proc = current.Parent;
            int fd = 0;
            GenericINode inode = null;

            var startTime = Arch.NativeMethods.l4api_get_system_clock();

            if (Util.ByteStringCompare(filenameBuf, IPCFilename.GetByteString()) == 0)
            {
                fd = proc.GetUnusedFd();
                inode = BinderINode.Instance;
            }
            else if (Util.ByteStringCompare(filenameBuf, AshmemFileName.GetByteString()) == 0)
            {
                var linux_fd = Arch.ArchFS.OpenAndReturnLinuxFd(current.Parent.helperPid, new ASCIIString(filenameBuf), flags, mode);
                if (linux_fd < 0)
                    return linux_fd;

                inode = new AshmemINode(linux_fd, current.Parent.helperPid);
                fd = proc.GetUnusedFd();
            }
            else if (SecureFS.IsSecureFS(current, filenameBuf))
            {
                var completion = SecureFS.OpenAndReadPagesAsync(current, filenameBuf, flags, mode);
                if (completion == null)
                    return -ErrorCode.ENOMEM;

                Globals.CompletionQueue.Enqueue(completion);
                current.SaveState(ref regs);
                current.AsyncReturn = true;
                return 0;
            }
            else
            {
                var filename_len = ret;

                var completion = Arch.ArchFS.OpenAndGetSizeAsync(current, filenameBuf, flags, mode);
                if (completion == null)
                    return -ErrorCode.ENOMEM;

                Globals.CompletionQueue.Enqueue(completion);
                current.SaveState(ref regs);
                current.AsyncReturn = true;
                return 0;
            }

            if (fd > 0)
            {
                var file = new File(proc, inode, flags, mode);
                proc.InstallFd(fd, file);
            }

            if (SyscallProfiler.Enable)
            {
                var endTime = Arch.NativeMethods.l4api_get_system_clock();
                SyscallProfiler.AccountOpen((int)inode.kind, (long)(endTime - startTime));
            }

            return fd;
        }
        public static int Open(Thread current, ref Arch.ExceptionRegisters regs, UserPtr filenamePtr, int flags, int mode)
        {
            // TODO: Deal with current path
            var filenameBuf = new byte[PATH_MAX];
            var ret         = filenamePtr.ReadString(current, filenameBuf);

            var          proc  = current.Parent;
            int          fd    = 0;
            GenericINode inode = null;

            var startTime = Arch.NativeMethods.l4api_get_system_clock();

            if (Util.ByteStringCompare(filenameBuf, IPCFilename.GetByteString()) == 0)
            {
                fd    = proc.GetUnusedFd();
                inode = BinderINode.Instance;
            }
            else if (Util.ByteStringCompare(filenameBuf, AshmemFileName.GetByteString()) == 0)
            {
                var linux_fd = Arch.ArchFS.OpenAndReturnLinuxFd(current.Parent.helperPid, new ASCIIString(filenameBuf), flags, mode);
                if (linux_fd < 0)
                {
                    return(linux_fd);
                }

                inode = new AshmemINode(linux_fd, current.Parent.helperPid);
                fd    = proc.GetUnusedFd();
            }
            else if (SecureFS.IsSecureFS(current, filenameBuf))
            {
                var completion = SecureFS.OpenAndReadPagesAsync(current, filenameBuf, flags, mode);
                if (completion == null)
                {
                    return(-ErrorCode.ENOMEM);
                }

                Globals.CompletionQueue.Enqueue(completion);
                current.SaveState(ref regs);
                current.AsyncReturn = true;
                return(0);
            }
            else
            {
                var filename_len = ret;

                var completion = Arch.ArchFS.OpenAndGetSizeAsync(current, filenameBuf, flags, mode);
                if (completion == null)
                {
                    return(-ErrorCode.ENOMEM);
                }

                Globals.CompletionQueue.Enqueue(completion);
                current.SaveState(ref regs);
                current.AsyncReturn = true;
                return(0);
            }

            if (fd > 0)
            {
                var file = new File(proc, inode, flags, mode);
                proc.InstallFd(fd, file);
            }

            if (SyscallProfiler.Enable)
            {
                var endTime = Arch.NativeMethods.l4api_get_system_clock();
                SyscallProfiler.AccountOpen((int)inode.kind, (long)(endTime - startTime));
            }

            return(fd);
        }
Exemple #13
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;
        }
Exemple #14
0
        public static int Select(Thread current, ref Arch.ExceptionRegisters regs, int maxfds, UserPtr inp, UserPtr outp, UserPtr exp, UserPtr tvp)
        {
            var helper = new SelectHelper();
            int ret = 0;

            ret = helper.AddUserFdList(current, inp, maxfds, POLLIN);
            if (ret < 0)
                return ret;

            ret = helper.AddUserFdList(current, outp, maxfds, POLLOUT);
            if (ret < 0)
                return ret;

            ret = helper.AddUserFdList(current, exp, maxfds, POLLERR);
            if (ret < 0)
                return ret;

            int timeout = 0;
            timeval tv;
            if (tvp == UserPtr.Zero)
            {
                timeout = -1;
            }
            else if (tvp.Read(current, out tv) != 0)
            {
                return -ErrorCode.EFAULT;
            }
            else
            {
                timeout = (int)(tv.tv_sec * 1000 + tv.tv_usec / 1000);
            }

            var nfds = helper.TotalFds;
            var pollfd_size = pollfd.Size * nfds;
            var buf = Globals.AllocateAlignedCompletionBuffer(pollfd_size);
            if (!buf.isValid)
                return -ErrorCode.ENOMEM;

            helper.WritePollFds(buf);

            var select_entry = new SelectCompletion(current, maxfds, inp, outp, exp, helper, buf);
            ret = Arch.IPCStubs.PollAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), nfds, timeout);

            if (ret < 0)
            {
                select_entry.Dispose();
                return ret;
            }

            Globals.CompletionQueue.Enqueue(select_entry);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return 0;
        }
Exemple #15
0
        private static int BindOrConnect(int type, Thread current, ref Arch.ExceptionRegisters regs, int sockfd, UserPtr sockaddr, int addrlen)
        {
            Contract.Requires(type == SYS_BIND || type == SYS_CONNECT);

            var proc = current.Parent;
            var file = proc.LookupFile(sockfd);
            if (file == null)
                return -ErrorCode.EBADF;

            if (file.inode.kind != GenericINode.INodeKind.SocketINodeKind)
                return -ErrorCode.ENOTSOCK;

            if (addrlen > Globals.LinuxIPCBuffer.Length)
                return -ErrorCode.EINVAL;

            var buf = Globals.AllocateAlignedCompletionBuffer(addrlen);

            if (!buf.isValid)
                return -ErrorCode.ENOMEM;

            var completion = new BridgeCompletion(current, buf);

            if (sockaddr.Read(current, buf, addrlen) != 0)
            {
                completion.Dispose();
                return -ErrorCode.EFAULT;
            }

            if (type == SYS_BIND)
            {
                Arch.IPCStubs.BindAsync(proc.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), file.inode.LinuxFd, addrlen);
            }
            else if (type == SYS_CONNECT)
            {
                Arch.IPCStubs.ConnectAsync(proc.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), file.inode.LinuxFd, addrlen);
            }

            Globals.CompletionQueue.Enqueue(completion);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return 0;
        }
Exemple #16
0
        public static int Select(Thread current, ref Arch.ExceptionRegisters regs, int maxfds, UserPtr inp, UserPtr outp, UserPtr exp, UserPtr tvp)
        {
            var helper = new SelectHelper();
            int ret    = 0;

            ret = helper.AddUserFdList(current, inp, maxfds, POLLIN);
            if (ret < 0)
            {
                return(ret);
            }

            ret = helper.AddUserFdList(current, outp, maxfds, POLLOUT);
            if (ret < 0)
            {
                return(ret);
            }

            ret = helper.AddUserFdList(current, exp, maxfds, POLLERR);
            if (ret < 0)
            {
                return(ret);
            }

            int     timeout = 0;
            timeval tv;

            if (tvp == UserPtr.Zero)
            {
                timeout = -1;
            }
            else if (tvp.Read(current, out tv) != 0)
            {
                return(-ErrorCode.EFAULT);
            }
            else
            {
                timeout = (int)(tv.tv_sec * 1000 + tv.tv_usec / 1000);
            }

            var nfds        = helper.TotalFds;
            var pollfd_size = pollfd.Size * nfds;
            var buf         = Globals.AllocateAlignedCompletionBuffer(pollfd_size);

            if (!buf.isValid)
            {
                return(-ErrorCode.ENOMEM);
            }

            helper.WritePollFds(buf);

            var select_entry = new SelectCompletion(current, maxfds, inp, outp, exp, helper, buf);

            ret = Arch.IPCStubs.PollAsync(current.Parent.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), nfds, timeout);

            if (ret < 0)
            {
                select_entry.Dispose();
                return(ret);
            }

            Globals.CompletionQueue.Enqueue(select_entry);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return(0);
        }
Exemple #17
0
        private static int Getsockname(Thread current, ref Arch.ExceptionRegisters regs, int sockfd, UserPtr sockaddr, UserPtr p_addrlen)
        {
            var proc = current.Parent;
            var file = proc.LookupFile(sockfd);
            if (file == null)
                return -ErrorCode.EBADF;

            if (file.inode.kind != GenericINode.INodeKind.SocketINodeKind)
                return -ErrorCode.ENOTSOCK;

            int addrlen;
            if (p_addrlen.Read(current, out addrlen) != 0)
                return -ErrorCode.EFAULT;

            if (addrlen > Globals.LinuxIPCBuffer.Length)
                return -ErrorCode.EINVAL;

            var buf = Globals.AllocateAlignedCompletionBuffer((int)addrlen);

            if (!buf.isValid)
                return -ErrorCode.ENOMEM;

            var completion = new GetSockParamCompletion(current, sockaddr, p_addrlen, buf);

            Arch.IPCStubs.GetsockNameAsync(proc.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), file.inode.LinuxFd, addrlen);

            Globals.CompletionQueue.Enqueue(completion);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return 0;
        }
Exemple #18
0
        private static int Wait(Thread current, ref Arch.ExceptionRegisters regs, UserPtr uaddr, int flags, int val, bool hasTimeout, timespec ts, uint bitset)
        {
            int old_val;
            if (uaddr.Read(current, out old_val) != 0)
                return -ErrorCode.EFAULT;

            if (old_val != val)
                return -ErrorCode.EWOULDBLOCK;

            //Arch.Console.Write("wait: addr=");
            //Arch.Console.Write(uaddr.Value.ToUInt32());
            //Arch.Console.Write(" thr=");
            //Arch.Console.Write(current.Tid);
            //Arch.Console.WriteLine();

            TimerQueueNode node;
            var futex_entry = new FutexCompletionEntry(current, uaddr, bitset);
            Globals.FutexLists.InsertAtTail(futex_entry);

            if (hasTimeout)
            {
                node = Globals.TimeoutQueue.Enqueue(ts.ToMilliseconds(), current);
                futex_entry.timeoutNode = node;
            }

            Globals.CompletionQueue.Enqueue(futex_entry);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return 0;
        }
Exemple #19
0
        private static int Setsockopt(Thread current, ref Arch.ExceptionRegisters regs, int sockfd, int level, int optname, UserPtr optval, int optlen)
        {
            var proc = current.Parent;
            var file = proc.LookupFile(sockfd);
            if (file == null)
                return -ErrorCode.EBADF;

            if (file.inode.kind != GenericINode.INodeKind.SocketINodeKind)
                return -ErrorCode.ENOTSOCK;

            if (optlen > Globals.LinuxIPCBuffer.Length)
                return -ErrorCode.EINVAL;

            var buf = Globals.AllocateAlignedCompletionBuffer(optlen);

            if (!buf.isValid)
                return -ErrorCode.ENOMEM;

            var completion = new BridgeCompletion(current, buf);

            if (optval.Read(current, buf, optlen) != 0)
            {
                completion.Dispose();
                return -ErrorCode.EFAULT;
            }

            Arch.IPCStubs.SetSockoptAsync(proc.helperPid, current.impl._value.thread._value, new Pointer(buf.Location), file.inode.LinuxFd, level, optname, optlen);

            Globals.CompletionQueue.Enqueue(completion);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return 0;
        }
Exemple #20
0
        // Forward the futex request to Linux helper
        private static int DoFutexShared(Thread current, ref Arch.ExceptionRegisters regs, UserPtr uaddr, int op, int val, UserPtr timeoutPtr, UserPtr uaddr2, uint val3)
        {
            // Some local test
            var cmd = op & FUTEX_CMD_MASK;
            timespec ts = new timespec();

            bool hasTimeout = timeoutPtr != UserPtr.Zero;
            if (hasTimeout && timeoutPtr.Read(current, out ts) != 0)
                return -ErrorCode.EFAULT;

            if (cmd == FUTEX_WAIT || cmd == FUTEX_WAIT_BITSET)
            {
                int old_val;
                if (uaddr.Read(current, out old_val) != 0)
                    return -ErrorCode.EFAULT;

                if (old_val != val)
                    return -ErrorCode.EWOULDBLOCK;

                var bitset = cmd == FUTEX_WAIT ? FUTEX_BITSET_MATCH_ANY : val3;
                var shadowAddr = FindShadowAddr(current, uaddr);

                if (shadowAddr == Pointer.Zero)
                {
                    Arch.Console.WriteLine("FutexShared: Don't know how to deal with shared_wait");
                    return 0;
                }

                var futex_entry = new FutexCompletionEntry(current, uaddr, bitset);

                Arch.IPCStubs.linux_sys_futex_wait(current.Parent.helperPid, current.impl._value.thread._value, op, shadowAddr, val, ts, bitset);

                Globals.CompletionQueue.Enqueue(futex_entry);
                current.SaveState(ref regs);
                current.AsyncReturn = true;
                return 0;
            }
            else if (cmd == FUTEX_WAKE || cmd == FUTEX_WAKE_BITSET)
            {
                var bitset = cmd == FUTEX_WAKE ? FUTEX_BITSET_MATCH_ANY : val3;
                if (bitset == 0)
                    return -ErrorCode.EINVAL;

                var shadowAddr = FindShadowAddr(current, uaddr);
                if (shadowAddr == Pointer.Zero)
                {
                    Arch.Console.WriteLine("FutexShared: Don't know how to deal with shared_wake");
                    return 0;
                }

                var c = new BridgeCompletion(current, new ByteBufferRef());

                Arch.IPCStubs.linux_sys_futex_wake(current.Parent.helperPid, current.impl._value.thread._value, op, shadowAddr, bitset);

                Globals.CompletionQueue.Enqueue(c);
                current.SaveState(ref regs);
                current.AsyncReturn = true;

                return 0;
            }

            return 0;
        }
Exemple #21
0
        private static int Recv(Thread current, ref Arch.ExceptionRegisters regs, UserPtr ptr_label, UserPtr userBuf, uint size)
        {
            Contract.Requires(current.VBinderState.Owner == current);

            if (!current.Parent.Space.VerifyWrite(userBuf, size) || !current.Parent.Space.VerifyWrite(ptr_label, sizeof(int)))
                return -ErrorCode.EFAULT;

            var b = current.VBinderState.NoPendingMessages();
            if (b)
            {
                var entry = new VBinderCompletion(current, ptr_label, userBuf, size);
                current.VBinderState.Completion = entry;

                current.SaveState(ref regs);
                current.AsyncReturn = true;
                return 0;
            }
            else
            {
                var msg = current.VBinderState.TakeMessage();

                Contract.Assert(msg.GhostTarget == current);

                var length = msg.Length;
                ptr_label.Write(current.Parent, msg.label);
                userBuf.Write(current, new Pointer(msg.payload.Location), length);
                msg.Recycle();
                return length;
            }
        }
Exemple #22
0
        // Forward the futex request to Linux helper
        private static int DoFutexShared(Thread current, ref Arch.ExceptionRegisters regs, UserPtr uaddr, int op, int val, UserPtr timeoutPtr, UserPtr uaddr2, uint val3)
        {
            // Some local test
            var      cmd = op & FUTEX_CMD_MASK;
            timespec ts  = new timespec();

            bool hasTimeout = timeoutPtr != UserPtr.Zero;

            if (hasTimeout && timeoutPtr.Read(current, out ts) != 0)
            {
                return(-ErrorCode.EFAULT);
            }

            if (cmd == FUTEX_WAIT || cmd == FUTEX_WAIT_BITSET)
            {
                int old_val;
                if (uaddr.Read(current, out old_val) != 0)
                {
                    return(-ErrorCode.EFAULT);
                }

                if (old_val != val)
                {
                    return(-ErrorCode.EWOULDBLOCK);
                }

                var bitset     = cmd == FUTEX_WAIT ? FUTEX_BITSET_MATCH_ANY : val3;
                var shadowAddr = FindShadowAddr(current, uaddr);

                if (shadowAddr == Pointer.Zero)
                {
                    Arch.Console.WriteLine("FutexShared: Don't know how to deal with shared_wait");
                    return(0);
                }

                var futex_entry = new FutexCompletionEntry(current, uaddr, bitset);

                Arch.IPCStubs.linux_sys_futex_wait(current.Parent.helperPid, current.impl._value.thread._value, op, shadowAddr, val, ts, bitset);

                Globals.CompletionQueue.Enqueue(futex_entry);
                current.SaveState(ref regs);
                current.AsyncReturn = true;
                return(0);
            }
            else if (cmd == FUTEX_WAKE || cmd == FUTEX_WAKE_BITSET)
            {
                var bitset = cmd == FUTEX_WAKE ? FUTEX_BITSET_MATCH_ANY : val3;
                if (bitset == 0)
                {
                    return(-ErrorCode.EINVAL);
                }

                var shadowAddr = FindShadowAddr(current, uaddr);
                if (shadowAddr == Pointer.Zero)
                {
                    Arch.Console.WriteLine("FutexShared: Don't know how to deal with shared_wake");
                    return(0);
                }

                var c = new BridgeCompletion(current, new ByteBufferRef());

                Arch.IPCStubs.linux_sys_futex_wake(current.Parent.helperPid, current.impl._value.thread._value, op, shadowAddr, bitset);

                Globals.CompletionQueue.Enqueue(c);
                current.SaveState(ref regs);
                current.AsyncReturn = true;

                return(0);
            }

            return(0);
        }
Exemple #23
0
        public static int Nanosleep(Thread current, ref Arch.ExceptionRegisters regs, UserPtr rqtp, UserPtr rmtp)
        {
            timespec ts;
            timespec trem;

            trem.tv_sec = 0;
            trem.tv_nsec = 0;

            if (rqtp.Read(current, out ts) != 0 || rmtp.Write(current, ref trem) != 0)
                return -ErrorCode.EFAULT;

            Globals.TimeoutQueue.Enqueue(ts.ToMilliseconds(), current);
            var c = new SleepCompletion(current);

            Globals.CompletionQueue.Enqueue(c);
            current.SaveState(ref regs);
            current.AsyncReturn = true;
            return 0;
        }