Signed-off-by: Richard Henderson <richard.hender...@linaro.org> --- linux-user/syscall.c | 176 +++++++++++++++++++++++++------------------ 1 file changed, 101 insertions(+), 75 deletions(-)
diff --git a/linux-user/syscall.c b/linux-user/syscall.c index e37a3ab643..c3bd625965 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8805,6 +8805,32 @@ IMPL(rt_sigaction) return ret; } +IMPL(rt_sigpending) +{ + sigset_t set; + abi_long ret; + + /* Yes, this check is >, not != like most. We follow the kernel's + * logic and it does it like this because it implements + * NR_sigpending through the same code path, and in that case + * the old_sigset_t is smaller in size. + */ + if (arg2 > sizeof(target_sigset_t)) { + return -TARGET_EINVAL; + } + ret = get_errno(sigpending(&set)); + if (!is_error(ret)) { + target_sigset_t *p; + p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0); + if (!p) { + return -TARGET_EFAULT; + } + host_to_target_sigset(p, &set); + unlock_user(p, arg1, sizeof(target_sigset_t)); + } + return ret; +} + IMPL(rt_sigprocmask) { int how = 0; @@ -8850,6 +8876,29 @@ IMPL(rt_sigprocmask) return ret; } +IMPL(rt_sigsuspend) +{ + CPUState *cpu = ENV_GET_CPU(cpu_env); + TaskState *ts = cpu->opaque; + target_sigset_t *p; + abi_long ret; + + if (arg2 != sizeof(target_sigset_t)) { + return -TARGET_EINVAL; + } + p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1); + if (!p) { + return -TARGET_EFAULT; + } + target_to_host_sigset(&ts->sigsuspend_mask, p); + unlock_user(p, arg1, 0); + ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask, SIGSET_T_SIZE)); + if (ret != -TARGET_ERESTARTSYS) { + ts->in_sigsuspend = 1; + } + return ret; +} + #ifdef TARGET_NR_sgetmask IMPL(sgetmask) { @@ -8960,6 +9009,24 @@ IMPL(sigaction) } #endif +#ifdef TARGET_NR_sigpending +IMPL(sigpending) +{ + sigset_t set; + abi_long ret = get_errno(sigpending(&set)); + if (!is_error(ret)) { + abi_ulong *p; + p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0); + if (!p) { + return -TARGET_EFAULT; + } + host_to_target_old_sigset(p, &set); + unlock_user(p, arg1, sizeof(target_sigset_t)); + } + return ret; +} +#endif + #ifdef TARGET_NR_sigprocmask IMPL(sigprocmask) { @@ -9032,6 +9099,32 @@ IMPL(sigprocmask) } #endif +#ifdef TARGET_NR_sigsuspend +IMPL(sigsuspend) +{ + CPUState *cpu = ENV_GET_CPU(cpu_env); + TaskState *ts = cpu->opaque; + abi_long ret; + +# ifdef TARGET_ALPHA + abi_ulong mask = arg1; + target_to_host_old_sigset(&ts->sigsuspend_mask, &mask); +# else + abi_ulong *p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1); + if (!p) { + return -TARGET_EFAULT; + } + target_to_host_old_sigset(&ts->sigsuspend_mask, p); + unlock_user(p, arg1, 0); +# endif + ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask, SIGSET_T_SIZE)); + if (ret != -TARGET_ERESTARTSYS) { + ts->in_sigsuspend = 1; + } + return ret; +} +#endif + #ifdef TARGET_NR_ssetmask IMPL(ssetmask) { @@ -9300,81 +9393,6 @@ IMPL(everything_else) char *fn; switch(num) { -#ifdef TARGET_NR_sigpending - case TARGET_NR_sigpending: - { - sigset_t set; - ret = get_errno(sigpending(&set)); - if (!is_error(ret)) { - if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0))) - return -TARGET_EFAULT; - host_to_target_old_sigset(p, &set); - unlock_user(p, arg1, sizeof(target_sigset_t)); - } - } - return ret; -#endif - case TARGET_NR_rt_sigpending: - { - sigset_t set; - - /* Yes, this check is >, not != like most. We follow the kernel's - * logic and it does it like this because it implements - * NR_sigpending through the same code path, and in that case - * the old_sigset_t is smaller in size. - */ - if (arg2 > sizeof(target_sigset_t)) { - return -TARGET_EINVAL; - } - - ret = get_errno(sigpending(&set)); - if (!is_error(ret)) { - if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0))) - return -TARGET_EFAULT; - host_to_target_sigset(p, &set); - unlock_user(p, arg1, sizeof(target_sigset_t)); - } - } - return ret; -#ifdef TARGET_NR_sigsuspend - case TARGET_NR_sigsuspend: - { - TaskState *ts = cpu->opaque; -#if defined(TARGET_ALPHA) - abi_ulong mask = arg1; - target_to_host_old_sigset(&ts->sigsuspend_mask, &mask); -#else - if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1))) - return -TARGET_EFAULT; - target_to_host_old_sigset(&ts->sigsuspend_mask, p); - unlock_user(p, arg1, 0); -#endif - ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask, - SIGSET_T_SIZE)); - if (ret != -TARGET_ERESTARTSYS) { - ts->in_sigsuspend = 1; - } - } - return ret; -#endif - case TARGET_NR_rt_sigsuspend: - { - TaskState *ts = cpu->opaque; - - if (arg2 != sizeof(target_sigset_t)) { - return -TARGET_EINVAL; - } - if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1))) - return -TARGET_EFAULT; - target_to_host_sigset(&ts->sigsuspend_mask, p); - unlock_user(p, arg1, 0); - ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask, - SIGSET_T_SIZE)); - if (ret != -TARGET_ERESTARTSYS) { - ts->in_sigsuspend = 1; - } - } - return ret; case TARGET_NR_rt_sigtimedwait: { sigset_t set; @@ -13112,7 +13130,9 @@ static impl_fn * const syscall_table[] = { [TARGET_NR_rmdir] = impl_rmdir, #endif [TARGET_NR_rt_sigaction] = impl_rt_sigaction, + [TARGET_NR_rt_sigpending] = impl_rt_sigpending, [TARGET_NR_rt_sigprocmask] = impl_rt_sigprocmask, + [TARGET_NR_rt_sigsuspend] = impl_rt_sigsuspend, #ifdef TARGET_NR_sgetmask [TARGET_NR_sgetmask] = impl_sgetmask, #endif @@ -13121,9 +13141,15 @@ static impl_fn * const syscall_table[] = { #ifdef TARGET_NR_sigaction [TARGET_NR_sigaction] = impl_sigaction, #endif +#ifdef TARGET_NR_sigpending + [TARGET_NR_sigpending] = impl_sigpending, +#endif #ifdef TARGET_NR_sigprocmask [TARGET_NR_sigprocmask] = impl_sigprocmask, #endif +#ifdef TARGET_NR_sigsuspend + [TARGET_NR_sigsuspend] = impl_sigsuspend, +#endif #ifdef TARGET_NR_ssetmask [TARGET_NR_ssetmask] = impl_ssetmask, #endif -- 2.17.0