qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 4/5] linux-user: Add support for multiplexing larger


From: Aleksandar Markovic
Subject: [Qemu-devel] [PATCH 4/5] linux-user: Add support for multiplexing larger target signals
Date: Wed, 22 May 2019 20:46:24 +0200

From: Miloš Stojanović <address@hidden>

Add MUX_SIG as a multiplex signal number for all target signals which are
out of the host range. Add support for multiplexing in do_sigaction(),
process_pending_signals(), target_set_sigmask() and do_target_sigprocmask().

This patch solves the problem of unusable target signals which are out of
the host range. This is done by enabling the usage of one of the host
signals (MUX_SIG) as a multiplex for all the target signals that are out
of range. In order to have the target signal masks available
TRACK_TARGET_MASK is defined which enables the tracking of the target
signals masks.

The table of signal handlers already supports the whole range of target
signals. In the do_sigaction() function the signal number of signals which
are out of range are replaced by MUX_SIG which bypasses the error from the
host system and doesn't interfere with signal handling on the target.
Since the MUX_SIG is used as a multiplex, it must never be blocked on host,
so support for emulating the blocking of this signal is added. This is done
by only blocking MUX_SIG in the target mask and retrieving its status from
there when it's needed.

Signed-off-by: Miloš Stojanović <address@hidden>
Signed-off-by: Aleksandar Markovic <address@hidden>
---
 linux-user/signal.c       | 32 ++++++++++++++++++++++++++++++++
 linux-user/syscall_defs.h | 20 ++++++++++++++++++++
 2 files changed, 52 insertions(+)

diff --git a/linux-user/signal.c b/linux-user/signal.c
index 9a73bfa..601de3e 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -291,6 +291,15 @@ int do_target_sigprocmask(int how, const target_sigset_t 
*target_set,
     }
     if (oldset) {
         *oldset = ts->signal_mask;
+#ifdef MUX_SIG
+        /*
+         * The emulation of MUX_SIG being blocked is done using the
+         * target_signal_mask, so the status of MUX_SIG is taken from there.
+         */
+        if (target_sigismember(&ts->target_signal_mask, MUX_SIG) == 1) {
+            sigaddset(oldset, MUX_SIG);
+        }
+#endif
     }
 
     if (target_set && set) {
@@ -331,6 +340,15 @@ int do_target_sigprocmask(int how, const target_sigset_t 
*target_set,
         target_sigdelset(&ts->target_signal_mask, SIGSTOP);
         sigdelset(&ts->signal_mask, SIGKILL);
         sigdelset(&ts->signal_mask, SIGSTOP);
+#ifdef MUX_SIG
+        /*
+         * Since MUX_SIG is used for all the target signals out of the host
+         * range it must never be blocked on host. The emulation of MUX_SIG
+         * being blocked is done using the target_signal_mask. The status
+         * of MUX_SIG is taken form the target_signal_mask.
+         */
+        sigdelset(&ts->signal_mask, MUX_SIG);
+#endif
     }
     return 0;
 }
@@ -355,6 +373,10 @@ void target_set_sigmask(const sigset_t *set,
 
     ts->signal_mask = *set;
     ts->target_signal_mask = *target_set;
+#ifdef MUX_SIG
+    /* MUX_SIG can't be blocked on host */
+    sigdelset(&ts->signal_mask, MUX_SIG);
+#endif
 }
 #endif
 #endif
@@ -929,6 +951,12 @@ int do_sigaction(int sig, const struct target_sigaction 
*act,
 
         /* we update the host linux signal state */
         host_sig = target_to_host_signal(sig);
+#ifdef MUX_SIG
+        /* put the out of host range signal into the multiplex */
+        if (sig >= _NSIG && sig < TARGET_NSIG) {
+            host_sig = MUX_SIG;
+        }
+#endif
         if (host_sig != SIGSEGV && host_sig != SIGBUS) {
             sigfillset(&act1.sa_mask);
             act1.sa_flags = SA_SIGINFO;
@@ -1141,6 +1169,10 @@ void process_pending_signals(CPUArchState *cpu_env)
         set = ts->signal_mask;
         sigdelset(&set, SIGSEGV);
         sigdelset(&set, SIGBUS);
+#ifdef MUX_SIG
+        /* MUX_SIG can't be blocked on host */
+        sigdelset(&ts->signal_mask, MUX_SIG);
+#endif
         sigprocmask(SIG_SETMASK, &set, 0);
     }
     ts->in_sigsuspend = 0;
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 64edec2..0c72509 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -387,6 +387,26 @@ struct target_dirent64 {
 #define TARGET_NSIG_BPW           TARGET_ABI_BITS
 #define TARGET_NSIG_WORDS  (TARGET_NSIG / TARGET_NSIG_BPW)
 
+#if _NSIG <= TARGET_NSIG
+/*
+ * MUX_SIG is used as a multiplex signal number - signals that are
+ * out of the host range and in the target range are sent through it.
+ * It is defined as the maximal available real-time signal in order to
+ * comply with the rule that low-numbered signals have highest priority.
+ * (signals using it will have the same priority but it will be smaller
+ * than all the other real-time signals)
+ * SIGRMTAX is avoided so it doesn't interfere with the hack of reversing
+ * __SIGRTMIN and __SIGRTMAX in the host_to_target_signal_table.
+ */
+#define MUX_SIG     (SIGRTMAX - 1)
+
+/*
+ * The target signal masks must be tracked since they are larger than
+ * the host signal masks.
+ */
+#define TRACK_TARGET_SIGMASK
+#endif
+
 typedef struct {
     abi_ulong sig[TARGET_NSIG_WORDS];
 } target_sigset_t;
-- 
2.7.4




reply via email to

[Prev in Thread] Current Thread [Next in Thread]