/* * Atomically swap in the new signal mask, and wait for a signal. */ inline int sys32_sigsuspend(struct pt_regs regs) { BUG(); return -EFAULT; #if 0 compat_sigset_t *uset; sigset_t newset, saveset; save_static(®s); uset = (compat_sigset_t *) regs.regs[4]; if (get_sigset(&newset, uset)) return -EFAULT; sigdelsetmask(&newset, ~_BLOCKABLE); spin_lock_irq(¤t->sighand->siglock); saveset = current->blocked; current->blocked = newset; recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); regs.regs[2] = EINTR; regs.regs[7] = 1; while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); if (do_signal32(&saveset, ®s)) return -EINTR; } #endif }
/* * Atomically swap in the new signal mask, and wait for a signal. */ asmlinkage inline int sys_sigsuspend(abi64_no_regargs, struct pt_regs regs) { sigset_t *uset, saveset, newset; save_static(®s); uset = (sigset_t *) regs.regs[4]; if (copy_from_user(&newset, uset, sizeof(sigset_t))) return -EFAULT; sigdelsetmask(&newset, ~_BLOCKABLE); spin_lock_irq(¤t->sigmask_lock); saveset = current->blocked; current->blocked = newset; recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); regs.regs[2] = EINTR; regs.regs[7] = 1; while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); if (do_signal(&saveset, ®s)) return -EINTR; } }
asmlinkage int sys_rt_sigsuspend(abi64_no_regargs, struct pt_regs regs) { sigset_t *unewset, saveset, newset; size_t sigsetsize; save_static(®s); /* XXX Don't preclude handling different sized sigset_t's. */ sigsetsize = regs.regs[5]; if (sigsetsize != sizeof(sigset_t)) return -EINVAL; unewset = (sigset_t *) regs.regs[4]; if (copy_from_user(&newset, unewset, sizeof(newset))) return -EFAULT; sigdelsetmask(&newset, ~_BLOCKABLE); spin_lock_irq(¤t->sigmask_lock); saveset = current->blocked; current->blocked = newset; recalc_sigpending(current); spin_unlock_irq(¤t->sigmask_lock); regs.regs[2] = EINTR; regs.regs[7] = 1; while (1) { current->state = TASK_INTERRUPTIBLE; schedule(); if (do_signal(&saveset, ®s)) return -EINTR; } }
asmlinkage int sys_fork(abi64_no_regargs, struct pt_regs regs) { int res; save_static(®s); res = do_fork(SIGCHLD, regs.regs[29], ®s, 0); return res; }
/* * This is trivial, and on the face of it looks like it * could equally well be done in user mode. * * Not so, for quite unobvious reasons - register pressure. * In user mode vfork() cannot have a stack frame, and if * done by calling the "clone()" system call directly, you * do not have enough call-clobbered registers to hold all * the information you need. */ asmlinkage int sys_vfork(struct pt_regs regs) { int res; save_static(®s); res = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, get_gpreg(®s, 29), ®s); return res; }
asmlinkage int sys_fork(struct pt_regs regs) { int res; save_static(®s); res = do_fork(SIGCHLD, get_gpreg(®s, 29), ®s); return res; }
asmlinkage int sys_clone(abi64_no_regargs, struct pt_regs regs) { unsigned long clone_flags; unsigned long newsp; int res; save_static(®s); clone_flags = regs.regs[4]; newsp = regs.regs[5]; if (!newsp) newsp = regs.regs[29]; res = do_fork(clone_flags, newsp, ®s, 0); return res; }
asmlinkage int sys_clone(struct pt_regs regs) { unsigned long clone_flags; unsigned long newsp; int res; save_static(®s); clone_flags = get_gpreg(®s, 4); newsp = get_gpreg(®s, 5); if (!newsp) newsp = get_gpreg(®s, 29); res = do_fork(clone_flags, newsp, ®s); return res; }