xiaoxiang781216 commented on a change in pull request #1377:
URL: https://github.com/apache/incubator-nuttx/pull/1377#discussion_r465116503



##########
File path: sched/sched/sched_note.c
##########
@@ -186,149 +236,159 @@ void note_spincommon(FAR struct tcb_s *tcb,
 #endif
 
 /****************************************************************************
- * Name: note_length
+ * Name: note_add
  *
  * Description:
- *   Length of data currently in circular buffer.
+ *   Put the variable length note to the note stream
  *
  * Input Parameters:
- *   None
+ *   note    - Pointer to the note to be added
+ *   notelen - Length of the note
  *
  * Returned Value:
- *   Length of data currently in circular buffer.
+ *   None
+ *
+ * Assumptions:
+ *   We are within a critical section.
  *
  ****************************************************************************/
 
-#if defined(CONFIG_SCHED_NOTE_GET) || defined(CONFIG_DEBUG_ASSERTIONS)
-static unsigned int note_length(void)
+static void note_add(FAR const uint8_t *note, uint8_t notelen)
 {
-  unsigned int head = g_note_info.ni_head;
-  unsigned int tail = g_note_info.ni_tail;
+#ifdef CONFIG_SMP
+  /* Ignore notes that are not in the set of monitored CPUs */
 
-  if (tail > head)
+  if ((CONFIG_SCHED_INSTRUMENTATION_CPUSET & (1 << this_cpu())) == 0)
     {
-      head += CONFIG_SCHED_NOTE_BUFSIZE;
+      /* Not in the set of monitored CPUs.  Do not log the note. */
+
+      return;
     }
+#endif
 
-  return head - tail;
-}
+#ifdef CONFIG_SMP
+  irqstate_t flags = up_irq_save();
+  spin_lock_wo_note(&g_note_lock);
 #endif
 
+  /* Loop until all bytes have been transferred */
+
+  if (g_sched_note_stream != NULL)
+    {
+      while (notelen > 0)
+        {
+          (g_sched_note_stream)->public.put(&g_sched_note_stream->public,

Review comment:
       The performance is poor, how about we make note_add as the interface 
between the common code and the trransport layer? so the hardware solution and 
software solution just need implement note_add.

##########
File path: include/nuttx/syslog/note_driver.h
##########
@@ -27,22 +27,283 @@
 
 #include <nuttx/config.h>
 
+#include <sys/types.h>
+#include <stdint.h>
+
+#include <nuttx/sched_note.h>
+#include <nuttx/fs/ioctl.h>
+
 #ifdef CONFIG_SCHED_INSTRUMENTATION
 
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
 
+/* IOCTL Commands ***********************************************************/
+
+/* TRIOC_START
+ *              - Start task tracing
+ *                Argument: Ignored
+ * TRIOC_STOP
+ *              - Stop task tracing
+ *                Argument: Ignored
+ * TRIOC_GETMODE
+ *              - Get task trace mode
+ *                Argument: A writable pointer to struct note_trace_mode_s
+ * TRIOC_SETMODE
+ *              - Set task trace mode
+ *                Argument: A read-only pointer to struct note_trace_mode_s
+ * TRIOC_GETSYSCALLFILTER
+ *              - Get syscall trace filter setting
+ *                Argument: A writable pointer to struct
+ *                          note_trace_syscallfilter_s
+ * TRIOC_SETSYSCALLFILTER
+ *              - Set syscall trace filter setting
+ *                Argument: A read-only pointer to struct
+ *                          note_trace_syscallfilter_s
+ * TRIOC_GETIRQFILTER
+ *              - Get IRQ trace filter setting
+ *                Argument: A writable pointer to struct
+ *                          note_trace_irqfilter_s
+ * TRIOC_SETIRQFILTER
+ *              - Set IRQ trace filter setting
+ *                Argument: A read-only pointer to struct
+ *                          note_trace_irqfilter_s
+ * TRIOC_GETTASKNAME
+ *              - Get task name string
+ *                Argument: A writable pointer to struct note_get_taskname_s
+ *                Result:   If -ESRCH, the corresponding task name doesn't
+ *                          exist.
+ */
+
+#if defined(CONFIG_SCHED_INSTRUMENTATION_FILTER) && defined(CONFIG_DRIVER_NOTE)
+
+#define _NOTETRACEBASE        (0xfe00)
+#define _NOTETRACEIOCVALID(c) (_IOC_TYPE(c) == _NOTETRACEBASE)
+#define _NOTETRACEIOC(nr)     _IOC(_NOTETRACEBASE, nr)
+
+#define TRIOC_START            _NOTETRACEIOC(0x01)
+#define TRIOC_STOP             _NOTETRACEIOC(0x02)
+#define TRIOC_GETMODE          _NOTETRACEIOC(0x03)
+#define TRIOC_SETMODE          _NOTETRACEIOC(0x04)
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+#define TRIOC_GETSYSCALLFILTER _NOTETRACEIOC(0x05)
+#define TRIOC_SETSYSCALLFILTER _NOTETRACEIOC(0x06)
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER
+#define TRIOC_GETIRQFILTER     _NOTETRACEIOC(0x07)
+#define TRIOC_SETIRQFILTER     _NOTETRACEIOC(0x08)
+#endif
+#ifdef NOTE_FEATURE_TASK_NAME
+#define TRIOC_GETTASKNAME      _NOTETRACEIOC(0x09)
+#endif
+
+#endif
+
 /****************************************************************************
  * Public Types
  ****************************************************************************/
 
+#ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER

Review comment:
       should the follow snippet belong nuttx/note.h?

##########
File path: sched/sched/sched_note.c
##########
@@ -361,6 +421,13 @@ void sched_note_start(FAR struct tcb_s *tcb)
   int namelen;
 #endif
 
+#ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER
+  if (!g_note_filter.enable)

Review comment:
       should we move this check to sched_note_add? so all duplication can be 
removed.

##########
File path: drivers/syslog/note_driver.c
##########
@@ -79,10 +107,29 @@ static const struct file_operations note_fops =
  * Private Functions
  ****************************************************************************/
 
+/****************************************************************************
+ * Name: note_open
+ ****************************************************************************/
+
+#ifdef NOTE_FEATURE_BUFFER_REWINDABLE
+static int note_open(FAR struct file *filep)
+{
+  if ((filep->f_oflags & O_ACCMODE) != O_WRONLY)
+    {
+      /* Reset the pointer to read the trace data */
+
+      sched_note_trace_stop();

Review comment:
       Why stop the trace? we will lost some trace from here to the next enable.

##########
File path: sched/sched/sched_note.c
##########
@@ -631,144 +924,337 @@ void sched_note_irqhandler(int irq, FAR void *handler, 
bool enter)
 }
 #endif
 
+#ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER
+
 /****************************************************************************
- * Name: sched_note_get
+ * Name: sched_note_trace_start
  *
  * Description:
- *   Remove the next note from the tail of the circular buffer.  The note
- *   is also removed from the circular buffer to make room for further notes.
+ *   Start task tracing
+ *   (Same as TRIOC_START ioctl)
  *
  * Input Parameters:
- *   buffer - Location to return the next note
- *   buflen - The length of the user provided buffer.
+ *   None
  *
  * Returned Value:
- *   On success, the positive, non-zero length of the return note is
- *   provided.  Zero is returned only if the circular buffer is empty.  A
- *   negated errno value is returned in the event of any failure.
+ *   None
  *
  ****************************************************************************/
 
-#ifdef CONFIG_SCHED_NOTE_GET
-ssize_t sched_note_get(FAR uint8_t *buffer, size_t buflen)
+void sched_note_trace_start(void)
 {
-  FAR struct note_common_s *note;
-  irqstate_t flags;
-  unsigned int remaining;
-  unsigned int tail;
-  ssize_t notelen;
-  size_t circlen;
+  irqstate_t irq_mask;
 
-  DEBUGASSERT(buffer != NULL);
-  flags = enter_critical_section();
+  irq_mask = enter_critical_section();
 
-  /* Verify that the circular buffer is not empty */
+  g_note_filter.enable = true;
+#ifdef NOTE_FEATURE_TASK_NAME
+  note_taskname_init();
+#endif
 
-  circlen = note_length();
-  if (circlen <= 0)
+  if (g_sched_note_stream != NULL &&
+      g_sched_note_stream->bufclear != NULL)
     {
-      notelen = 0;
-      goto errout_with_csection;
+      (g_sched_note_stream)->bufclear(g_sched_note_stream,
+        (g_note_filter.mode.flag & TRIOC_MODE_FLAG_ONESHOT) != 0);
     }
 
-  /* Get the index to the tail of the circular buffer */
+  leave_critical_section(irq_mask);
+}
 
-  tail    = g_note_info.ni_tail;
-  DEBUGASSERT(tail < CONFIG_SCHED_NOTE_BUFSIZE);
+/****************************************************************************
+ * Name: sched_note_trace_stop
+ *
+ * Description:
+ *   Stop task tracing
+ *   (Same as TRIOC_STOP ioctl)
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
 
-  /* Get the length of the note at the tail index */
+void sched_note_trace_stop(void)
+{
+  irqstate_t irq_mask;
 
-  note    = (FAR struct note_common_s *)&g_note_info.ni_buffer[tail];
-  notelen = note->nc_length;
-  DEBUGASSERT(notelen <= circlen);
+  irq_mask = enter_critical_section();
 
-  /* Is the user buffer large enough to hold the note? */
+  g_note_filter.enable = false;
 
-  if (buflen < notelen)
+  if (g_sched_note_stream != NULL &&
+      g_sched_note_stream->bufrewind != NULL)
     {
-      /* Remove the large note so that we do not get constipated. */
+      (g_sched_note_stream)->bufrewind(g_sched_note_stream);
+    }
+
+  leave_critical_section(irq_mask);
+}
+
+/****************************************************************************
+ * Name: sched_note_trace_mode
+ *
+ * Description:
+ *   Set and get task trace mode.
+ *   (Same as TRIOC_GETMODE / TRIOC_SETMODE ioctls)
+ *
+ * Input Parameters:
+ *   oldm - A writable pointer to struct note_trace_mode_s to get current
+ *          trace mode
+ *          If 0, no data is written.
+ *   newm - A read-only pointer to struct note_trace_mode_s which holds the
+ *          new trace mode
+ *          If 0, the trace mode is not updated.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
 
-      note_remove();
+void sched_note_trace_mode(struct note_trace_mode_s *oldm,
+                           struct note_trace_mode_s *newm)
+{
+  irqstate_t irq_mask;
 
-      /* and return an error */
+  irq_mask = enter_critical_section();
 
-      notelen = -EFBIG;
-      goto errout_with_csection;
+  if (newm != NULL)
+    {
+      sched_note_trace_stop();
+      g_note_filter.mode = *newm;
+      if (g_sched_note_stream != NULL &&
+          g_sched_note_stream->bufclear != NULL)
+        {
+          (g_sched_note_stream)->bufclear(g_sched_note_stream,
+            (g_note_filter.mode.flag & TRIOC_MODE_FLAG_ONESHOT) != 0);
+        }
     }
 
-  /* Loop until the note has been transferred to the user buffer */
+  if (oldm != NULL)
+    {
+      *oldm = g_note_filter.mode;
+    }
 
-  remaining = (unsigned int)notelen;
-  while (remaining > 0)
+  leave_critical_section(irq_mask);
+}
+
+/****************************************************************************
+ * Name: sched_note_trace_syscallfilter
+ *
+ * Description:
+ *   Set and get syscall trace filter setting
+ *   (Same as TRIOC_GETSYSCALLFILTER / TRIOC_SETSYSCALLFILTER ioctls)
+ *
+ * Input Parameters:
+ *   oldf - A writable pointer to struct note_trace_syscallfilter_s to get
+ *          current syscall trace filter setting
+ *          If 0, no data is written.
+ *   newf - A read-only pointer to struct note_trace_syscallfilter_s of the
+ *          new syscall trace filter setting
+ *          If 0, the setting is not updated.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+void sched_note_trace_syscallfilter(struct note_trace_syscallfilter_s *oldf,
+                                    struct note_trace_syscallfilter_s *newf)
+{
+  irqstate_t irq_mask;
+  int i;
+  int nr;
+
+  irq_mask = enter_critical_section();
+
+  if (newf != NULL)
     {
-      /* Copy the next byte at the tail index */
+      sched_note_trace_stop();
 
-      *buffer++ = g_note_info.ni_buffer[tail];
+      /* Replace the syscall filter mask by the provided setting */
 
-      /* Adjust indices and counts */
+      memset(g_note_filter.syscall_mask, 0,
+             sizeof g_note_filter.syscall_mask);
+      for (i = 0; i < newf->nr_syscalls; i++)
+        {
+          nr = newf->syscalls[i];
 
-      tail = note_next(tail, 1);
-      remaining--;
+          if (nr < SYS_nsyscalls)
+            {
+              BITMASK_SET(g_note_filter.syscall_mask, nr);
+            }
+        }
     }
 
-  g_note_info.ni_tail = tail;
+  /* Count the number of filtered syscalls to calculate the requied size to
+   * get the current setting.
+   */
 
-errout_with_csection:
-  leave_critical_section(flags);
-  return notelen;
+  nr = 0;
+  for (i = 0; i < SYS_nsyscalls; i++)
+    {
+      if (BITMASK_CHECK(g_note_filter.syscall_mask, i))
+        {
+          nr++;
+        }
+    }
+
+  if (oldf != NULL)

Review comment:
       should move before the modification, otherwise we get the latest value 
not the old one.

##########
File path: sched/sched/sched_note.c
##########
@@ -631,144 +924,337 @@ void sched_note_irqhandler(int irq, FAR void *handler, 
bool enter)
 }
 #endif
 
+#ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER
+
 /****************************************************************************
- * Name: sched_note_get
+ * Name: sched_note_trace_start
  *
  * Description:
- *   Remove the next note from the tail of the circular buffer.  The note
- *   is also removed from the circular buffer to make room for further notes.
+ *   Start task tracing
+ *   (Same as TRIOC_START ioctl)
  *
  * Input Parameters:
- *   buffer - Location to return the next note
- *   buflen - The length of the user provided buffer.
+ *   None
  *
  * Returned Value:
- *   On success, the positive, non-zero length of the return note is
- *   provided.  Zero is returned only if the circular buffer is empty.  A
- *   negated errno value is returned in the event of any failure.
+ *   None
  *
  ****************************************************************************/
 
-#ifdef CONFIG_SCHED_NOTE_GET
-ssize_t sched_note_get(FAR uint8_t *buffer, size_t buflen)
+void sched_note_trace_start(void)
 {
-  FAR struct note_common_s *note;
-  irqstate_t flags;
-  unsigned int remaining;
-  unsigned int tail;
-  ssize_t notelen;
-  size_t circlen;
+  irqstate_t irq_mask;
 
-  DEBUGASSERT(buffer != NULL);
-  flags = enter_critical_section();
+  irq_mask = enter_critical_section();
 
-  /* Verify that the circular buffer is not empty */
+  g_note_filter.enable = true;
+#ifdef NOTE_FEATURE_TASK_NAME
+  note_taskname_init();
+#endif
 
-  circlen = note_length();
-  if (circlen <= 0)
+  if (g_sched_note_stream != NULL &&
+      g_sched_note_stream->bufclear != NULL)
     {
-      notelen = 0;
-      goto errout_with_csection;
+      (g_sched_note_stream)->bufclear(g_sched_note_stream,
+        (g_note_filter.mode.flag & TRIOC_MODE_FLAG_ONESHOT) != 0);
     }
 
-  /* Get the index to the tail of the circular buffer */
+  leave_critical_section(irq_mask);
+}
 
-  tail    = g_note_info.ni_tail;
-  DEBUGASSERT(tail < CONFIG_SCHED_NOTE_BUFSIZE);
+/****************************************************************************
+ * Name: sched_note_trace_stop
+ *
+ * Description:
+ *   Stop task tracing
+ *   (Same as TRIOC_STOP ioctl)
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
 
-  /* Get the length of the note at the tail index */
+void sched_note_trace_stop(void)
+{
+  irqstate_t irq_mask;
 
-  note    = (FAR struct note_common_s *)&g_note_info.ni_buffer[tail];
-  notelen = note->nc_length;
-  DEBUGASSERT(notelen <= circlen);
+  irq_mask = enter_critical_section();
 
-  /* Is the user buffer large enough to hold the note? */
+  g_note_filter.enable = false;
 
-  if (buflen < notelen)
+  if (g_sched_note_stream != NULL &&
+      g_sched_note_stream->bufrewind != NULL)
     {
-      /* Remove the large note so that we do not get constipated. */
+      (g_sched_note_stream)->bufrewind(g_sched_note_stream);
+    }
+
+  leave_critical_section(irq_mask);
+}
+
+/****************************************************************************
+ * Name: sched_note_trace_mode
+ *
+ * Description:
+ *   Set and get task trace mode.
+ *   (Same as TRIOC_GETMODE / TRIOC_SETMODE ioctls)
+ *
+ * Input Parameters:
+ *   oldm - A writable pointer to struct note_trace_mode_s to get current
+ *          trace mode
+ *          If 0, no data is written.
+ *   newm - A read-only pointer to struct note_trace_mode_s which holds the
+ *          new trace mode
+ *          If 0, the trace mode is not updated.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
 
-      note_remove();
+void sched_note_trace_mode(struct note_trace_mode_s *oldm,
+                           struct note_trace_mode_s *newm)
+{
+  irqstate_t irq_mask;
 
-      /* and return an error */
+  irq_mask = enter_critical_section();
 
-      notelen = -EFBIG;
-      goto errout_with_csection;
+  if (newm != NULL)
+    {
+      sched_note_trace_stop();
+      g_note_filter.mode = *newm;
+      if (g_sched_note_stream != NULL &&
+          g_sched_note_stream->bufclear != NULL)
+        {
+          (g_sched_note_stream)->bufclear(g_sched_note_stream,
+            (g_note_filter.mode.flag & TRIOC_MODE_FLAG_ONESHOT) != 0);
+        }
     }
 
-  /* Loop until the note has been transferred to the user buffer */
+  if (oldm != NULL)
+    {
+      *oldm = g_note_filter.mode;
+    }
 
-  remaining = (unsigned int)notelen;
-  while (remaining > 0)
+  leave_critical_section(irq_mask);
+}
+
+/****************************************************************************
+ * Name: sched_note_trace_syscallfilter
+ *
+ * Description:
+ *   Set and get syscall trace filter setting
+ *   (Same as TRIOC_GETSYSCALLFILTER / TRIOC_SETSYSCALLFILTER ioctls)
+ *
+ * Input Parameters:
+ *   oldf - A writable pointer to struct note_trace_syscallfilter_s to get
+ *          current syscall trace filter setting
+ *          If 0, no data is written.
+ *   newf - A read-only pointer to struct note_trace_syscallfilter_s of the
+ *          new syscall trace filter setting
+ *          If 0, the setting is not updated.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+void sched_note_trace_syscallfilter(struct note_trace_syscallfilter_s *oldf,
+                                    struct note_trace_syscallfilter_s *newf)
+{
+  irqstate_t irq_mask;
+  int i;
+  int nr;
+
+  irq_mask = enter_critical_section();
+
+  if (newf != NULL)
     {
-      /* Copy the next byte at the tail index */
+      sched_note_trace_stop();
 
-      *buffer++ = g_note_info.ni_buffer[tail];
+      /* Replace the syscall filter mask by the provided setting */
 
-      /* Adjust indices and counts */
+      memset(g_note_filter.syscall_mask, 0,
+             sizeof g_note_filter.syscall_mask);
+      for (i = 0; i < newf->nr_syscalls; i++)
+        {
+          nr = newf->syscalls[i];
 
-      tail = note_next(tail, 1);
-      remaining--;
+          if (nr < SYS_nsyscalls)
+            {
+              BITMASK_SET(g_note_filter.syscall_mask, nr);
+            }
+        }
     }
 
-  g_note_info.ni_tail = tail;
+  /* Count the number of filtered syscalls to calculate the requied size to
+   * get the current setting.
+   */
 
-errout_with_csection:
-  leave_critical_section(flags);
-  return notelen;
+  nr = 0;
+  for (i = 0; i < SYS_nsyscalls; i++)
+    {
+      if (BITMASK_CHECK(g_note_filter.syscall_mask, i))
+        {
+          nr++;
+        }
+    }
+
+  if (oldf != NULL)
+    {
+      /* Return the current filter setting */
+
+      int *p = oldf->syscalls;
+      int s = oldf->size;
+      oldf->nr_syscalls = nr;
+
+      for (i = 0; i < SYS_nsyscalls; i++)
+        {
+          if (p == NULL || s <= sizeof(int))
+            {
+              break;
+            }
+
+          if (BITMASK_CHECK(g_note_filter.syscall_mask, i))
+            {
+              *p++ = i;
+              s -= sizeof(int);
+            }
+        }
+    }
+
+  leave_critical_section(irq_mask);
 }
 #endif
 
 /****************************************************************************
- * Name: sched_note_size
+ * Name: sched_note_trace_irqfilter
  *
  * Description:
- *   Return the size of the next note at the tail of the circular buffer.
+ *   Set and get IRQ trace filter setting
+ *   (Same as TRIOC_GETIRQFILTER / TRIOC_SETIRQFILTER ioctls)
  *
  * Input Parameters:
- *   None.
+ *   oldf - A writable pointer to struct note_trace_irqfilter_s to get
+ *          current IRQ trace filter setting
+ *          If 0, no data is written.
+ *   newf - A read-only pointer to struct note_trace_irqfilter_s of the new
+ *          IRQ trace filter setting
+ *          If 0, the setting is not updated.
  *
  * Returned Value:
- *   Zero is returned if the circular buffer is empty.  Otherwise, the size
- *   of the next note is returned.
+ *   None
  *
  ****************************************************************************/
 
-#ifdef CONFIG_SCHED_NOTE_GET
-ssize_t sched_note_size(void)
+#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER
+void sched_note_trace_irqfilter(struct note_trace_irqfilter_s *oldf,
+                                struct note_trace_irqfilter_s *newf)
 {
-  FAR struct note_common_s *note;
-  irqstate_t flags;
-  unsigned int tail;
-  ssize_t notelen;
-  size_t circlen;
+  irqstate_t irq_mask;
+  int i;
+  int nr;
 
-  flags = enter_critical_section();
+  irq_mask = enter_critical_section();
 
-  /* Verify that the circular buffer is not empty */
+  if (newf != NULL)
+    {
+      sched_note_trace_stop();
+
+      /* Replace the IRQ filter mask by the provided setting */
+
+      memset(g_note_filter.irqhandler_mask, 0,
+             sizeof g_note_filter.irqhandler_mask);

Review comment:
       should we use the same format here to avoid the 
conversion(number<->bitmap)?

##########
File path: sched/sched/sched_note.c
##########
@@ -370,6 +437,10 @@ void sched_note_start(FAR struct tcb_s *tcb)
   strncpy(note.nsa_name, tcb->name, CONFIG_TASK_NAME_SIZE + 1);
 
   length = SIZEOF_NOTE_START(namelen + 1);
+
+#ifdef NOTE_FEATURE_TASK_NAME
+  note_taskname_put(tcb->pid, tcb->name);

Review comment:
       If the note already contain task name and pid, why we need save pid and 
name additionally?

##########
File path: drivers/syslog/note_driver.c
##########
@@ -138,6 +185,231 @@ static ssize_t note_read(FAR struct file *filep, FAR char 
*buffer,
   sched_unlock();
   return retlen;
 }
+#endif
+
+/****************************************************************************
+ * Name: note_write
+ ****************************************************************************/
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER
+static ssize_t note_write(FAR struct file *filep, FAR const char *buffer,

Review comment:
       why need to implement a dummy note_write?

##########
File path: sched/sched/sched_note.c
##########
@@ -631,144 +924,337 @@ void sched_note_irqhandler(int irq, FAR void *handler, 
bool enter)
 }
 #endif
 
+#ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER
+
 /****************************************************************************
- * Name: sched_note_get
+ * Name: sched_note_trace_start
  *
  * Description:
- *   Remove the next note from the tail of the circular buffer.  The note
- *   is also removed from the circular buffer to make room for further notes.
+ *   Start task tracing
+ *   (Same as TRIOC_START ioctl)
  *
  * Input Parameters:
- *   buffer - Location to return the next note
- *   buflen - The length of the user provided buffer.
+ *   None
  *
  * Returned Value:
- *   On success, the positive, non-zero length of the return note is
- *   provided.  Zero is returned only if the circular buffer is empty.  A
- *   negated errno value is returned in the event of any failure.
+ *   None
  *
  ****************************************************************************/
 
-#ifdef CONFIG_SCHED_NOTE_GET
-ssize_t sched_note_get(FAR uint8_t *buffer, size_t buflen)
+void sched_note_trace_start(void)
 {
-  FAR struct note_common_s *note;
-  irqstate_t flags;
-  unsigned int remaining;
-  unsigned int tail;
-  ssize_t notelen;
-  size_t circlen;
+  irqstate_t irq_mask;
 
-  DEBUGASSERT(buffer != NULL);
-  flags = enter_critical_section();
+  irq_mask = enter_critical_section();
 
-  /* Verify that the circular buffer is not empty */
+  g_note_filter.enable = true;
+#ifdef NOTE_FEATURE_TASK_NAME
+  note_taskname_init();
+#endif
 
-  circlen = note_length();
-  if (circlen <= 0)
+  if (g_sched_note_stream != NULL &&
+      g_sched_note_stream->bufclear != NULL)
     {
-      notelen = 0;
-      goto errout_with_csection;
+      (g_sched_note_stream)->bufclear(g_sched_note_stream,
+        (g_note_filter.mode.flag & TRIOC_MODE_FLAG_ONESHOT) != 0);
     }
 
-  /* Get the index to the tail of the circular buffer */
+  leave_critical_section(irq_mask);
+}
 
-  tail    = g_note_info.ni_tail;
-  DEBUGASSERT(tail < CONFIG_SCHED_NOTE_BUFSIZE);
+/****************************************************************************
+ * Name: sched_note_trace_stop
+ *
+ * Description:
+ *   Stop task tracing
+ *   (Same as TRIOC_STOP ioctl)
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
 
-  /* Get the length of the note at the tail index */
+void sched_note_trace_stop(void)
+{
+  irqstate_t irq_mask;
 
-  note    = (FAR struct note_common_s *)&g_note_info.ni_buffer[tail];
-  notelen = note->nc_length;
-  DEBUGASSERT(notelen <= circlen);
+  irq_mask = enter_critical_section();
 
-  /* Is the user buffer large enough to hold the note? */
+  g_note_filter.enable = false;
 
-  if (buflen < notelen)
+  if (g_sched_note_stream != NULL &&
+      g_sched_note_stream->bufrewind != NULL)
     {
-      /* Remove the large note so that we do not get constipated. */
+      (g_sched_note_stream)->bufrewind(g_sched_note_stream);
+    }
+
+  leave_critical_section(irq_mask);
+}
+
+/****************************************************************************
+ * Name: sched_note_trace_mode
+ *
+ * Description:
+ *   Set and get task trace mode.
+ *   (Same as TRIOC_GETMODE / TRIOC_SETMODE ioctls)
+ *
+ * Input Parameters:
+ *   oldm - A writable pointer to struct note_trace_mode_s to get current
+ *          trace mode
+ *          If 0, no data is written.
+ *   newm - A read-only pointer to struct note_trace_mode_s which holds the
+ *          new trace mode
+ *          If 0, the trace mode is not updated.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
 
-      note_remove();
+void sched_note_trace_mode(struct note_trace_mode_s *oldm,
+                           struct note_trace_mode_s *newm)
+{
+  irqstate_t irq_mask;
 
-      /* and return an error */
+  irq_mask = enter_critical_section();
 
-      notelen = -EFBIG;
-      goto errout_with_csection;
+  if (newm != NULL)
+    {
+      sched_note_trace_stop();
+      g_note_filter.mode = *newm;
+      if (g_sched_note_stream != NULL &&
+          g_sched_note_stream->bufclear != NULL)
+        {
+          (g_sched_note_stream)->bufclear(g_sched_note_stream,
+            (g_note_filter.mode.flag & TRIOC_MODE_FLAG_ONESHOT) != 0);
+        }
     }
 
-  /* Loop until the note has been transferred to the user buffer */
+  if (oldm != NULL)
+    {
+      *oldm = g_note_filter.mode;
+    }
 
-  remaining = (unsigned int)notelen;
-  while (remaining > 0)
+  leave_critical_section(irq_mask);
+}
+
+/****************************************************************************
+ * Name: sched_note_trace_syscallfilter
+ *
+ * Description:
+ *   Set and get syscall trace filter setting
+ *   (Same as TRIOC_GETSYSCALLFILTER / TRIOC_SETSYSCALLFILTER ioctls)
+ *
+ * Input Parameters:
+ *   oldf - A writable pointer to struct note_trace_syscallfilter_s to get
+ *          current syscall trace filter setting
+ *          If 0, no data is written.
+ *   newf - A read-only pointer to struct note_trace_syscallfilter_s of the
+ *          new syscall trace filter setting
+ *          If 0, the setting is not updated.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+void sched_note_trace_syscallfilter(struct note_trace_syscallfilter_s *oldf,
+                                    struct note_trace_syscallfilter_s *newf)
+{
+  irqstate_t irq_mask;
+  int i;
+  int nr;
+
+  irq_mask = enter_critical_section();
+
+  if (newf != NULL)
     {
-      /* Copy the next byte at the tail index */
+      sched_note_trace_stop();
 
-      *buffer++ = g_note_info.ni_buffer[tail];
+      /* Replace the syscall filter mask by the provided setting */
 
-      /* Adjust indices and counts */
+      memset(g_note_filter.syscall_mask, 0,
+             sizeof g_note_filter.syscall_mask);
+      for (i = 0; i < newf->nr_syscalls; i++)
+        {
+          nr = newf->syscalls[i];
 
-      tail = note_next(tail, 1);
-      remaining--;
+          if (nr < SYS_nsyscalls)
+            {
+              BITMASK_SET(g_note_filter.syscall_mask, nr);
+            }
+        }
     }
 
-  g_note_info.ni_tail = tail;
+  /* Count the number of filtered syscalls to calculate the requied size to
+   * get the current setting.
+   */
 
-errout_with_csection:
-  leave_critical_section(flags);
-  return notelen;
+  nr = 0;
+  for (i = 0; i < SYS_nsyscalls; i++)
+    {
+      if (BITMASK_CHECK(g_note_filter.syscall_mask, i))
+        {
+          nr++;
+        }
+    }
+
+  if (oldf != NULL)
+    {
+      /* Return the current filter setting */
+
+      int *p = oldf->syscalls;
+      int s = oldf->size;
+      oldf->nr_syscalls = nr;
+
+      for (i = 0; i < SYS_nsyscalls; i++)
+        {
+          if (p == NULL || s <= sizeof(int))
+            {
+              break;
+            }
+
+          if (BITMASK_CHECK(g_note_filter.syscall_mask, i))
+            {
+              *p++ = i;
+              s -= sizeof(int);
+            }
+        }
+    }
+
+  leave_critical_section(irq_mask);
 }
 #endif
 
 /****************************************************************************
- * Name: sched_note_size
+ * Name: sched_note_trace_irqfilter
  *
  * Description:
- *   Return the size of the next note at the tail of the circular buffer.
+ *   Set and get IRQ trace filter setting
+ *   (Same as TRIOC_GETIRQFILTER / TRIOC_SETIRQFILTER ioctls)
  *
  * Input Parameters:
- *   None.
+ *   oldf - A writable pointer to struct note_trace_irqfilter_s to get
+ *          current IRQ trace filter setting
+ *          If 0, no data is written.
+ *   newf - A read-only pointer to struct note_trace_irqfilter_s of the new
+ *          IRQ trace filter setting
+ *          If 0, the setting is not updated.
  *
  * Returned Value:
- *   Zero is returned if the circular buffer is empty.  Otherwise, the size
- *   of the next note is returned.
+ *   None
  *
  ****************************************************************************/
 
-#ifdef CONFIG_SCHED_NOTE_GET
-ssize_t sched_note_size(void)
+#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER
+void sched_note_trace_irqfilter(struct note_trace_irqfilter_s *oldf,
+                                struct note_trace_irqfilter_s *newf)
 {
-  FAR struct note_common_s *note;
-  irqstate_t flags;
-  unsigned int tail;
-  ssize_t notelen;
-  size_t circlen;
+  irqstate_t irq_mask;
+  int i;
+  int nr;
 
-  flags = enter_critical_section();
+  irq_mask = enter_critical_section();
 
-  /* Verify that the circular buffer is not empty */
+  if (newf != NULL)
+    {
+      sched_note_trace_stop();
+
+      /* Replace the IRQ filter mask by the provided setting */
+
+      memset(g_note_filter.irqhandler_mask, 0,
+             sizeof g_note_filter.irqhandler_mask);
+      for (i = 0; i < newf->nr_irqs; i++)
+        {
+          nr = newf->irqs[i];
+
+          if (nr < NR_IRQS)
+            {
+              BITMASK_SET(g_note_filter.irqhandler_mask, nr);
+            }
+        }
+    }
+
+  /* Count the number of filtered IRQs to calculate the requied size to get
+   * the current setting.
+   */
+
+  nr = 0;
+  for (i = 0; i < NR_IRQS; i++)
+    {
+      if (BITMASK_CHECK(g_note_filter.irqhandler_mask, i))
+        {
+          nr++;
+        }
+    }
 
-  circlen = note_length();
-  if (circlen <= 0)
+  if (oldf != NULL)

Review comment:
       move befoe the modification.

##########
File path: sched/sched/sched_note.c
##########
@@ -631,144 +924,337 @@ void sched_note_irqhandler(int irq, FAR void *handler, 
bool enter)
 }
 #endif
 
+#ifdef CONFIG_SCHED_INSTRUMENTATION_FILTER
+
 /****************************************************************************
- * Name: sched_note_get
+ * Name: sched_note_trace_start
  *
  * Description:
- *   Remove the next note from the tail of the circular buffer.  The note
- *   is also removed from the circular buffer to make room for further notes.
+ *   Start task tracing
+ *   (Same as TRIOC_START ioctl)
  *
  * Input Parameters:
- *   buffer - Location to return the next note
- *   buflen - The length of the user provided buffer.
+ *   None
  *
  * Returned Value:
- *   On success, the positive, non-zero length of the return note is
- *   provided.  Zero is returned only if the circular buffer is empty.  A
- *   negated errno value is returned in the event of any failure.
+ *   None
  *
  ****************************************************************************/
 
-#ifdef CONFIG_SCHED_NOTE_GET
-ssize_t sched_note_get(FAR uint8_t *buffer, size_t buflen)
+void sched_note_trace_start(void)
 {
-  FAR struct note_common_s *note;
-  irqstate_t flags;
-  unsigned int remaining;
-  unsigned int tail;
-  ssize_t notelen;
-  size_t circlen;
+  irqstate_t irq_mask;
 
-  DEBUGASSERT(buffer != NULL);
-  flags = enter_critical_section();
+  irq_mask = enter_critical_section();
 
-  /* Verify that the circular buffer is not empty */
+  g_note_filter.enable = true;
+#ifdef NOTE_FEATURE_TASK_NAME
+  note_taskname_init();
+#endif
 
-  circlen = note_length();
-  if (circlen <= 0)
+  if (g_sched_note_stream != NULL &&
+      g_sched_note_stream->bufclear != NULL)
     {
-      notelen = 0;
-      goto errout_with_csection;
+      (g_sched_note_stream)->bufclear(g_sched_note_stream,
+        (g_note_filter.mode.flag & TRIOC_MODE_FLAG_ONESHOT) != 0);
     }
 
-  /* Get the index to the tail of the circular buffer */
+  leave_critical_section(irq_mask);
+}
 
-  tail    = g_note_info.ni_tail;
-  DEBUGASSERT(tail < CONFIG_SCHED_NOTE_BUFSIZE);
+/****************************************************************************
+ * Name: sched_note_trace_stop
+ *
+ * Description:
+ *   Stop task tracing
+ *   (Same as TRIOC_STOP ioctl)
+ *
+ * Input Parameters:
+ *   None
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
 
-  /* Get the length of the note at the tail index */
+void sched_note_trace_stop(void)
+{
+  irqstate_t irq_mask;
 
-  note    = (FAR struct note_common_s *)&g_note_info.ni_buffer[tail];
-  notelen = note->nc_length;
-  DEBUGASSERT(notelen <= circlen);
+  irq_mask = enter_critical_section();
 
-  /* Is the user buffer large enough to hold the note? */
+  g_note_filter.enable = false;
 
-  if (buflen < notelen)
+  if (g_sched_note_stream != NULL &&
+      g_sched_note_stream->bufrewind != NULL)
     {
-      /* Remove the large note so that we do not get constipated. */
+      (g_sched_note_stream)->bufrewind(g_sched_note_stream);
+    }
+
+  leave_critical_section(irq_mask);
+}
+
+/****************************************************************************
+ * Name: sched_note_trace_mode
+ *
+ * Description:
+ *   Set and get task trace mode.
+ *   (Same as TRIOC_GETMODE / TRIOC_SETMODE ioctls)
+ *
+ * Input Parameters:
+ *   oldm - A writable pointer to struct note_trace_mode_s to get current
+ *          trace mode
+ *          If 0, no data is written.
+ *   newm - A read-only pointer to struct note_trace_mode_s which holds the
+ *          new trace mode
+ *          If 0, the trace mode is not updated.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
 
-      note_remove();
+void sched_note_trace_mode(struct note_trace_mode_s *oldm,
+                           struct note_trace_mode_s *newm)
+{
+  irqstate_t irq_mask;
 
-      /* and return an error */
+  irq_mask = enter_critical_section();
 
-      notelen = -EFBIG;
-      goto errout_with_csection;
+  if (newm != NULL)
+    {
+      sched_note_trace_stop();
+      g_note_filter.mode = *newm;
+      if (g_sched_note_stream != NULL &&
+          g_sched_note_stream->bufclear != NULL)
+        {
+          (g_sched_note_stream)->bufclear(g_sched_note_stream,
+            (g_note_filter.mode.flag & TRIOC_MODE_FLAG_ONESHOT) != 0);
+        }
     }
 
-  /* Loop until the note has been transferred to the user buffer */
+  if (oldm != NULL)
+    {
+      *oldm = g_note_filter.mode;
+    }
 
-  remaining = (unsigned int)notelen;
-  while (remaining > 0)
+  leave_critical_section(irq_mask);
+}
+
+/****************************************************************************
+ * Name: sched_note_trace_syscallfilter
+ *
+ * Description:
+ *   Set and get syscall trace filter setting
+ *   (Same as TRIOC_GETSYSCALLFILTER / TRIOC_SETSYSCALLFILTER ioctls)
+ *
+ * Input Parameters:
+ *   oldf - A writable pointer to struct note_trace_syscallfilter_s to get
+ *          current syscall trace filter setting
+ *          If 0, no data is written.
+ *   newf - A read-only pointer to struct note_trace_syscallfilter_s of the
+ *          new syscall trace filter setting
+ *          If 0, the setting is not updated.
+ *
+ * Returned Value:
+ *   None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+void sched_note_trace_syscallfilter(struct note_trace_syscallfilter_s *oldf,
+                                    struct note_trace_syscallfilter_s *newf)
+{
+  irqstate_t irq_mask;
+  int i;
+  int nr;
+
+  irq_mask = enter_critical_section();
+
+  if (newf != NULL)
     {
-      /* Copy the next byte at the tail index */
+      sched_note_trace_stop();
 
-      *buffer++ = g_note_info.ni_buffer[tail];
+      /* Replace the syscall filter mask by the provided setting */
 
-      /* Adjust indices and counts */
+      memset(g_note_filter.syscall_mask, 0,
+             sizeof g_note_filter.syscall_mask);
+      for (i = 0; i < newf->nr_syscalls; i++)
+        {
+          nr = newf->syscalls[i];
 
-      tail = note_next(tail, 1);
-      remaining--;
+          if (nr < SYS_nsyscalls)
+            {
+              BITMASK_SET(g_note_filter.syscall_mask, nr);

Review comment:
       should we use the same format here to avoid the 
conversion(number<->bitmap)?

##########
File path: include/nuttx/sched.h
##########
@@ -748,6 +748,10 @@ struct tcb_s
 #if CONFIG_TASK_NAME_SIZE > 0
   char name[CONFIG_TASK_NAME_SIZE + 1];  /* Task name (with NUL terminator)    
 */
 #endif
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+  int syscall_nest;                      /* Syscall nest level */

Review comment:
       But should we trace the nest system call too?

##########
File path: drivers/syslog/Kconfig
##########
@@ -64,7 +64,7 @@ endif
 config DRIVER_NOTE
        bool "Scheduler instrumentation driver"
        default n
-       depends on SCHED_INSTRUMENTATION_BUFFER && SCHED_NOTE_GET
+       depends on (SCHED_INSTRUMENTATION_BUFFER && SCHED_NOTE_GET) || 
SCHED_INSTRUMENTATION_FILTER

Review comment:
       Ok.

##########
File path: sched/sched/sched_note_buffer.c
##########
@@ -0,0 +1,471 @@
+/****************************************************************************
+ * sched/sched/sched_note_buffer.c

Review comment:
       We can merge this file into note_driver to simplify the interaction.




----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


Reply via email to