[v7,59/74] linux-user: Split out sigpending, rt_sigpending

Message ID 20190519203726.20729-60-richard.henderson@linaro.org
State New
Headers show
Series
  • linux-user: Split do_syscall
Related show

Commit Message

Richard Henderson May 19, 2019, 8:37 p.m.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

---
 linux-user/syscall-defs.h    |  4 ++++
 linux-user/syscall-sig.inc.c | 45 ++++++++++++++++++++++++++++++++++++
 linux-user/syscall.c         | 36 -----------------------------
 linux-user/strace.list       |  6 -----
 4 files changed, 49 insertions(+), 42 deletions(-)

-- 
2.17.1

Patch

diff --git a/linux-user/syscall-defs.h b/linux-user/syscall-defs.h
index ef77f60524..83a69246d0 100644
--- a/linux-user/syscall-defs.h
+++ b/linux-user/syscall-defs.h
@@ -194,6 +194,7 @@  SYSCALL_DEF(rt_sigaction, ARG_SIGNAL, ARG_PTR, ARG_PTR, ARG_PTR, ARG_DEC);
 #else
 SYSCALL_DEF(rt_sigaction, ARG_SIGNAL, ARG_PTR, ARG_PTR, ARG_DEC);
 #endif
+SYSCALL_DEF(rt_sigpending, ARG_PTR, ARG_DEC);
 SYSCALL_DEF(rt_sigprocmask, ARG_SIGPROCMASKHOW, ARG_PTR, ARG_PTR, ARG_DEC);
 #if !defined(SYSCALL_TABLE) || defined(TARGET_NR_semctl)
 SYSCALL_DEF(semctl, ARG_DEC, ARG_DEC, ARG_DEC, ARG_HEX);
@@ -223,6 +224,9 @@  SYSCALL_DEF(shmget, ARG_DEC, ARG_DEC, ARG_HEX);
 #ifdef TARGET_NR_sigaction
 SYSCALL_DEF(sigaction, ARG_SIGNAL, ARG_PTR, ARG_PTR);
 #endif
+#ifdef TARGET_NR_sigpending
+SYSCALL_DEF(sigpending, ARG_PTR);
+#endif
 #if defined(TARGET_ALPHA)
 SYSCALL_DEF(sigprocmask, ARG_SIGPROCMASKHOW, ARG_HEX);
 #elif defined(TARGET_NR_sigprocmask)
diff --git a/linux-user/syscall-sig.inc.c b/linux-user/syscall-sig.inc.c
index 8a6518bdaa..fe717a5121 100644
--- a/linux-user/syscall-sig.inc.c
+++ b/linux-user/syscall-sig.inc.c
@@ -117,6 +117,33 @@  SYSCALL_IMPL(rt_sigaction)
     return ret;
 }
 
+SYSCALL_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)) {
+        void *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;
+}
+
 SYSCALL_IMPL(rt_sigprocmask)
 {
     int how = 0;
@@ -259,6 +286,24 @@  SYSCALL_IMPL(sigaction)
 }
 #endif
 
+#ifdef TARGET_NR_sigpending
+SYSCALL_IMPL(sigpending)
+{
+    sigset_t set;
+    abi_long ret = get_errno(sigpending(&set));
+
+    if (!is_error(ret)) {
+        void *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
 SYSCALL_IMPL(sigprocmask)
 {
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 11bbdfade4..7dda237c95 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4241,42 +4241,6 @@  static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
     void *p;
 
     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:
         {
diff --git a/linux-user/strace.list b/linux-user/strace.list
index 7157876302..978e47bf0e 100644
--- a/linux-user/strace.list
+++ b/linux-user/strace.list
@@ -926,9 +926,6 @@ 
 #ifdef TARGET_NR_rmdir
 { TARGET_NR_rmdir, "rmdir" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_rt_sigpending
-{ TARGET_NR_rt_sigpending, "rt_sigpending" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_rt_sigqueueinfo
 { TARGET_NR_rt_sigqueueinfo, "rt_sigqueueinfo" , NULL, print_rt_sigqueueinfo, NULL },
 #endif
@@ -1128,9 +1125,6 @@ 
 #ifdef TARGET_NR_signalfd4
 { TARGET_NR_signalfd4, "signalfd4" , NULL, NULL, NULL },
 #endif
-#ifdef TARGET_NR_sigpending
-{ TARGET_NR_sigpending, "sigpending" , NULL, NULL, NULL },
-#endif
 #ifdef TARGET_NR_sigreturn
 { TARGET_NR_sigreturn, "sigreturn" , NULL, NULL, NULL },
 #endif