Add one or more "signal slots" per possible cause of in-band signal
into struct xnthread to get rid of dynamic allocation.

For SIGDEBUG, except SIGDEBUG_WATCHDOG all other SIGDEBUG_* cause
including SIGDEBUG_MIGRATE_SIGNAL, SIGDEBUG_MIGRATE_SYSCALL,
SIGDEBUG_MIGRATE_FAULT, SIGDEBUG_MIGRATE_PRIOINV, SIGDEBUG_NOMLOCK,
SIGDEBUG_RESCNT_IMBALANCE, SIGDEBUG_LOCK_BREAK, SIGDEBUG_MUTEX_SLEEP
are synchronous and mutually exclusive due to the oob->in-band transition.
But SIGDEBUG_WATCHDOG is triggered asynchronously by the oob timer.

All SIGSHADOW_* events need their own slot: SIGSHADOW_ACTION_HARDEN and
SIGSHADOW_ACTION_HOME can be raised by remote threads asynchronously to
the target thread. SIGSHADOW_ACTION_BACKTRACE comes in addition to
SIGDEBUG_MIGRATE_*. For the latter reason, SIGSHADOW_ACTION_BACKTRACE
cannot pile up though.

Including SIGTERM, we have totally 6 slots.

Signed-off-by: Hongzhan Chen <[email protected]>

diff --git a/include/cobalt/kernel/thread.h b/include/cobalt/kernel/thread.h
index bc83cc556..29795f79c 100644
--- a/include/cobalt/kernel/thread.h
+++ b/include/cobalt/kernel/thread.h
@@ -42,6 +42,7 @@
  */
 #define XNTHREAD_BLOCK_BITS   
(XNSUSP|XNPEND|XNDELAY|XNDORMANT|XNRELAX|XNHELD|XNDBGSTOP)
 #define XNTHREAD_MODE_BITS    (XNRRB|XNWARN|XNTRAPLB)
+#define XNTHREAD_SIGNALS_NUM  6
 
 struct xnthread;
 struct xnsched;
@@ -51,6 +52,13 @@ struct xnsched_tpslot;
 struct xnthread_personality;
 struct completion;
 
+struct lostage_signal {
+       struct pipeline_inband_work inband_work; /* Must be first. */
+       struct task_struct *task;
+       int signo, sigval;
+       struct lostage_signal *self; /* Revisit: I-pipe requirement */
+};
+
 struct xnthread_init_attr {
        struct xnthread_personality *personality;
        cpumask_t affinity;
@@ -205,6 +213,29 @@ struct xnthread {
        const char *exe_path;   /* Executable path */
        u32 proghash;           /* Hash value for exe_path */
 #endif
+       /*
+        * Each slot handle different cause of signal
+        * slot 0:
+        *      SIGDEBUG_MIGRATE_SIGNAL
+        *      SIGDEBUG_MIGRATE_SYSCALL
+        *      SIGDEBUG_MIGRATE_FAULT
+        *      SIGDEBUG_MIGRATE_PRIOINV
+        *      SIGDEBUG_NOMLOCK
+        *      SIGDEBUG_RESCNT_IMBALANCE
+        *      SIGDEBUG_LOCK_BREAK
+        *      SIGDEBUG_MUTEX_SLEEP
+        * slot 1:
+        *      SIGDEBUG_WATCHDOG
+        * slot 2:
+        *      SIGSHADOW_ACTION_HARDEN
+        * slot 3:
+        *      SIGSHADOW_ACTION_BACKTRACE
+        * slot 4:
+        *      SIGSHADOW_ACTION_HOME
+        * slot 5:
+        *      SIGTERM
+        */
+       struct lostage_signal sigarray[XNTHREAD_SIGNALS_NUM];
 };
 
 static inline int xnthread_get_state(const struct xnthread *thread)
diff --git a/kernel/cobalt/thread.c b/kernel/cobalt/thread.c
index 9c7753ac4..ebb798b58 100644
--- a/kernel/cobalt/thread.c
+++ b/kernel/cobalt/thread.c
@@ -2065,13 +2065,6 @@ void xnthread_relax(int notify, int reason)
 }
 EXPORT_SYMBOL_GPL(xnthread_relax);
 
-struct lostage_signal {
-       struct pipeline_inband_work inband_work; /* Must be first. */
-       struct task_struct *task;
-       int signo, sigval;
-       struct lostage_signal *self; /* Revisit: I-pipe requirement */
-};
-
 static inline void do_kthread_signal(struct task_struct *p,
                                     struct xnthread *thread,
                                     struct lostage_signal *rq)
@@ -2111,7 +2104,7 @@ static void lostage_task_signal(struct 
pipeline_inband_work *inband_work)
        } else
                send_sig(signo, p, 1);
 out:
-       xnfree(rq->self);
+       memset(rq->self, 0, sizeof(*rq));
 }
 
 static int force_wakeup(struct xnthread *thread) /* nklock locked, irqs off */
@@ -2273,14 +2266,56 @@ void xnthread_demote(struct xnthread *thread)
 }
 EXPORT_SYMBOL_GPL(xnthread_demote);
 
+int get_slot_index_from_sig(int sig, int arg)
+{
+       int action;
+
+       switch (sig) {
+       case SIGDEBUG:
+               switch (arg) {
+               case SIGDEBUG_WATCHDOG:
+                       return 1;
+               case SIGDEBUG_MIGRATE_SIGNAL:
+               case SIGDEBUG_MIGRATE_SYSCALL:
+               case SIGDEBUG_MIGRATE_FAULT:
+               case SIGDEBUG_MIGRATE_PRIOINV:
+               case SIGDEBUG_NOMLOCK:
+               case SIGDEBUG_RESCNT_IMBALANCE:
+               case SIGDEBUG_LOCK_BREAK:
+               case SIGDEBUG_MUTEX_SLEEP:
+                       return 0;
+               }
+               break;
+       case SIGSHADOW:
+               action = sigshadow_action(arg);
+               switch (action) {
+               case SIGSHADOW_ACTION_HARDEN:
+                       return 2;
+               case SIGSHADOW_ACTION_BACKTRACE:
+                       return 3;
+               case SIGSHADOW_ACTION_HOME:
+                       return 4;
+               }
+               break;
+       case SIGTERM:
+               return 5;
+       }
+
+       return -1;
+}
+
 void xnthread_signal(struct xnthread *thread, int sig, int arg)
 {
        struct lostage_signal *sigwork;
+       int slot;
+
+       slot = get_slot_index_from_sig(sig, arg);
 
-       sigwork = xnmalloc(sizeof(*sigwork));
-       if (WARN_ON(sigwork == NULL))
+       if (slot < 0 || slot >= XNTHREAD_SIGNALS_NUM)
                return;
 
+       sigwork = &thread->sigarray[slot];
+
        sigwork->inband_work = (struct pipeline_inband_work)
                        PIPELINE_INBAND_WORK_INITIALIZER(*sigwork,
                                        lostage_task_signal);
-- 
2.17.1


Reply via email to