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

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

commit d6bbe4f6a5fe1bd5bb6516ca685cf3dc82fc45cf
Author: chao.an <[email protected]>
AuthorDate: Tue Mar 8 10:58:44 2022 +0800

    segger/sysview: add syscall support
    
    Signed-off-by: chao.an <[email protected]>
---
 drivers/segger/note_sysview.c | 161 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 157 insertions(+), 4 deletions(-)

diff --git a/drivers/segger/note_sysview.c b/drivers/segger/note_sysview.c
index 053eb1a..be3b472 100644
--- a/drivers/segger/note_sysview.c
+++ b/drivers/segger/note_sysview.c
@@ -40,12 +40,16 @@
 
 struct sysview_s
 {
-  unsigned int              irq[CONFIG_SMP_NCPUS];
+  unsigned int                 irq[CONFIG_SMP_NCPUS];
 #ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER
-  struct note_filter_mode_s mode;
+  struct note_filter_mode_s    mode;
 #endif
 #ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER
-  struct note_filter_irq_s  irq_mask;
+  struct note_filter_irq_s     irq_mask;
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+  struct note_filter_syscall_s syscall_mask;
+  struct note_filter_syscall_s syscall_marker;
 #endif
 };
 
@@ -155,11 +159,24 @@ static bool sysview_isenabled(void)
     }
 #endif
 
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+  /* Use the Syscall "0" to identify whether the syscall is enabled,
+   * if the host tool is closed abnormally, use this bit to clear
+   * the active set.
+   */
+
+  if (!enable &&
+      NOTE_FILTER_SYSCALLMASK_ISSET(0, &g_sysview.syscall_marker))
+    {
+      NOTE_FILTER_SYSCALLMASK_ZERO(&g_sysview.syscall_marker);
+    }
+#endif
+
   return enable;
 }
 
 /****************************************************************************
- * Name: sysview_isenabled_irqhandler
+ * Name: sysview_isenabled_irq
  *
  * Description:
  *   Check whether the interrupt handler instrumentation is enabled.
@@ -198,6 +215,44 @@ static bool sysview_isenabled_irq(int irq, bool enter)
 #endif
 
 /****************************************************************************
+ * Name: sysview_isenabled_syscall
+ *
+ * Description:
+ *   Check whether the syscall instrumentation is enabled.
+ *
+ * Input Parameters:
+ *   nr - syscall number
+ *
+ * Returned Value:
+ *   True is returned if the instrumentation is enabled.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+static inline int sysview_isenabled_syscall(int nr)
+{
+#ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER
+  if (!sysview_isenabled())
+    {
+      return false;
+    }
+
+  /* If the syscall trace is disabled or the syscall number is masked,
+   * do nothing.
+   */
+
+  if ((g_sysview.mode.flag & NOTE_FILTER_MODE_FLAG_SYSCALL) == 0 ||
+      NOTE_FILTER_SYSCALLMASK_ISSET(nr, &g_sysview.syscall_mask))
+    {
+      return false;
+    }
+#endif
+
+  return true;
+}
+#endif
+
+/****************************************************************************
  * Public Functions
  ****************************************************************************/
 
@@ -310,6 +365,58 @@ void sched_note_irqhandler(int irq, FAR void *handler, 
bool enter)
 }
 #endif
 
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+void sched_note_syscall_enter(int nr, int argc, ...)
+{
+  nr -= CONFIG_SYS_RESERVED;
+
+  if (sysview_isenabled_syscall(nr) == 0)
+    {
+      return;
+    }
+
+  /* Set the name marker if the current syscall nr is not active */
+
+  if (NOTE_FILTER_SYSCALLMASK_ISSET(nr, &g_sysview.syscall_marker) == 0)
+    {
+      /* Set the name marker */
+
+      SEGGER_SYSVIEW_NameMarker(nr, g_funcnames[nr]);
+
+      /* Mark the syscall active */
+
+      NOTE_FILTER_SYSCALLMASK_SET(nr, &g_sysview.syscall_marker);
+
+      /* Use the Syscall "0" to identify whether the syscall is enabled,
+       * if the host tool is closed abnormally, use this bit to clear
+       * the active set.
+       */
+
+      if (NOTE_FILTER_SYSCALLMASK_ISSET(0, &g_sysview.syscall_marker) == 0)
+        {
+          NOTE_FILTER_SYSCALLMASK_SET(0, &g_sysview.syscall_marker);
+        }
+    }
+
+  SEGGER_SYSVIEW_MarkStart(nr);
+}
+
+void sched_note_syscall_leave(int nr, uintptr_t result)
+{
+  nr -= CONFIG_SYS_RESERVED;
+
+  if (sysview_isenabled_syscall(nr) == 0)
+    {
+      return;
+    }
+
+  if (NOTE_FILTER_SYSCALLMASK_ISSET(nr, &g_sysview.syscall_marker) != 0)
+    {
+      SEGGER_SYSVIEW_MarkStop(nr);
+    }
+}
+#endif
+
 /****************************************************************************
  * Name: sysview_get_interrupt_id
  *
@@ -490,4 +597,50 @@ void sched_note_filter_irq(struct note_filter_irq_s *oldf,
 }
 #endif
 
+/****************************************************************************
+ * Name: sched_note_filter_syscall
+ *
+ * Description:
+ *   Set and get syscall filter setting
+ *   (Same as NOTECTL_GETSYSCALLFILTER / NOTECTL_SETSYSCALLFILTER ioctls)
+ *
+ * Input Parameters:
+ *   oldf - A writable pointer to struct note_filter_syscall_s to get
+ *          current syscall filter setting
+ *          If 0, no data is written.
+ *   newf - A read-only pointer to struct note_filter_syscall_s of the
+ *          new syscall filter setting
+ *          If 0, the setting is not updated.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+void sched_note_filter_syscall(struct note_filter_syscall_s *oldf,
+                               struct note_filter_syscall_s *newf)
+{
+  irqstate_t flags;
+
+  flags = spin_lock_irqsave(NULL);
+
+  if (oldf != NULL)
+    {
+      /* Return the current filter setting */
+
+      *oldf = g_sysview.syscall_mask;
+    }
+
+  if (newf != NULL)
+    {
+      /* Replace the syscall filter mask by the provided setting */
+
+      g_sysview.syscall_mask = *newf;
+    }
+
+  spin_unlock_irqrestore(NULL, flags);
+}
 #endif
+
+#endif /* CONFIG_SCHED_INSTRUMENTATION_FILTER */

Reply via email to