You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2023/08/11 05:27:24 UTC

[nuttx] 01/07: drivers/noteram: move trace_dump to noteram

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/nuttx.git

commit 39001e370546914d8338449da67c62c41b97ffde
Author: yinshengkai <yi...@xiaomi.com>
AuthorDate: Fri Aug 11 10:31:02 2023 +0800

    drivers/noteram: move trace_dump to noteram
    
    Signed-off-by: yinshengkai <yi...@xiaomi.com>
---
 drivers/note/noteram_driver.c | 737 ++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 705 insertions(+), 32 deletions(-)

diff --git a/drivers/note/noteram_driver.c b/drivers/note/noteram_driver.c
index 2d0b116800..ec7cbc9ba7 100644
--- a/drivers/note/noteram_driver.c
+++ b/drivers/note/noteram_driver.c
@@ -29,6 +29,7 @@
 #include <fcntl.h>
 #include <assert.h>
 #include <errno.h>
+#include <stdio.h>
 #include <string.h>
 
 #include <nuttx/spinlock.h>
@@ -39,6 +40,32 @@
 #include <nuttx/note/noteram_driver.h>
 #include <nuttx/fs/fs.h>
 
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+#  ifdef CONFIG_LIB_SYSCALL
+#    include <syscall.h>
+#  else
+#    define CONFIG_LIB_SYSCALL
+#    include <syscall.h>
+#    undef CONFIG_LIB_SYSCALL
+#  endif
+#endif
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define NCPUS CONFIG_SMP_NCPUS
+
+/* Renumber idle task PIDs
+ *  In NuttX, PID number less than NCPUS are idle tasks.
+ *  In Linux, there is only one idle task of PID 0.
+ */
+
+#define get_pid(pid) ((pid) < NCPUS ? 0 : (pid))
+
+#define get_task_state(s)                                                    \
+  ((s) == 0 ? 'X' : ((s) <= LAST_READY_TO_RUN_STATE ? 'R' : 'S'))
+
 /****************************************************************************
  * Private Types
  ****************************************************************************/
@@ -55,17 +82,54 @@ struct noteram_driver_s
   spinlock_t lock;
 };
 
+/* The structure to hold the context data of trace dump */
+
+struct noteram_dump_cpu_context_s
+{
+  int intr_nest;            /* Interrupt nest level */
+  bool pendingswitch;       /* sched_switch pending flag */
+  int current_state;        /* Task state of the current line */
+  pid_t current_pid;        /* Task PID of the current line */
+  pid_t next_pid;           /* Task PID of the next line */
+  uint8_t current_priority; /* Task Priority of the current line */
+  uint8_t next_priority;    /* Task Priority of the next line */
+};
+
+struct noteram_dump_task_context_s
+{
+  FAR struct noteram_dump_task_context_s *next;
+  pid_t pid;                            /* Task PID */
+  int syscall_nest;                     /* Syscall nest level */
+  char name[CONFIG_TASK_NAME_SIZE + 1]; /* Task name (with NULL terminator) */
+};
+
+struct noteram_dump_context_s
+{
+  int buflen;           /* The length of the dumped data */
+  char buffer[256];     /* Buffer to hold the line to be dumped */
+  struct noteram_dump_cpu_context_s cpu[NCPUS];
+  FAR struct noteram_dump_task_context_s *task;
+};
+
 /****************************************************************************
  * Private Function Prototypes
  ****************************************************************************/
 
 static int noteram_open(FAR struct file *filep);
+static int noteram_close(FAR struct file *filep);
 static ssize_t noteram_read(FAR struct file *filep,
                             FAR char *buffer, size_t buflen);
 static int noteram_ioctl(struct file *filep, int cmd, unsigned long arg);
 static void noteram_add(FAR struct note_driver_s *drv,
                         FAR const void *note, size_t len);
 
+static void
+noteram_dump_init_context(FAR struct noteram_dump_context_s *ctx);
+static void
+noteram_dump_fini_context(FAR struct noteram_dump_context_s *ctx);
+static int noteram_dump_one(FAR uint8_t *p,
+                            FAR struct noteram_dump_context_s *ctx);
+
 /****************************************************************************
  * Private Data
  ****************************************************************************/
@@ -73,7 +137,7 @@ static void noteram_add(FAR struct note_driver_s *drv,
 static const struct file_operations g_noteram_fops =
 {
   noteram_open,  /* open */
-  NULL,          /* close */
+  noteram_close, /* close */
   noteram_read,  /* read */
   NULL,          /* write */
   NULL,          /* seek */
@@ -391,14 +455,29 @@ static ssize_t noteram_size(FAR struct noteram_driver_s *drv)
 
 static int noteram_open(FAR struct file *filep)
 {
-  FAR struct noteram_driver_s *drv =
-    (FAR struct noteram_driver_s *)filep->f_inode->i_private;
+  FAR struct noteram_dump_context_s *ctx;
+  FAR struct noteram_driver_s *drv = (FAR struct noteram_driver_s *)
+                                     filep->f_inode->i_private;
 
   /* Reset the read index of the circular buffer */
 
-  filep->f_priv = drv;
   drv->ni_read = drv->ni_tail;
+  ctx = kmm_zalloc(sizeof(*ctx));
+  if (ctx == NULL)
+    {
+      return -ENOMEM;
+    }
 
+  filep->f_priv = ctx;
+  noteram_dump_init_context(ctx);
+  return OK;
+}
+
+int noteram_close(FAR struct file *filep)
+{
+  FAR struct noteram_dump_context_s *ctx = filep->f_priv;
+  noteram_dump_fini_context(ctx);
+  kmm_free(ctx);
   return OK;
 }
 
@@ -406,49 +485,71 @@ static int noteram_open(FAR struct file *filep)
  * Name: noteram_read
  ****************************************************************************/
 
-static ssize_t noteram_read(FAR struct file *filep,
-                            FAR char *buffer, size_t buflen)
+static ssize_t noteram_read(FAR struct file *filep, FAR char *buffer,
+                            size_t buflen)
 {
-  ssize_t notelen;
-  ssize_t retlen ;
+  ssize_t ret = -EFBIG;
+  ssize_t retlen = 0;
+  uint8_t note[32];
   irqstate_t flags;
+  FAR struct noteram_dump_context_s *ctx = filep->f_priv;
   FAR struct noteram_driver_s *drv =
-    (FAR struct noteram_driver_s *)filep->f_priv;
+    (FAR struct noteram_driver_s *)filep->f_inode->i_private;
 
-  DEBUGASSERT(filep != 0 && buffer != NULL && buflen > 0);
+  /* If we have parsed but unread data last time,
+   * we should save the last data first
+   */
+
+  if (ctx->buflen > 0)
+    {
+      if (ctx->buflen > buflen)
+        {
+          goto errout;
+        }
+
+      strlcpy(buffer, ctx->buffer, buflen);
+      retlen = ctx->buflen;
+      buffer += ctx->buflen;
+      buflen -= ctx->buflen;
+    }
 
   /* Then loop, adding as many notes as possible to the user buffer. */
 
-  retlen = 0;
-  flags = spin_lock_irqsave_wo_note(&drv->lock);
   do
     {
       /* Get the next note (removing it from the buffer) */
 
-      notelen = noteram_get(drv, (FAR uint8_t *)buffer, buflen);
-      if (notelen < 0)
+      flags = spin_lock_irqsave_wo_note(&drv->lock);
+      ret = noteram_get(drv, note, sizeof(note));
+      spin_unlock_irqrestore_wo_note(&drv->lock, flags);
+      if (ret <= 0)
         {
-          /* We were unable to read the next note, probably because it will
-           * not fit into the user buffer.
-           */
+          ctx->buflen = 0;
+          break;
+        }
 
-          if (retlen == 0)
-            {
-              /* If nothing was read then report the error.  Otherwise,
-               * just silently drop the note.
-               */
+      /* Parse notes into text format */
 
-              retlen = notelen;
-            }
+      ctx->buflen = noteram_dump_one(note, ctx);
+
+      /* If the remaining space is insufficient,
+       * return the read data directly first
+       */
 
+      if (ctx->buflen > buflen)
+        {
+          ret = -EFBIG;
           break;
         }
 
       /* Update pointers from the note that was transferred */
 
-      retlen += notelen;
-      buffer += notelen;
-      buflen -= notelen;
+      strlcpy(buffer, ctx->buffer, buflen);
+
+      retlen += ctx->buflen;
+      buffer += ctx->buflen;
+      buflen -= ctx->buflen;
+      ctx->buflen = 0;
 
       /* Will the next note fit?  There is a race here and even if the next
        * note will fit, it may fail still when noteram_get() is called.
@@ -457,12 +558,14 @@ static ssize_t noteram_read(FAR struct file *filep,
        * trying to get the next note (which would cause it to be deleted).
        */
 
-      notelen = noteram_size(drv);
+      ret = noteram_size(drv);
     }
-  while (notelen > 0 && notelen <= buflen);
+  while (ret > 0);
 
-  spin_unlock_irqrestore_wo_note(&drv->lock, flags);
-  return retlen;
+  /* If no data is read, an error code is returned */
+
+errout:
+  return retlen ? retlen : ret;
 }
 
 /****************************************************************************
@@ -473,7 +576,7 @@ static int noteram_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
 {
   int ret = -ENOSYS;
   FAR struct noteram_driver_s *drv =
-    (FAR struct noteram_driver_s *)filep->f_priv;
+    (FAR struct noteram_driver_s *)filep->f_inode->i_private;
   irqstate_t flags = spin_lock_irqsave_wo_note(&drv->lock);
 
   /* Handle the ioctl commands */
@@ -626,6 +729,576 @@ static void noteram_add(FAR struct note_driver_s *driver,
   spin_unlock_irqrestore_wo_note(&drv->lock, flags);
 }
 
+/****************************************************************************
+ * Name: noteram_dump_unflatten
+ ****************************************************************************/
+
+static void noteram_dump_unflatten(FAR void *dst, FAR uint8_t *src,
+                                   size_t len)
+{
+#ifdef CONFIG_ENDIAN_BIG
+  FAR uint8_t *end = (FAR uint8_t *)dst + len - 1;
+  while (len-- > 0)
+    {
+      *end-- = *src++;
+    }
+#else
+  memcpy(dst, src, len);
+#endif
+}
+
+/****************************************************************************
+ * Name: noteram_dump_init_context
+ ****************************************************************************/
+
+static void noteram_dump_init_context(FAR struct noteram_dump_context_s *ctx)
+{
+  int cpu;
+
+  /* Initialize the trace dump context */
+
+  for (cpu = 0; cpu < NCPUS; cpu++)
+    {
+      ctx->cpu[cpu].intr_nest = 0;
+      ctx->cpu[cpu].pendingswitch = false;
+      ctx->cpu[cpu].current_state = TSTATE_TASK_RUNNING;
+      ctx->cpu[cpu].current_pid = -1;
+      ctx->cpu[cpu].next_pid = -1;
+      ctx->cpu[cpu].current_priority = -1;
+      ctx->cpu[cpu].next_priority = -1;
+    }
+
+  ctx->task = NULL;
+}
+
+/****************************************************************************
+ * Name: noteram_dump_fini_context
+ ****************************************************************************/
+
+static void noteram_dump_fini_context(FAR struct noteram_dump_context_s *ctx)
+{
+  FAR struct noteram_dump_task_context_s *tctx;
+  FAR struct noteram_dump_task_context_s *ntctx;
+
+  /* Finalize the trace dump context */
+
+  tctx = ctx->task;
+  ctx->task = NULL;
+  while (tctx != NULL)
+    {
+      ntctx = tctx->next;
+      free(tctx);
+      tctx = ntctx;
+    }
+}
+
+/****************************************************************************
+ * Name: copy_task_name
+ ****************************************************************************/
+
+#if CONFIG_TASK_NAME_SIZE > 0
+static void copy_task_name(FAR char *dst, FAR const char *src)
+{
+  char c;
+  int i;
+
+  /* Replace space to underline
+   * Text trace data format cannot use a space as a task name.
+   */
+
+  for (i = 0; i < CONFIG_TASK_NAME_SIZE; i++)
+    {
+      c = *src++;
+      if (c == '\0')
+        {
+          break;
+        }
+
+      *dst++ = (c == ' ') ? '_' : c;
+    }
+
+  *dst = '\0';
+}
+#endif
+
+/****************************************************************************
+ * Name: get_task_context
+ ****************************************************************************/
+
+FAR static struct noteram_dump_task_context_s *
+get_task_context(pid_t pid, FAR struct noteram_dump_context_s *ctx)
+{
+  FAR struct noteram_dump_task_context_s **tctxp;
+  tctxp = &ctx->task;
+  while (*tctxp != NULL)
+    {
+      if ((*tctxp)->pid == pid)
+        {
+          return *tctxp;
+        }
+
+      tctxp = &((*tctxp)->next);
+    }
+
+  /* Create new trace dump task context */
+
+  *tctxp = (FAR struct noteram_dump_task_context_s *)malloc(
+      sizeof(struct noteram_dump_task_context_s));
+  if (*tctxp != NULL)
+    {
+      (*tctxp)->next = NULL;
+      (*tctxp)->pid = pid;
+      (*tctxp)->syscall_nest = 0;
+      (*tctxp)->name[0] = '\0';
+
+#ifdef NOTERAM_GETTASKNAME
+        {
+          struct noteram_get_taskname_s tnm;
+          int res;
+
+          res = note_get_taskname(pid, tnm.taskname);
+          if (res == 0)
+            {
+              copy_task_name((*tctxp)->name, tnm.taskname);
+            }
+        }
+#endif
+    }
+
+  return *tctxp;
+}
+
+/****************************************************************************
+ * Name: get_task_name
+ ****************************************************************************/
+
+static const char *get_task_name(pid_t pid,
+                                 FAR struct noteram_dump_context_s *ctx)
+{
+  FAR struct noteram_dump_task_context_s *tctx;
+
+  tctx = get_task_context(pid, ctx);
+  if (tctx != NULL && tctx->name[0] != '\0')
+    {
+      return tctx->name;
+    }
+
+  return "<noname>";
+}
+
+/****************************************************************************
+ * Name: noteram_dump_header
+ ****************************************************************************/
+
+static int noteram_dump_header(FAR char *offset,
+                               FAR struct note_common_s *note,
+                               FAR struct noteram_dump_context_s *ctx)
+{
+  pid_t pid;
+  uint32_t nsec;
+  uint32_t sec;
+  int ret;
+
+  noteram_dump_unflatten(&nsec, note->nc_systime_nsec, sizeof(nsec));
+  noteram_dump_unflatten(&sec, note->nc_systime_sec, sizeof(sec));
+#ifdef CONFIG_SMP
+  int cpu = note->nc_cpu;
+#else
+  int cpu = 0;
+#endif
+
+  noteram_dump_unflatten(&pid, note->nc_pid, sizeof(pid));
+
+  ret = sprintf(offset, "%8s-%-3u [%d] %3" PRIu32 ".%09" PRIu32 ": ",
+                get_task_name(pid, ctx), get_pid(pid), cpu, sec, nsec);
+  return ret;
+}
+
+#if (defined CONFIG_SCHED_INSTRUMENTATION_SWITCH)                            \
+    || (defined CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER)
+/****************************************************************************
+ * Name: noteram_dump_sched_switch
+ ****************************************************************************/
+
+static int noteram_dump_sched_switch(FAR char *offset,
+                                     FAR struct note_common_s *note,
+                                     FAR struct noteram_dump_context_s *ctx)
+{
+  FAR struct noteram_dump_cpu_context_s *cctx;
+  uint8_t current_priority;
+  uint8_t next_priority;
+  pid_t current_pid;
+  pid_t next_pid;
+  int ret;
+#ifdef CONFIG_SMP
+  int cpu = note->nc_cpu;
+#else
+  int cpu = 0;
+#endif
+
+  cctx = &ctx->cpu[cpu];
+  current_pid = cctx->current_pid;
+  next_pid = cctx->next_pid;
+
+  current_priority = cctx->current_priority;
+  next_priority = cctx->next_priority;
+
+  ret = sprintf(offset,
+                "sched_switch: "
+                "prev_comm=%s prev_pid=%u prev_prio=%u prev_state=%c ==> "
+                "next_comm=%s next_pid=%u next_prio=%u\n",
+                get_task_name(current_pid, ctx), get_pid(current_pid),
+                current_priority, get_task_state(cctx->current_state),
+                get_task_name(next_pid, ctx), get_pid(next_pid),
+                next_priority);
+
+  cctx->current_pid = cctx->next_pid;
+  cctx->current_priority = cctx->next_priority;
+  cctx->pendingswitch = false;
+  return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: noteram_dump_one
+ ****************************************************************************/
+
+static int noteram_dump_one(FAR uint8_t *p,
+                            FAR struct noteram_dump_context_s *ctx)
+{
+  FAR struct note_common_s *note = (FAR struct note_common_s *)p;
+  FAR struct noteram_dump_cpu_context_s *cctx;
+  FAR char *buffer = (FAR char *)ctx->buffer;
+  FAR char *offset = (FAR char *)ctx->buffer;
+  pid_t pid;
+#ifdef CONFIG_SMP
+  int cpu = note->nc_cpu;
+#else
+  int cpu = 0;
+#endif
+
+  cctx = &ctx->cpu[cpu];
+  noteram_dump_unflatten(&pid, note->nc_pid, sizeof(pid));
+
+  if (cctx->current_pid < 0)
+    {
+      cctx->current_pid = pid;
+    }
+
+  /* Output one note */
+
+  switch (note->nc_type)
+    {
+    case NOTE_START:
+      {
+#if CONFIG_TASK_NAME_SIZE > 0
+        FAR struct note_start_s *nst = (FAR struct note_start_s *)p;
+        FAR struct noteram_dump_task_context_s *tctx;
+
+        tctx = get_task_context(pid, ctx);
+        if (tctx != NULL)
+          {
+            copy_task_name(tctx->name, nst->nst_name);
+          }
+#endif
+
+        offset += noteram_dump_header(offset, note, ctx);
+        offset += sprintf(offset,
+                          "sched_wakeup_new: comm=%s pid=%d target_cpu=%d\n",
+                          get_task_name(pid, ctx), get_pid(pid), cpu);
+      }
+      break;
+
+    case NOTE_STOP:
+      {
+        /* This note informs the task to be stopped.
+         * Change current task state for the succeeding NOTE_RESUME.
+         */
+
+        cctx->current_state = 0;
+      }
+      break;
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH
+    case NOTE_SUSPEND:
+      {
+        FAR struct note_suspend_s *nsu = (FAR struct note_suspend_s *)p;
+
+        /* This note informs the task to be suspended.
+         * Preserve the information for the succeeding NOTE_RESUME.
+         */
+
+        cctx->current_state = nsu->nsu_state;
+      }
+      break;
+
+    case NOTE_RESUME:
+      {
+        /* This note informs the task to be resumed.
+         * The task switch timing depends on the running context.
+         */
+
+        cctx->next_pid = pid;
+        cctx->next_priority = note->nc_priority;
+
+        if (cctx->intr_nest == 0)
+          {
+            /* If not in the interrupt context, the task switch is
+             * executed immediately.
+             */
+
+            offset += noteram_dump_header(offset, note, ctx);
+            offset += noteram_dump_sched_switch(offset, note, ctx);
+          }
+        else
+          {
+            /* If in the interrupt context, the task switch is postponed
+             * until leaving the interrupt handler.
+             */
+
+            offset += noteram_dump_header(offset, note, ctx);
+            offset += sprintf(offset,
+                              "sched_waking: comm=%s pid=%d target_cpu=%d\n",
+                              get_task_name(cctx->next_pid, ctx),
+                              get_pid(cctx->next_pid), cpu);
+            cctx->pendingswitch = true;
+          }
+      }
+      break;
+#endif
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+    case NOTE_SYSCALL_ENTER:
+      {
+        FAR struct note_syscall_enter_s *nsc;
+        FAR struct noteram_dump_task_context_s *tctx;
+        int i;
+        int j;
+        uintptr_t arg;
+
+        /* Exclude the case of syscall issued by an interrupt handler and
+         * nested syscalls to correct tracecompass display.
+         */
+
+        if (cctx->intr_nest > 0)
+          {
+            break;
+          }
+
+        tctx = get_task_context(pid, ctx);
+        if (tctx == NULL)
+          {
+            break;
+          }
+
+        tctx->syscall_nest++;
+        if (tctx->syscall_nest > 1)
+          {
+            break;
+          }
+
+        nsc = (FAR struct note_syscall_enter_s *)p;
+        if (nsc->nsc_nr < CONFIG_SYS_RESERVED ||
+            nsc->nsc_nr >= SYS_maxsyscall)
+          {
+            break;
+          }
+
+        offset += noteram_dump_header(offset, note, ctx);
+        offset += sprintf(offset, "sys_%s(",
+                          g_funcnames[nsc->nsc_nr - CONFIG_SYS_RESERVED]);
+
+        for (i = j = 0; i < nsc->nsc_argc; i++)
+          {
+            noteram_dump_unflatten(&arg, nsc->nsc_args, sizeof(arg));
+            if (i == 0)
+              {
+                offset += sprintf(offset, "arg%d: 0x%" PRIxPTR, i, arg);
+              }
+            else
+              {
+                offset += sprintf(offset, ", arg%d: 0x%" PRIxPTR, i, arg);
+              }
+          }
+
+        offset += sprintf(offset, ")\n");
+      }
+      break;
+
+    case NOTE_SYSCALL_LEAVE:
+      {
+        FAR struct note_syscall_leave_s *nsc;
+        FAR struct noteram_dump_task_context_s *tctx;
+        uintptr_t result;
+
+        /* Exclude the case of syscall issued by an interrupt handler and
+         * nested syscalls to correct tracecompass display.
+         */
+
+        if (cctx->intr_nest > 0)
+          {
+            break;
+          }
+
+        tctx = get_task_context(pid, ctx);
+        if (tctx == NULL)
+          {
+            break;
+          }
+
+        tctx->syscall_nest--;
+        if (tctx->syscall_nest > 0)
+          {
+            break;
+          }
+
+        tctx->syscall_nest = 0;
+
+        nsc = (FAR struct note_syscall_leave_s *)p;
+        if (nsc->nsc_nr < CONFIG_SYS_RESERVED ||
+            nsc->nsc_nr >= SYS_maxsyscall)
+          {
+            break;
+          }
+
+        offset += noteram_dump_header(offset, note, ctx);
+        noteram_dump_unflatten(&result, nsc->nsc_result, sizeof(result));
+        offset += sprintf(offset, "sys_%s -> 0x%" PRIxPTR "\n",
+                          g_funcnames[nsc->nsc_nr - CONFIG_SYS_RESERVED],
+                          result);
+      }
+      break;
+#endif
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER
+    case NOTE_IRQ_ENTER:
+      {
+        FAR struct note_irqhandler_s *nih;
+
+        nih = (FAR struct note_irqhandler_s *)p;
+        offset += noteram_dump_header(offset, note, ctx);
+        offset += sprintf(offset, "irq_handler_entry: irq=%u name=%d\n",
+                          nih->nih_irq, nih->nih_irq);
+        cctx->intr_nest++;
+      }
+      break;
+
+    case NOTE_IRQ_LEAVE:
+      {
+        FAR struct note_irqhandler_s *nih;
+
+        nih = (FAR struct note_irqhandler_s *)p;
+        offset += noteram_dump_header(offset, note, ctx);
+        offset += sprintf(offset, "irq_handler_exit: irq=%u ret=handled\n",
+                nih->nih_irq);
+        cctx->intr_nest--;
+
+        if (cctx->intr_nest <= 0)
+          {
+            cctx->intr_nest = 0;
+            if (cctx->pendingswitch)
+              {
+                /* If the pending task switch exists, it is executed here */
+
+                offset += noteram_dump_header(offset, note, ctx);
+                offset += noteram_dump_sched_switch(offset, note, ctx);
+              }
+          }
+      }
+      break;
+#endif
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION
+    case NOTE_CSECTION_ENTER:
+    case NOTE_CSECTION_LEAVE:
+      {
+        struct note_csection_s *ncs;
+        ncs = (FAR struct note_csection_s *)p;
+        offset += noteram_dump_header(offset, &ncs->ncs_cmn, ctx);
+        offset += sprintf(offset,
+                          "tracing_mark_write: %c|%d|"
+                          "critical_section\n",
+                           note->nc_type == NOTE_CSECTION_ENTER ?
+                           'B' : 'E', pid);
+      }
+      break;
+#endif
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION
+    case NOTE_PREEMPT_LOCK:
+    case NOTE_PREEMPT_UNLOCK:
+      {
+        struct note_preempt_s *npr;
+        int16_t count;
+        npr = (FAR struct note_preempt_s *)p;
+        noteram_dump_unflatten(&count, npr->npr_count, sizeof(count));
+        offset += noteram_dump_header(offset, &npr->npr_cmn, ctx);
+        offset += sprintf(offset, "tracing_mark_write: "
+                          "%c|%d|sched_lock:%d\n",
+                          note->nc_type == NOTE_PREEMPT_LOCK ?
+                          'B' : 'E', pid, count);
+      }
+      break;
+#endif
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_DUMP
+    case NOTE_DUMP_STRING:
+      {
+        FAR struct note_string_s *nst;
+        uintptr_t ip;
+
+        nst = (FAR struct note_string_s *)p;
+        offset += noteram_dump_header(offset, note, ctx);
+        noteram_dump_unflatten(&ip, nst->nst_ip, sizeof(ip));
+
+        if (nst->nst_data[1] == '\0' &&
+            (nst->nst_data[0] == 'B' || nst->nst_data[0] == 'E'))
+          {
+            offset += sprintf(offset, "tracing_mark_write: %c|%d|%pS\n",
+                              nst->nst_data[0], pid, (FAR void *)ip);
+          }
+        else
+          {
+            offset += sprintf(offset, "tracing_mark_write: %s\n",
+                    nst->nst_data);
+          }
+      }
+      break;
+
+    case NOTE_DUMP_BINARY:
+      {
+        FAR struct note_binary_s *nbi;
+        uint8_t count;
+        uintptr_t ip;
+        int i;
+
+        nbi = (FAR struct note_binary_s *)p;
+        offset += noteram_dump_header(offset, note, ctx);
+        count = note->nc_length - sizeof(struct note_binary_s) + 1;
+
+        noteram_dump_unflatten(&ip, nbi->nbi_ip, sizeof(ip));
+
+        offset += sprintf(offset, "0x%" PRIdPTR ": event=%u count=%u", ip,
+                          nbi->nbi_event, count);
+        for (i = 0; i < count; i++)
+          {
+            offset += sprintf(offset, " 0x%x", nbi->nbi_data[i]);
+          }
+
+        offset += sprintf(offset, "\n");
+      }
+      break;
+#endif
+
+    default:
+      break;
+    }
+
+  /* Return the length of the processed note */
+
+  return offset - buffer;
+}
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/