You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by li...@apache.org on 2020/09/03 02:20:58 UTC

[incubator-nuttx] 02/02: arch/sim: Model host signal as NuttX's interrupt

This is an automated email from the ASF dual-hosted git repository.

liuhaitao pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit 5107104bbead8179253240713a9f16d1775444ba
Author: Xiang Xiao <xi...@xiaomi.com>
AuthorDate: Sat Aug 29 14:06:56 2020 +0800

    arch/sim: Model host signal as NuttX's interrupt
    
    Signed-off-by: Xiang Xiao <xi...@xiaomi.com>
---
 arch/Kconfig                           |  1 -
 arch/sim/include/irq.h                 |  4 +-
 arch/sim/src/sim/up_hostirq.c          | 71 ++++++++++++++++++++++++++++++++++
 arch/sim/src/sim/up_internal.h         | 24 ++++++++++++
 arch/sim/src/sim/up_interruptcontext.c | 36 ++++++++++++++++-
 5 files changed, 130 insertions(+), 6 deletions(-)

diff --git a/arch/Kconfig b/arch/Kconfig
index 79b7e51..93a50ef 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -72,7 +72,6 @@ config ARCH_SIM
 	select ARCH_HAVE_TICKLESS
 	select ARCH_HAVE_POWEROFF
 	select ARCH_HAVE_TESTSET
-	select ARCH_NOINTC
 	select ALARM_ARCH
 	select ONESHOT
 	select SERIAL_CONSOLE
diff --git a/arch/sim/include/irq.h b/arch/sim/include/irq.h
index 808266b..bec1d78 100644
--- a/arch/sim/include/irq.h
+++ b/arch/sim/include/irq.h
@@ -44,9 +44,7 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
-/* No interrupts */
-
-#define NR_IRQS 0
+#define NR_IRQS 64
 
 /* Number of registers saved in context switch */
 
diff --git a/arch/sim/src/sim/up_hostirq.c b/arch/sim/src/sim/up_hostirq.c
index 9acbd59..b929620 100644
--- a/arch/sim/src/sim/up_hostirq.c
+++ b/arch/sim/src/sim/up_hostirq.c
@@ -25,6 +25,19 @@
 #include <signal.h>
 #include <stddef.h>
 #include <stdint.h>
+#include <string.h>
+
+#include "up_internal.h"
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#ifdef CONFIG_SMP
+volatile void *g_current_regs[CONFIG_SMP_NCPUS];
+#else
+volatile void *g_current_regs[1];
+#endif
 
 /****************************************************************************
  * Private Types
@@ -37,6 +50,19 @@ union sigset_u
 };
 
 /****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: up_handle_irq
+ ****************************************************************************/
+
+static void up_handle_irq(int irq, siginfo_t *info, void *context)
+{
+  up_doirq(irq, context);
+}
+
+/****************************************************************************
  * Public Functions
  ****************************************************************************/
 
@@ -86,3 +112,48 @@ void up_irq_restore(uint64_t flags)
 void up_irqinitialize(void)
 {
 }
+
+/****************************************************************************
+ * Name: up_enable_irq
+ *
+ * Description:
+ *   Enable the IRQ specified by 'irq'
+ *
+ ****************************************************************************/
+
+void up_enable_irq(int irq)
+{
+  struct sigaction act;
+  sigset_t set;
+
+  /* Register signal handler */
+
+  memset(&act, 0, sizeof(act));
+  act.sa_sigaction = up_handle_irq;
+  act.sa_flags     = SA_SIGINFO;
+  sigfillset(&act.sa_mask);
+  sigaction(irq, &act, NULL);
+
+  /* Unmask the signal */
+
+  sigemptyset(&set);
+  sigaddset(&set, irq);
+  pthread_sigmask(SIG_UNBLOCK, &set, NULL);
+}
+
+/****************************************************************************
+ * Name: up_disable_irq
+ *
+ * Description:
+ *   Disable the IRQ specified by 'irq'
+ *
+ ****************************************************************************/
+
+void up_disable_irq(int irq)
+{
+  /* Since it's hard to mask the signal on all threads,
+   * let's change the signal handler to ignore instead.
+   */
+
+  signal(irq, SIG_IGN);
+}
diff --git a/arch/sim/src/sim/up_internal.h b/arch/sim/src/sim/up_internal.h
index 26e3f51..df24178 100644
--- a/arch/sim/src/sim/up_internal.h
+++ b/arch/sim/src/sim/up_internal.h
@@ -169,6 +169,28 @@ struct ioexpander_dev_s;
  * Public Data
  ****************************************************************************/
 
+/* g_current_regs[] holds a references to the current interrupt level
+ * register storage structure.  If is non-NULL only during interrupt
+ * processing.  Access to g_current_regs[] must be through the macro
+ * CURRENT_REGS for portability.
+ */
+
+#ifdef CONFIG_SMP
+/* For the case of architectures with multiple CPUs, then there must be one
+ * such value for each processor that can receive an interrupt.
+ */
+
+int up_cpu_index(void); /* See include/nuttx/arch.h */
+extern volatile void *g_current_regs[CONFIG_SMP_NCPUS];
+#  define CURRENT_REGS (g_current_regs[up_cpu_index()])
+
+#else
+
+extern volatile void *g_current_regs[1];
+#  define CURRENT_REGS (g_current_regs[0])
+
+#endif
+
 #ifdef CONFIG_SMP
 /* These spinlocks are used in the SMP configuration in order to implement
  * up_cpu_pause().  The protocol for CPUn to pause CPUm is as follows
@@ -192,6 +214,8 @@ extern volatile uint8_t g_cpu_paused[CONFIG_SMP_NCPUS];
  * Public Function Prototypes
  ****************************************************************************/
 
+void *up_doirq(int irq, void *regs);
+
 /* up_setjmp32.S ************************************************************/
 
 int  up_setjmp(void *jb);
diff --git a/arch/sim/src/sim/up_interruptcontext.c b/arch/sim/src/sim/up_interruptcontext.c
index 91661ac..7a3a9e4 100644
--- a/arch/sim/src/sim/up_interruptcontext.c
+++ b/arch/sim/src/sim/up_interruptcontext.c
@@ -41,6 +41,7 @@
 
 #include <stdbool.h>
 #include <nuttx/arch.h>
+
 #include "up_internal.h"
 
 /****************************************************************************
@@ -58,7 +59,38 @@
 
 bool up_interrupt_context(void)
 {
-  /* The simulation is never in the interrupt state */
+  return CURRENT_REGS != NULL;
+}
+
+/****************************************************************************
+ * Name: up_doirq
+ ****************************************************************************/
+
+void *up_doirq(int irq, void *regs)
+{
+  /* Current regs non-zero indicates that we are processing an interrupt;
+   * CURRENT_REGS is also used to manage interrupt level context switches.
+   */
+
+  CURRENT_REGS = regs;
+
+  /* Deliver the IRQ */
+
+  irq_dispatch(irq, regs);
+
+  /* If a context switch occurred while processing the interrupt then
+   * CURRENT_REGS may have change value.  If we return any value different
+   * from the input regs, then the lower level will know that a context
+   * switch occurred during interrupt processing.
+   */
+
+  regs = (void *)CURRENT_REGS;
+
+  /* Restore the previous value of CURRENT_REGS.  NULL would indicate that
+   * we are no longer in an interrupt handler.  It will be non-NULL if we
+   * are returning from a nested interrupt.
+   */
 
-  return false;
+  CURRENT_REGS = NULL;
+  return regs;
 }