Gary-Hobson commented on code in PR #8525:
URL: https://github.com/apache/nuttx/pull/8525#discussion_r1108085445


##########
drivers/note/note_lastsched_driver.c:
##########
@@ -0,0 +1,397 @@
+/****************************************************************************
+ * drivers/note/note_lastsched_driver.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <inttypes.h>
+#include <stdatomic.h>
+#include <syslog.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/note/note_driver.h>
+#include <nuttx/sched.h>
+#include <nuttx/sched_note.h>
+#include <sched/sched.h>
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static void note_lastsched_start(FAR struct note_driver_s *drv,
+                                 FAR struct tcb_s *tcb);
+static void note_lastsched_stop(FAR struct note_driver_s *drv,
+                                FAR struct tcb_s *tcb);
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH
+static void note_lastsched_suspend(FAR struct note_driver_s *drv,
+                                   FAR struct tcb_s *tcb);
+static void note_lastsched_resume(FAR struct note_driver_s *drv,
+                                  FAR struct tcb_s *tcb);
+#  ifdef CONFIG_SMP
+static void note_lastsched_cpu_start(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, int cpu);
+static void note_lastsched_cpu_started(FAR struct note_driver_s *drv,
+                                       FAR struct tcb_s *tcb);
+static void note_lastsched_cpu_pause(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, int cpu);
+static void note_lastsched_cpu_paused(FAR struct note_driver_s *drv,
+                                      FAR struct tcb_s *tcb);
+static void note_lastsched_cpu_resume(FAR struct note_driver_s *drv,
+                                      FAR struct tcb_s *tcb, int cpu);
+static void note_lastsched_cpu_resumed(FAR struct note_driver_s *drv,
+                                       FAR struct tcb_s *tcb);
+#  endif
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION
+static void note_lastsched_premption(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, bool locked);
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION
+static void note_lastsched_csection(FAR struct note_driver_s *drv,
+                                    FAR struct tcb_s *tcb, bool enter);
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
+static void note_spinlock(FAR struct note_driver_s *drv,
+                          FAR struct tcb_s *tcb, FAR volatile void *spinlock,
+                          int type);
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+static void note_lastsched_syscall_enter(FAR struct note_driver_s *drv,
+                                         int nr, int argc, va_list *ap);
+static void note_lastsched_syscall_leave(FAR struct note_driver_s *drv,
+                                         int nr, uintptr_t result);
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER
+static void note_lastsched_irqhandler(FAR struct note_driver_s *drv, int irq,
+                                      FAR void *handler, bool enter);
+#endif
+
+struct note_lastsched_chunk_s
+{
+  uint32_t systick;
+  uint32_t cpu_pid;
+  enum note_type_e type;
+  void *args;
+};
+
+struct note_lastsched_s
+{
+  uint32_t freq;
+  size_t index;
+  struct timespec ts;
+  struct note_lastsched_chunk_s
+         buffer[CONFIG_DRIVER_NOTE_LASTSCHED_NBUFFERS];
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct note_lastsched_s g_note_lastsched;
+
+static const struct note_driver_ops_s g_note_lastsched_ops =
+{
+  NULL,
+  note_lastsched_start,
+  note_lastsched_stop,
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH
+  note_lastsched_suspend,
+  note_lastsched_resume,
+#  ifdef CONFIG_SMP
+  note_lastsched_cpu_start,
+  note_lastsched_cpu_started,
+  note_lastsched_cpu_pause,
+  note_lastsched_cpu_paused,
+  note_lastsched_cpu_resume,
+  note_lastsched_cpu_resumed,
+#  endif
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION
+  note_lastsched_premption,
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION
+  note_lastsched_csection,
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
+  note_spinlock,
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+  note_lastsched_syscall_enter,
+  note_lastsched_syscall_leave,
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER
+  note_lastsched_irqhandler,
+#endif
+};
+
+static const FAR char *note_type_string[] =
+{
+  "NOTE_START",
+  "NOTE_STOP",
+  "NOTE_SUSPEND",
+  "NOTE_RESUME",
+  "NOTE_CPU_START",
+  "NOTE_CPU_STARTED",
+  "NOTE_CPU_PAUSE",
+  "NOTE_CPU_PAUSED",
+  "NOTE_CPU_RESUME",
+  "NOTE_CPU_RESUMED",
+  "NOTE_PREEMPT_LOCK",
+  "NOTE_PREEMPT_UNLOCK",
+  "NOTE_CSECTION_ENTER",
+  "NOTE_CSECTION_LEAVE",
+  "NOTE_SPINLOCK_LOCK",
+  "NOTE_SPINLOCK_LOCKED",
+  "NOTE_SPINLOCK_UNLOCK",
+  "NOTE_SPINLOCK_ABORT",
+  "NOTE_SYSCALL_ENTER",
+  "NOTE_SYSCALL_LEAVE",
+  "NOTE_IRQ_ENTER",
+  "NOTE_IRQ_LEAVE",
+  "NOTE_DUMP_STRING",
+  "NOTE_DUMP_BINARY"
+};
+
+static struct note_driver_s g_note_lastsched_driver =
+{
+  &g_note_lastsched_ops,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: note_lastsched_common
+ ****************************************************************************/
+
+static inline void note_lastsched_common(FAR struct tcb_s *tcb, uint8_t type,
+                                         void *args)
+{
+  size_t index = atomic_fetch_add(&g_note_lastsched.index, 1);
+  FAR struct note_lastsched_chunk_s *note = &g_note_lastsched.buffer[index];
+
+  if (g_note_lastsched.freq != 0)
+    {
+      note->systick = up_perf_gettime();
+    }
+  else
+    {
+      struct timespec ts;
+      clock_systime_timespec(&ts);
+      note->systick = (uint32_t)&ts.tv_nsec;
+    }
+
+  note->type = type;
+  if (tcb)
+    {
+      note->cpu_pid = tcb->pid;
+#ifdef CONFIG_SMP
+      note->cpu_pid |= tcb->cpu << 27;
+#endif
+    }
+
+  note->args = args;
+  if (g_note_lastsched.index == CONFIG_DRIVER_NOTE_LASTSCHED_NBUFFERS)
+    {
+      clock_systime_timespec(&g_note_lastsched.ts);
+      atomic_exchange(&g_note_lastsched.index, 0);
+    }
+}
+
+/****************************************************************************
+ * Name: note_lastsched_*
+ ****************************************************************************/
+
+static void note_lastsched_start(FAR struct note_driver_s *drv,
+                                 FAR struct tcb_s *tcb)
+{
+  note_lastsched_common(tcb, NOTE_START, NULL);
+}
+
+static void note_lastsched_stop(FAR struct note_driver_s *drv,
+                                FAR struct tcb_s *tcb)
+{
+  note_lastsched_common(tcb, NOTE_STOP, NULL);
+}
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH
+static void note_lastsched_suspend(FAR struct note_driver_s *drv,
+                                   FAR struct tcb_s *tcb)
+{
+  note_lastsched_common(tcb, NOTE_SUSPEND, NULL);
+}
+
+static void note_lastsched_resume(FAR struct note_driver_s *drv,
+                                  FAR struct tcb_s *tcb)
+{
+  note_lastsched_common(tcb, NOTE_RESUME, NULL);
+}
+#endif
+
+#ifdef CONFIG_SMP
+static void note_lastsched_cpu_start(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, int cpu)
+{
+  note_lastsched_common(tcb, NOTE_RESUME, (void *)cpu);
+}
+
+static void note_lastsched_cpu_started(FAR struct note_driver_s *drv,
+                                       FAR struct tcb_s *tcb)
+{
+  note_lastsched_common(tcb, NOTE_RESUME, NULL);
+}
+
+#  ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH
+static void note_lastsched_cpu_pause(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, int cpu)
+{
+  note_lastsched_common(tcb, NOTE_RESUME, (void *)cpu);
+}
+
+static void note_lastsched_cpu_paused(FAR struct note_driver_s *drv,
+                                      FAR struct tcb_s *tcb)
+{
+  note_lastsched_common(tcb, NOTE_RESUME, NULL);
+}
+
+static void note_lastsched_cpu_resume(FAR struct note_driver_s *drv,
+                                      FAR struct tcb_s *tcb, int cpu)
+{
+  note_lastsched_common(tcb, NOTE_RESUME, (void *)cpu);
+}
+
+static void note_lastsched_cpu_resumed(FAR struct note_driver_s *drv,
+                                       FAR struct tcb_s *tcb)
+{
+  note_lastsched_common(tcb, NOTE_RESUME, NULL);
+}
+#  endif
+#endif
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION
+static void note_lastsched_premption(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, bool locked)
+{
+  note_lastsched_common(
+    tcb, locked ? NOTE_PREEMPT_LOCK : NOTE_PREEMPT_UNLOCK, NULL);
+}
+#endif
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION
+static void note_lastsched_csection(FAR struct note_driver_s *drv,
+                                    FAR struct tcb_s *tcb, bool enter)
+{
+  note_lastsched_common(
+      tcb, enter ? NOTE_CSECTION_ENTER : NOTE_CSECTION_LEAVE, NULL);
+}
+#endif
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
+static void note_spinlock(FAR struct note_driver_s *drv,
+                          FAR struct tcb_s *tcb, FAR volatile void *spinlock,
+                          int type)
+{
+  note_lastsched_common(tcb, type, (FAR void *)spinlock);
+}
+#endif
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER
+static void note_lastsched_irqhandler(FAR struct note_driver_s *drv, int irq,
+                                      FAR void *handler, bool enter)
+{
+  note_lastsched_common(this_task(), enter ? NOTE_IRQ_ENTER : NOTE_IRQ_LEAVE,
+                        (FAR void *)irq);
+}
+#endif
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+static void note_lastsched_syscall_enter(FAR struct note_driver_s *drv,
+                                         int nr, int argc, va_list *ap)
+{
+  note_lastsched_common(this_task(), NOTE_SYSCALL_ENTER, (void *)nr);
+}
+
+static void note_lastsched_syscall_leave(FAR struct note_driver_s *drv,
+                                         int nr, uintptr_t result)
+{
+  note_lastsched_common(this_task(), NOTE_SYSCALL_LEAVE, (void *)nr);
+}
+#endif
+
+/****************************************************************************
+ * Name: note_lastched_register
+ ****************************************************************************/
+
+int note_lastched_register(void)
+{
+  g_note_lastsched.freq = up_perf_getfreq();
+  if (g_note_lastsched.freq == 0)
+    {
+      g_note_lastsched.freq = NSEC_PER_SEC;
+    }
+
+  clock_gettime(CLOCK_REALTIME, &g_note_lastsched.ts);
+  return note_driver_register(&g_note_lastsched_driver);
+}
+
+/****************************************************************************
+ * Name: note_lastsched_dump
+ ****************************************************************************/
+
+void note_lastsched_dump(void)
+{
+  size_t i;
+  uint32_t freq;
+  irqstate_t flags;
+  struct note_filter_mode_s old;
+  size_t index = g_note_lastsched.index;
+  FAR struct note_lastsched_chunk_s *note;
+
+  sched_note_filter_mode(&old, NULL);

Review Comment:
   syslog in notelast is a system call, but we don't care about it.
   sched_note needs to be turned off when dumping



##########
drivers/note/note_lastsched_driver.c:
##########
@@ -0,0 +1,397 @@
+/****************************************************************************
+ * drivers/note/note_lastsched_driver.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <inttypes.h>
+#include <stdatomic.h>
+#include <syslog.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/note/note_driver.h>
+#include <nuttx/sched.h>
+#include <nuttx/sched_note.h>
+#include <sched/sched.h>
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static void note_lastsched_start(FAR struct note_driver_s *drv,
+                                 FAR struct tcb_s *tcb);
+static void note_lastsched_stop(FAR struct note_driver_s *drv,
+                                FAR struct tcb_s *tcb);
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH
+static void note_lastsched_suspend(FAR struct note_driver_s *drv,
+                                   FAR struct tcb_s *tcb);
+static void note_lastsched_resume(FAR struct note_driver_s *drv,
+                                  FAR struct tcb_s *tcb);
+#  ifdef CONFIG_SMP
+static void note_lastsched_cpu_start(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, int cpu);
+static void note_lastsched_cpu_started(FAR struct note_driver_s *drv,
+                                       FAR struct tcb_s *tcb);
+static void note_lastsched_cpu_pause(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, int cpu);
+static void note_lastsched_cpu_paused(FAR struct note_driver_s *drv,
+                                      FAR struct tcb_s *tcb);
+static void note_lastsched_cpu_resume(FAR struct note_driver_s *drv,
+                                      FAR struct tcb_s *tcb, int cpu);
+static void note_lastsched_cpu_resumed(FAR struct note_driver_s *drv,
+                                       FAR struct tcb_s *tcb);
+#  endif
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION
+static void note_lastsched_premption(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, bool locked);
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION
+static void note_lastsched_csection(FAR struct note_driver_s *drv,
+                                    FAR struct tcb_s *tcb, bool enter);
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
+static void note_spinlock(FAR struct note_driver_s *drv,
+                          FAR struct tcb_s *tcb, FAR volatile void *spinlock,
+                          int type);
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+static void note_lastsched_syscall_enter(FAR struct note_driver_s *drv,
+                                         int nr, int argc, va_list *ap);
+static void note_lastsched_syscall_leave(FAR struct note_driver_s *drv,
+                                         int nr, uintptr_t result);
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER
+static void note_lastsched_irqhandler(FAR struct note_driver_s *drv, int irq,
+                                      FAR void *handler, bool enter);
+#endif
+
+struct note_lastsched_chunk_s
+{
+  uint32_t systick;
+  uint32_t cpu_pid;
+  enum note_type_e type;
+  void *args;
+};
+
+struct note_lastsched_s
+{
+  uint32_t freq;
+  size_t index;
+  struct timespec ts;
+  struct note_lastsched_chunk_s
+         buffer[CONFIG_DRIVER_NOTE_LASTSCHED_NBUFFERS];
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct note_lastsched_s g_note_lastsched;
+
+static const struct note_driver_ops_s g_note_lastsched_ops =
+{
+  NULL,
+  note_lastsched_start,
+  note_lastsched_stop,
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH
+  note_lastsched_suspend,
+  note_lastsched_resume,
+#  ifdef CONFIG_SMP
+  note_lastsched_cpu_start,
+  note_lastsched_cpu_started,
+  note_lastsched_cpu_pause,
+  note_lastsched_cpu_paused,
+  note_lastsched_cpu_resume,
+  note_lastsched_cpu_resumed,
+#  endif
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION
+  note_lastsched_premption,
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION
+  note_lastsched_csection,
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
+  note_spinlock,
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+  note_lastsched_syscall_enter,
+  note_lastsched_syscall_leave,
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER
+  note_lastsched_irqhandler,
+#endif
+};
+
+static const FAR char *note_type_string[] =
+{
+  "NOTE_START",
+  "NOTE_STOP",
+  "NOTE_SUSPEND",
+  "NOTE_RESUME",
+  "NOTE_CPU_START",
+  "NOTE_CPU_STARTED",
+  "NOTE_CPU_PAUSE",
+  "NOTE_CPU_PAUSED",
+  "NOTE_CPU_RESUME",
+  "NOTE_CPU_RESUMED",
+  "NOTE_PREEMPT_LOCK",
+  "NOTE_PREEMPT_UNLOCK",
+  "NOTE_CSECTION_ENTER",
+  "NOTE_CSECTION_LEAVE",
+  "NOTE_SPINLOCK_LOCK",
+  "NOTE_SPINLOCK_LOCKED",
+  "NOTE_SPINLOCK_UNLOCK",
+  "NOTE_SPINLOCK_ABORT",
+  "NOTE_SYSCALL_ENTER",
+  "NOTE_SYSCALL_LEAVE",
+  "NOTE_IRQ_ENTER",
+  "NOTE_IRQ_LEAVE",
+  "NOTE_DUMP_STRING",
+  "NOTE_DUMP_BINARY"
+};
+
+static struct note_driver_s g_note_lastsched_driver =
+{
+  &g_note_lastsched_ops,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: note_lastsched_common
+ ****************************************************************************/
+
+static inline void note_lastsched_common(FAR struct tcb_s *tcb, uint8_t type,
+                                         void *args)
+{
+  size_t index = atomic_fetch_add(&g_note_lastsched.index, 1);
+  FAR struct note_lastsched_chunk_s *note = &g_note_lastsched.buffer[index];
+
+  if (g_note_lastsched.freq != 0)
+    {
+      note->systick = up_perf_gettime();
+    }
+  else
+    {
+      struct timespec ts;
+      clock_systime_timespec(&ts);
+      note->systick = (uint32_t)&ts.tv_nsec;
+    }
+
+  note->type = type;
+  if (tcb)
+    {
+      note->cpu_pid = tcb->pid;
+#ifdef CONFIG_SMP
+      note->cpu_pid |= tcb->cpu << 27;
+#endif
+    }
+
+  note->args = args;
+  if (g_note_lastsched.index == CONFIG_DRIVER_NOTE_LASTSCHED_NBUFFERS)
+    {
+      clock_systime_timespec(&g_note_lastsched.ts);
+      atomic_exchange(&g_note_lastsched.index, 0);
+    }
+}
+
+/****************************************************************************
+ * Name: note_lastsched_*
+ ****************************************************************************/
+
+static void note_lastsched_start(FAR struct note_driver_s *drv,
+                                 FAR struct tcb_s *tcb)
+{
+  note_lastsched_common(tcb, NOTE_START, NULL);
+}
+
+static void note_lastsched_stop(FAR struct note_driver_s *drv,
+                                FAR struct tcb_s *tcb)
+{
+  note_lastsched_common(tcb, NOTE_STOP, NULL);
+}
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH
+static void note_lastsched_suspend(FAR struct note_driver_s *drv,
+                                   FAR struct tcb_s *tcb)
+{
+  note_lastsched_common(tcb, NOTE_SUSPEND, NULL);
+}
+
+static void note_lastsched_resume(FAR struct note_driver_s *drv,
+                                  FAR struct tcb_s *tcb)
+{
+  note_lastsched_common(tcb, NOTE_RESUME, NULL);
+}
+#endif
+
+#ifdef CONFIG_SMP
+static void note_lastsched_cpu_start(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, int cpu)
+{
+  note_lastsched_common(tcb, NOTE_RESUME, (void *)cpu);
+}
+
+static void note_lastsched_cpu_started(FAR struct note_driver_s *drv,
+                                       FAR struct tcb_s *tcb)
+{
+  note_lastsched_common(tcb, NOTE_RESUME, NULL);
+}
+
+#  ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH
+static void note_lastsched_cpu_pause(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, int cpu)
+{
+  note_lastsched_common(tcb, NOTE_RESUME, (void *)cpu);
+}
+
+static void note_lastsched_cpu_paused(FAR struct note_driver_s *drv,
+                                      FAR struct tcb_s *tcb)
+{
+  note_lastsched_common(tcb, NOTE_RESUME, NULL);
+}
+
+static void note_lastsched_cpu_resume(FAR struct note_driver_s *drv,
+                                      FAR struct tcb_s *tcb, int cpu)
+{
+  note_lastsched_common(tcb, NOTE_RESUME, (void *)cpu);
+}
+
+static void note_lastsched_cpu_resumed(FAR struct note_driver_s *drv,
+                                       FAR struct tcb_s *tcb)
+{
+  note_lastsched_common(tcb, NOTE_RESUME, NULL);
+}
+#  endif
+#endif
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION
+static void note_lastsched_premption(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, bool locked)
+{
+  note_lastsched_common(
+    tcb, locked ? NOTE_PREEMPT_LOCK : NOTE_PREEMPT_UNLOCK, NULL);
+}
+#endif
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION
+static void note_lastsched_csection(FAR struct note_driver_s *drv,
+                                    FAR struct tcb_s *tcb, bool enter)
+{
+  note_lastsched_common(
+      tcb, enter ? NOTE_CSECTION_ENTER : NOTE_CSECTION_LEAVE, NULL);
+}
+#endif
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
+static void note_spinlock(FAR struct note_driver_s *drv,
+                          FAR struct tcb_s *tcb, FAR volatile void *spinlock,
+                          int type)
+{
+  note_lastsched_common(tcb, type, (FAR void *)spinlock);
+}
+#endif
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER
+static void note_lastsched_irqhandler(FAR struct note_driver_s *drv, int irq,
+                                      FAR void *handler, bool enter)
+{
+  note_lastsched_common(this_task(), enter ? NOTE_IRQ_ENTER : NOTE_IRQ_LEAVE,
+                        (FAR void *)irq);
+}
+#endif
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+static void note_lastsched_syscall_enter(FAR struct note_driver_s *drv,
+                                         int nr, int argc, va_list *ap)
+{
+  note_lastsched_common(this_task(), NOTE_SYSCALL_ENTER, (void *)nr);
+}
+
+static void note_lastsched_syscall_leave(FAR struct note_driver_s *drv,
+                                         int nr, uintptr_t result)
+{
+  note_lastsched_common(this_task(), NOTE_SYSCALL_LEAVE, (void *)nr);
+}
+#endif
+
+/****************************************************************************
+ * Name: note_lastched_register
+ ****************************************************************************/
+
+int note_lastched_register(void)
+{
+  g_note_lastsched.freq = up_perf_getfreq();
+  if (g_note_lastsched.freq == 0)
+    {
+      g_note_lastsched.freq = NSEC_PER_SEC;
+    }
+
+  clock_gettime(CLOCK_REALTIME, &g_note_lastsched.ts);
+  return note_driver_register(&g_note_lastsched_driver);
+}
+
+/****************************************************************************
+ * Name: note_lastsched_dump
+ ****************************************************************************/
+
+void note_lastsched_dump(void)
+{
+  size_t i;
+  uint32_t freq;
+  irqstate_t flags;
+  struct note_filter_mode_s old;
+  size_t index = g_note_lastsched.index;
+  FAR struct note_lastsched_chunk_s *note;
+
+  sched_note_filter_mode(&old, NULL);
+  old.flag &= ~(NOTE_FILTER_MODE_FLAG_ENABLE);
+  sched_note_filter_mode(NULL, &old);
+  flags = enter_critical_section();
+
+  syslog(LOG_INFO,
+         "last_sched: system frequency: %" PRIu32 "\n"
+         "last_sched: start time: %" PRIu32 ".%" PRIu32,
+         g_note_lastsched.freq,
+         g_note_lastsched.ts.tv_sec,
+         g_note_lastsched.ts.tv_nsec);
+
+  freq = g_note_lastsched.freq ? NSEC_PER_SEC : g_note_lastsched.freq;
+  for (i = index; i != index - 1; i++)
+    {
+      note = &g_note_lastsched.buffer[i];
+      i = (i == CONFIG_DRIVER_NOTE_LASTSCHED_NBUFFERS - 1) ? 0 : i;
+      syslog(LOG_INFO,
+             "last_sched|%" PRIuPTR ": time:%" PRIu32 ", cpu: %" PRIu32 ", "
+             "pid:%2" PRIu32 ", type: %-16s, args: %p\n",
+             i, (uint32_t)((uint64_t)note->systick * NSEC_PER_SEC / freq),
+             note->cpu_pid >> 27, note->cpu_pid & 0x0fffffff,
+             note_type_string[note->type], note->args);
+    }
+
+  leave_critical_section(flags);

Review Comment:
   done



##########
drivers/note/note_lastsched_driver.c:
##########
@@ -0,0 +1,397 @@
+/****************************************************************************
+ * drivers/note/note_lastsched_driver.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <inttypes.h>
+#include <stdatomic.h>
+#include <syslog.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/note/note_driver.h>
+#include <nuttx/sched.h>
+#include <nuttx/sched_note.h>
+#include <sched/sched.h>
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static void note_lastsched_start(FAR struct note_driver_s *drv,
+                                 FAR struct tcb_s *tcb);
+static void note_lastsched_stop(FAR struct note_driver_s *drv,
+                                FAR struct tcb_s *tcb);
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH
+static void note_lastsched_suspend(FAR struct note_driver_s *drv,
+                                   FAR struct tcb_s *tcb);
+static void note_lastsched_resume(FAR struct note_driver_s *drv,
+                                  FAR struct tcb_s *tcb);
+#  ifdef CONFIG_SMP
+static void note_lastsched_cpu_start(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, int cpu);
+static void note_lastsched_cpu_started(FAR struct note_driver_s *drv,
+                                       FAR struct tcb_s *tcb);
+static void note_lastsched_cpu_pause(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, int cpu);
+static void note_lastsched_cpu_paused(FAR struct note_driver_s *drv,
+                                      FAR struct tcb_s *tcb);
+static void note_lastsched_cpu_resume(FAR struct note_driver_s *drv,
+                                      FAR struct tcb_s *tcb, int cpu);
+static void note_lastsched_cpu_resumed(FAR struct note_driver_s *drv,
+                                       FAR struct tcb_s *tcb);
+#  endif
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION
+static void note_lastsched_premption(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, bool locked);
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION
+static void note_lastsched_csection(FAR struct note_driver_s *drv,
+                                    FAR struct tcb_s *tcb, bool enter);
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
+static void note_spinlock(FAR struct note_driver_s *drv,
+                          FAR struct tcb_s *tcb, FAR volatile void *spinlock,
+                          int type);
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+static void note_lastsched_syscall_enter(FAR struct note_driver_s *drv,
+                                         int nr, int argc, va_list *ap);
+static void note_lastsched_syscall_leave(FAR struct note_driver_s *drv,
+                                         int nr, uintptr_t result);
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER
+static void note_lastsched_irqhandler(FAR struct note_driver_s *drv, int irq,
+                                      FAR void *handler, bool enter);
+#endif
+
+struct note_lastsched_chunk_s
+{
+  uint32_t systick;
+  uint32_t cpu_pid;
+  enum note_type_e type;
+  void *args;
+};
+
+struct note_lastsched_s
+{
+  uint32_t freq;
+  size_t index;
+  struct timespec ts;
+  struct note_lastsched_chunk_s
+         buffer[CONFIG_DRIVER_NOTE_LASTSCHED_NBUFFERS];
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct note_lastsched_s g_note_lastsched;
+
+static const struct note_driver_ops_s g_note_lastsched_ops =
+{
+  NULL,
+  note_lastsched_start,
+  note_lastsched_stop,
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH
+  note_lastsched_suspend,
+  note_lastsched_resume,
+#  ifdef CONFIG_SMP
+  note_lastsched_cpu_start,
+  note_lastsched_cpu_started,
+  note_lastsched_cpu_pause,
+  note_lastsched_cpu_paused,
+  note_lastsched_cpu_resume,
+  note_lastsched_cpu_resumed,
+#  endif
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION
+  note_lastsched_premption,
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION
+  note_lastsched_csection,
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
+  note_spinlock,
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+  note_lastsched_syscall_enter,
+  note_lastsched_syscall_leave,
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER
+  note_lastsched_irqhandler,
+#endif
+};
+
+static const FAR char *note_type_string[] =
+{
+  "NOTE_START",
+  "NOTE_STOP",
+  "NOTE_SUSPEND",
+  "NOTE_RESUME",
+  "NOTE_CPU_START",
+  "NOTE_CPU_STARTED",
+  "NOTE_CPU_PAUSE",
+  "NOTE_CPU_PAUSED",
+  "NOTE_CPU_RESUME",
+  "NOTE_CPU_RESUMED",
+  "NOTE_PREEMPT_LOCK",
+  "NOTE_PREEMPT_UNLOCK",
+  "NOTE_CSECTION_ENTER",
+  "NOTE_CSECTION_LEAVE",
+  "NOTE_SPINLOCK_LOCK",
+  "NOTE_SPINLOCK_LOCKED",
+  "NOTE_SPINLOCK_UNLOCK",
+  "NOTE_SPINLOCK_ABORT",
+  "NOTE_SYSCALL_ENTER",
+  "NOTE_SYSCALL_LEAVE",
+  "NOTE_IRQ_ENTER",
+  "NOTE_IRQ_LEAVE",
+  "NOTE_DUMP_STRING",
+  "NOTE_DUMP_BINARY"
+};
+
+static struct note_driver_s g_note_lastsched_driver =
+{
+  &g_note_lastsched_ops,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: note_lastsched_common
+ ****************************************************************************/
+
+static inline void note_lastsched_common(FAR struct tcb_s *tcb, uint8_t type,
+                                         void *args)
+{
+  size_t index = atomic_fetch_add(&g_note_lastsched.index, 1);
+  FAR struct note_lastsched_chunk_s *note = &g_note_lastsched.buffer[index];
+
+  if (g_note_lastsched.freq != 0)
+    {
+      note->systick = up_perf_gettime();
+    }
+  else
+    {
+      struct timespec ts;
+      clock_systime_timespec(&ts);
+      note->systick = (uint32_t)&ts.tv_nsec;
+    }
+
+  note->type = type;
+  if (tcb)
+    {
+      note->cpu_pid = tcb->pid;
+#ifdef CONFIG_SMP
+      note->cpu_pid |= tcb->cpu << 27;
+#endif
+    }
+
+  note->args = args;
+  if (g_note_lastsched.index == CONFIG_DRIVER_NOTE_LASTSCHED_NBUFFERS)
+    {
+      clock_systime_timespec(&g_note_lastsched.ts);
+      atomic_exchange(&g_note_lastsched.index, 0);
+    }
+}
+
+/****************************************************************************
+ * Name: note_lastsched_*
+ ****************************************************************************/
+
+static void note_lastsched_start(FAR struct note_driver_s *drv,
+                                 FAR struct tcb_s *tcb)
+{
+  note_lastsched_common(tcb, NOTE_START, NULL);
+}
+
+static void note_lastsched_stop(FAR struct note_driver_s *drv,
+                                FAR struct tcb_s *tcb)
+{
+  note_lastsched_common(tcb, NOTE_STOP, NULL);
+}
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH
+static void note_lastsched_suspend(FAR struct note_driver_s *drv,
+                                   FAR struct tcb_s *tcb)
+{
+  note_lastsched_common(tcb, NOTE_SUSPEND, NULL);
+}
+
+static void note_lastsched_resume(FAR struct note_driver_s *drv,
+                                  FAR struct tcb_s *tcb)
+{
+  note_lastsched_common(tcb, NOTE_RESUME, NULL);
+}
+#endif
+
+#ifdef CONFIG_SMP
+static void note_lastsched_cpu_start(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, int cpu)
+{
+  note_lastsched_common(tcb, NOTE_RESUME, (void *)cpu);
+}
+
+static void note_lastsched_cpu_started(FAR struct note_driver_s *drv,
+                                       FAR struct tcb_s *tcb)
+{
+  note_lastsched_common(tcb, NOTE_RESUME, NULL);
+}
+
+#  ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH
+static void note_lastsched_cpu_pause(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, int cpu)
+{
+  note_lastsched_common(tcb, NOTE_RESUME, (void *)cpu);
+}
+
+static void note_lastsched_cpu_paused(FAR struct note_driver_s *drv,
+                                      FAR struct tcb_s *tcb)
+{
+  note_lastsched_common(tcb, NOTE_RESUME, NULL);
+}
+
+static void note_lastsched_cpu_resume(FAR struct note_driver_s *drv,
+                                      FAR struct tcb_s *tcb, int cpu)
+{
+  note_lastsched_common(tcb, NOTE_RESUME, (void *)cpu);
+}
+
+static void note_lastsched_cpu_resumed(FAR struct note_driver_s *drv,
+                                       FAR struct tcb_s *tcb)
+{
+  note_lastsched_common(tcb, NOTE_RESUME, NULL);
+}
+#  endif
+#endif
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION
+static void note_lastsched_premption(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, bool locked)
+{
+  note_lastsched_common(
+    tcb, locked ? NOTE_PREEMPT_LOCK : NOTE_PREEMPT_UNLOCK, NULL);
+}
+#endif
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION
+static void note_lastsched_csection(FAR struct note_driver_s *drv,
+                                    FAR struct tcb_s *tcb, bool enter)
+{
+  note_lastsched_common(
+      tcb, enter ? NOTE_CSECTION_ENTER : NOTE_CSECTION_LEAVE, NULL);
+}
+#endif
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
+static void note_spinlock(FAR struct note_driver_s *drv,
+                          FAR struct tcb_s *tcb, FAR volatile void *spinlock,
+                          int type)
+{
+  note_lastsched_common(tcb, type, (FAR void *)spinlock);
+}
+#endif
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER
+static void note_lastsched_irqhandler(FAR struct note_driver_s *drv, int irq,
+                                      FAR void *handler, bool enter)
+{
+  note_lastsched_common(this_task(), enter ? NOTE_IRQ_ENTER : NOTE_IRQ_LEAVE,
+                        (FAR void *)irq);
+}
+#endif
+
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+static void note_lastsched_syscall_enter(FAR struct note_driver_s *drv,
+                                         int nr, int argc, va_list *ap)
+{
+  note_lastsched_common(this_task(), NOTE_SYSCALL_ENTER, (void *)nr);
+}
+
+static void note_lastsched_syscall_leave(FAR struct note_driver_s *drv,
+                                         int nr, uintptr_t result)
+{
+  note_lastsched_common(this_task(), NOTE_SYSCALL_LEAVE, (void *)nr);
+}
+#endif
+
+/****************************************************************************
+ * Name: note_lastched_register
+ ****************************************************************************/
+
+int note_lastched_register(void)
+{
+  g_note_lastsched.freq = up_perf_getfreq();
+  if (g_note_lastsched.freq == 0)
+    {
+      g_note_lastsched.freq = NSEC_PER_SEC;
+    }
+
+  clock_gettime(CLOCK_REALTIME, &g_note_lastsched.ts);
+  return note_driver_register(&g_note_lastsched_driver);
+}
+
+/****************************************************************************
+ * Name: note_lastsched_dump
+ ****************************************************************************/
+
+void note_lastsched_dump(void)
+{
+  size_t i;
+  uint32_t freq;
+  irqstate_t flags;
+  struct note_filter_mode_s old;
+  size_t index = g_note_lastsched.index;
+  FAR struct note_lastsched_chunk_s *note;
+
+  sched_note_filter_mode(&old, NULL);
+  old.flag &= ~(NOTE_FILTER_MODE_FLAG_ENABLE);
+  sched_note_filter_mode(NULL, &old);
+  flags = enter_critical_section();
+
+  syslog(LOG_INFO,
+         "last_sched: system frequency: %" PRIu32 "\n"
+         "last_sched: start time: %" PRIu32 ".%" PRIu32,
+         g_note_lastsched.freq,
+         g_note_lastsched.ts.tv_sec,
+         g_note_lastsched.ts.tv_nsec);
+
+  freq = g_note_lastsched.freq ? NSEC_PER_SEC : g_note_lastsched.freq;
+  for (i = index; i != index - 1; i++)
+    {
+      note = &g_note_lastsched.buffer[i];
+      i = (i == CONFIG_DRIVER_NOTE_LASTSCHED_NBUFFERS - 1) ? 0 : i;
+      syslog(LOG_INFO,
+             "last_sched|%" PRIuPTR ": time:%" PRIu32 ", cpu: %" PRIu32 ", "

Review Comment:
   done



##########
drivers/note/note_lastsched_driver.c:
##########
@@ -0,0 +1,397 @@
+/****************************************************************************
+ * drivers/note/note_lastsched_driver.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <inttypes.h>
+#include <stdatomic.h>
+#include <syslog.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/note/note_driver.h>
+#include <nuttx/sched.h>
+#include <nuttx/sched_note.h>
+#include <sched/sched.h>
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static void note_lastsched_start(FAR struct note_driver_s *drv,
+                                 FAR struct tcb_s *tcb);
+static void note_lastsched_stop(FAR struct note_driver_s *drv,
+                                FAR struct tcb_s *tcb);
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH
+static void note_lastsched_suspend(FAR struct note_driver_s *drv,
+                                   FAR struct tcb_s *tcb);
+static void note_lastsched_resume(FAR struct note_driver_s *drv,
+                                  FAR struct tcb_s *tcb);
+#  ifdef CONFIG_SMP
+static void note_lastsched_cpu_start(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, int cpu);
+static void note_lastsched_cpu_started(FAR struct note_driver_s *drv,
+                                       FAR struct tcb_s *tcb);
+static void note_lastsched_cpu_pause(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, int cpu);
+static void note_lastsched_cpu_paused(FAR struct note_driver_s *drv,
+                                      FAR struct tcb_s *tcb);
+static void note_lastsched_cpu_resume(FAR struct note_driver_s *drv,
+                                      FAR struct tcb_s *tcb, int cpu);
+static void note_lastsched_cpu_resumed(FAR struct note_driver_s *drv,
+                                       FAR struct tcb_s *tcb);
+#  endif
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION
+static void note_lastsched_premption(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, bool locked);
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION
+static void note_lastsched_csection(FAR struct note_driver_s *drv,
+                                    FAR struct tcb_s *tcb, bool enter);
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
+static void note_spinlock(FAR struct note_driver_s *drv,
+                          FAR struct tcb_s *tcb, FAR volatile void *spinlock,
+                          int type);
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+static void note_lastsched_syscall_enter(FAR struct note_driver_s *drv,
+                                         int nr, int argc, va_list *ap);
+static void note_lastsched_syscall_leave(FAR struct note_driver_s *drv,
+                                         int nr, uintptr_t result);
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER
+static void note_lastsched_irqhandler(FAR struct note_driver_s *drv, int irq,
+                                      FAR void *handler, bool enter);
+#endif
+
+struct note_lastsched_chunk_s
+{
+  uint32_t systick;
+  uint32_t cpu_pid;
+  enum note_type_e type;
+  void *args;
+};
+
+struct note_lastsched_s
+{
+  uint32_t freq;
+  size_t index;
+  struct timespec ts;
+  struct note_lastsched_chunk_s
+         buffer[CONFIG_DRIVER_NOTE_LASTSCHED_NBUFFERS];
+};
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static struct note_lastsched_s g_note_lastsched;
+
+static const struct note_driver_ops_s g_note_lastsched_ops =
+{
+  NULL,
+  note_lastsched_start,
+  note_lastsched_stop,
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH
+  note_lastsched_suspend,
+  note_lastsched_resume,
+#  ifdef CONFIG_SMP
+  note_lastsched_cpu_start,
+  note_lastsched_cpu_started,
+  note_lastsched_cpu_pause,
+  note_lastsched_cpu_paused,
+  note_lastsched_cpu_resume,
+  note_lastsched_cpu_resumed,
+#  endif
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION
+  note_lastsched_premption,
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION
+  note_lastsched_csection,
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
+  note_spinlock,
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+  note_lastsched_syscall_enter,
+  note_lastsched_syscall_leave,
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER
+  note_lastsched_irqhandler,
+#endif
+};
+
+static const FAR char *note_type_string[] =
+{
+  "NOTE_START",
+  "NOTE_STOP",
+  "NOTE_SUSPEND",
+  "NOTE_RESUME",
+  "NOTE_CPU_START",
+  "NOTE_CPU_STARTED",
+  "NOTE_CPU_PAUSE",
+  "NOTE_CPU_PAUSED",
+  "NOTE_CPU_RESUME",
+  "NOTE_CPU_RESUMED",
+  "NOTE_PREEMPT_LOCK",
+  "NOTE_PREEMPT_UNLOCK",
+  "NOTE_CSECTION_ENTER",
+  "NOTE_CSECTION_LEAVE",
+  "NOTE_SPINLOCK_LOCK",
+  "NOTE_SPINLOCK_LOCKED",
+  "NOTE_SPINLOCK_UNLOCK",
+  "NOTE_SPINLOCK_ABORT",
+  "NOTE_SYSCALL_ENTER",
+  "NOTE_SYSCALL_LEAVE",
+  "NOTE_IRQ_ENTER",
+  "NOTE_IRQ_LEAVE",
+  "NOTE_DUMP_STRING",
+  "NOTE_DUMP_BINARY"
+};
+
+static struct note_driver_s g_note_lastsched_driver =
+{
+  &g_note_lastsched_ops,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: note_lastsched_common
+ ****************************************************************************/
+
+static inline void note_lastsched_common(FAR struct tcb_s *tcb, uint8_t type,
+                                         void *args)

Review Comment:
   done



##########
drivers/note/note_lastsched_driver.c:
##########
@@ -0,0 +1,397 @@
+/****************************************************************************
+ * drivers/note/note_lastsched_driver.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <inttypes.h>
+#include <stdatomic.h>
+#include <syslog.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/note/note_driver.h>
+#include <nuttx/sched.h>
+#include <nuttx/sched_note.h>
+#include <sched/sched.h>
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static void note_lastsched_start(FAR struct note_driver_s *drv,
+                                 FAR struct tcb_s *tcb);
+static void note_lastsched_stop(FAR struct note_driver_s *drv,
+                                FAR struct tcb_s *tcb);
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH
+static void note_lastsched_suspend(FAR struct note_driver_s *drv,
+                                   FAR struct tcb_s *tcb);
+static void note_lastsched_resume(FAR struct note_driver_s *drv,
+                                  FAR struct tcb_s *tcb);
+#  ifdef CONFIG_SMP
+static void note_lastsched_cpu_start(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, int cpu);
+static void note_lastsched_cpu_started(FAR struct note_driver_s *drv,
+                                       FAR struct tcb_s *tcb);
+static void note_lastsched_cpu_pause(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, int cpu);
+static void note_lastsched_cpu_paused(FAR struct note_driver_s *drv,
+                                      FAR struct tcb_s *tcb);
+static void note_lastsched_cpu_resume(FAR struct note_driver_s *drv,
+                                      FAR struct tcb_s *tcb, int cpu);
+static void note_lastsched_cpu_resumed(FAR struct note_driver_s *drv,
+                                       FAR struct tcb_s *tcb);
+#  endif
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION
+static void note_lastsched_premption(FAR struct note_driver_s *drv,
+                                     FAR struct tcb_s *tcb, bool locked);
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION
+static void note_lastsched_csection(FAR struct note_driver_s *drv,
+                                    FAR struct tcb_s *tcb, bool enter);
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS
+static void note_spinlock(FAR struct note_driver_s *drv,
+                          FAR struct tcb_s *tcb, FAR volatile void *spinlock,
+                          int type);
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL
+static void note_lastsched_syscall_enter(FAR struct note_driver_s *drv,
+                                         int nr, int argc, va_list *ap);
+static void note_lastsched_syscall_leave(FAR struct note_driver_s *drv,
+                                         int nr, uintptr_t result);
+#endif
+#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER
+static void note_lastsched_irqhandler(FAR struct note_driver_s *drv, int irq,
+                                      FAR void *handler, bool enter);
+#endif
+
+struct note_lastsched_chunk_s
+{
+  uint32_t systick;
+  uint32_t cpu_pid;
+  enum note_type_e type;
+  void *args;
+};
+
+struct note_lastsched_s

Review Comment:
   done



##########
drivers/note/Kconfig:
##########
@@ -231,6 +231,20 @@ config DRIVER_NOTELOG
        ---help---
                The note driver output to syslog.
 
+config DRIVER_NOTE_LASTSCHED

Review Comment:
   done



-- 
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.

To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org

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

Reply via email to