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); }
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; }
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); }
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); }
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); }
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); }
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); }
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); }
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; }
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); }
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 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; }
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; }
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); }
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; }
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; }
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; }
// 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; }
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; } }
// 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); }
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; }