Gary-Hobson commented on code in PR #8525: URL: https://github.com/apache/nuttx/pull/8525#discussion_r1109353762
########## drivers/note/notesched_driver.c: ########## @@ -0,0 +1,393 @@ +/**************************************************************************** + * drivers/note/notesched_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 Types + ****************************************************************************/ + +struct notesched_chunk_s +{ + uint8_t type; +#ifdef CONFIG_SMP + uint8_t cpu; +#endif + pid_t pid; + struct timespec time; + uintptr_t args; +}; + +struct notesched_s +{ + struct note_driver_s driver; + size_t index; + struct notesched_chunk_s buffer[CONFIG_DRIVER_NOTESCHED_NBUFFERS]; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void notesched_start(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb); +static void notesched_stop(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb); +#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH +static void notesched_suspend(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb); +static void notesched_resume(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb); +#ifdef CONFIG_SMP +static void notesched_cpu_start(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb, int cpu); +static void notesched_cpu_started(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb); +static void notesched_cpu_pause(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb, int cpu); +static void notesched_cpu_paused(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb); +static void notesched_cpu_resume(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb, int cpu); +static void notesched_cpu_resumed(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb); +#endif +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION +static void notesched_premption(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb, bool locked); +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION +static void notesched_csection(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb, bool enter); +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS +static void notesched_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 notesched_syscall_enter(FAR struct note_driver_s *drv, int nr, + int argc, va_list *ap); +static void notesched_syscall_leave(FAR struct note_driver_s *drv, int nr, + uintptr_t result); +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER +static void notesched_irqhandler(FAR struct note_driver_s *drv, int irq, + FAR void *handler, bool enter); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct note_driver_ops_s g_notesched_ops = +{ + NULL, + notesched_start, + notesched_stop, +#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH + notesched_suspend, + notesched_resume, +# ifdef CONFIG_SMP + notesched_cpu_start, + notesched_cpu_started, + notesched_cpu_pause, + notesched_cpu_paused, + notesched_cpu_resume, + notesched_cpu_resumed, +# endif +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION + notesched_premption, +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION + notesched_csection, +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS + notesched_spinlock, +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL + notesched_syscall_enter, + notesched_syscall_leave, +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER + notesched_irqhandler, +#endif +}; + +static struct notesched_s g_notesched = +{ + {&g_notesched_ops} +}; + +static const FAR char *g_note_type[] = Review Comment: done ########## drivers/note/Make.defs: ########## @@ -36,5 +36,10 @@ ifeq ($(CONFIG_DRIVER_NOTECTL),y) CSRCS += notectl_driver.c endif +ifeq ($(CONFIG_DRIVER_NOTESCHED),y) + CSRCS += notesched_driver.c + CFLAGS += ${INCDIR_PREFIX}${TOPDIR}/sched Review Comment: done ########## drivers/note/notesched_driver.c: ########## @@ -0,0 +1,393 @@ +/**************************************************************************** + * drivers/note/notesched_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 Types + ****************************************************************************/ + +struct notesched_chunk_s +{ + uint8_t type; +#ifdef CONFIG_SMP + uint8_t cpu; +#endif + pid_t pid; + struct timespec time; + uintptr_t args; +}; + +struct notesched_s +{ + struct note_driver_s driver; + size_t index; + struct notesched_chunk_s buffer[CONFIG_DRIVER_NOTESCHED_NBUFFERS]; +}; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static void notesched_start(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb); +static void notesched_stop(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb); +#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH +static void notesched_suspend(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb); +static void notesched_resume(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb); +#ifdef CONFIG_SMP +static void notesched_cpu_start(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb, int cpu); +static void notesched_cpu_started(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb); +static void notesched_cpu_pause(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb, int cpu); +static void notesched_cpu_paused(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb); +static void notesched_cpu_resume(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb, int cpu); +static void notesched_cpu_resumed(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb); +#endif +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION +static void notesched_premption(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb, bool locked); +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION +static void notesched_csection(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb, bool enter); +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS +static void notesched_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 notesched_syscall_enter(FAR struct note_driver_s *drv, int nr, + int argc, va_list *ap); +static void notesched_syscall_leave(FAR struct note_driver_s *drv, int nr, + uintptr_t result); +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER +static void notesched_irqhandler(FAR struct note_driver_s *drv, int irq, + FAR void *handler, bool enter); +#endif + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct note_driver_ops_s g_notesched_ops = +{ + NULL, + notesched_start, + notesched_stop, +#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH + notesched_suspend, + notesched_resume, +# ifdef CONFIG_SMP + notesched_cpu_start, + notesched_cpu_started, + notesched_cpu_pause, + notesched_cpu_paused, + notesched_cpu_resume, + notesched_cpu_resumed, +# endif +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION + notesched_premption, +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION + notesched_csection, +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS + notesched_spinlock, +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL + notesched_syscall_enter, + notesched_syscall_leave, +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER + notesched_irqhandler, +#endif +}; + +static struct notesched_s g_notesched = +{ + {&g_notesched_ops} +}; + +static const FAR char *g_note_type[] = +{ + "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" +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: notesched_common + ****************************************************************************/ + +static inline void notesched_common(FAR struct tcb_s *tcb, uint8_t type, + uintptr_t args) +{ + /* atomic operation, equivalent to g_notesched.index++ */ + + size_t index = atomic_fetch_add(&g_notesched.index, 1); + FAR struct notesched_chunk_s *note = &g_notesched.buffer[index]; + uint32_t freq = up_perf_getfreq(); + + if (freq != 0) + { + uint32_t tick = up_perf_gettime(); + note->time.tv_nsec = (uint64_t)tick * NSEC_PER_SEC / freq; + note->time.tv_sec = tick / freq; + } + else + { + clock_systime_timespec(¬e->time); + } + + note->args = args; + note->type = type; + if (tcb) + { + note->pid = tcb->pid; +#ifdef CONFIG_SMP + note->cpu = tcb->cpu; +#endif + } + + if (g_notesched.index == CONFIG_DRIVER_NOTESCHED_NBUFFERS) + { + /* atomic operation, equivalent to g_notesched.index = 0 */ + + atomic_exchange(&g_notesched.index, 0); + } +} + +/**************************************************************************** + * Name: notesched_* + ****************************************************************************/ + +static void notesched_start(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb) +{ + notesched_common(tcb, NOTE_START, 0); +} + +static void notesched_stop(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb) +{ + notesched_common(tcb, NOTE_STOP, 0); +} + +#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH +static void notesched_suspend(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb) +{ + notesched_common(tcb, NOTE_SUSPEND, 0); +} + +static void notesched_resume(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb) +{ + notesched_common(tcb, NOTE_RESUME, 0); +} +#endif + +#ifdef CONFIG_SMP +static void notesched_cpu_start(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb, int cpu) +{ + notesched_common(tcb, NOTE_RESUME, (uintptr_t)cpu); +} + +static void notesched_cpu_started(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb) +{ + notesched_common(tcb, NOTE_RESUME, 0); +} + +#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH +static void notesched_cpu_pause(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb, int cpu) +{ + notesched_common(tcb, NOTE_RESUME, cpu); +} + +static void notesched_cpu_paused(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb) +{ + notesched_common(tcb, NOTE_RESUME, 0); +} + +static void notesched_cpu_resume(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb, int cpu) +{ + notesched_common(tcb, NOTE_RESUME, cpu); +} + +static void notesched_cpu_resumed(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb) +{ + notesched_common(tcb, NOTE_RESUME, 0); +} +#endif +#endif + +#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION +static void notesched_premption(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb, bool locked) +{ + notesched_common(tcb, locked ? NOTE_PREEMPT_LOCK : NOTE_PREEMPT_UNLOCK, 0); +} +#endif + +#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION +static void notesched_csection(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb, bool enter) +{ + notesched_common(tcb, + enter ? NOTE_CSECTION_ENTER : NOTE_CSECTION_LEAVE, 0); +} +#endif + +#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS +static void notesched_spinlock(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb, + FAR volatile void *spinlock, int type) +{ + notesched_common(tcb, type, (uintptr_t)spinlock); +} +#endif + +#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER +static void notesched_irqhandler(FAR struct note_driver_s *drv, int irq, + FAR void *handler, bool enter) +{ + notesched_common(this_task(), enter ? NOTE_IRQ_ENTER : NOTE_IRQ_LEAVE, + (uintptr_t)irq); +} +#endif + +#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL +static void notesched_syscall_enter(FAR struct note_driver_s *drv, int nr, + int argc, va_list *ap) +{ + notesched_common(this_task(), NOTE_SYSCALL_ENTER, (uintptr_t)nr); +} + +static void notesched_syscall_leave(FAR struct note_driver_s *drv, int nr, + uintptr_t result) +{ + notesched_common(this_task(), NOTE_SYSCALL_LEAVE, (uintptr_t)nr); +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: notesched_register + ****************************************************************************/ + +int notesched_register(void) +{ + return note_driver_register(&g_notesched.driver); +} + +/**************************************************************************** + * Name: notesched_dump + ****************************************************************************/ + +void notesched_dump(void) +{ + size_t i; + struct note_filter_mode_s old; + size_t index = g_notesched.index; + FAR struct notesched_chunk_s *note; + + sched_note_filter_mode(&old, NULL); + old.flag &= ~(NOTE_FILTER_MODE_FLAG_ENABLE); + sched_note_filter_mode(NULL, &old); + + for (i = index; i != index - 1; i++) + { + note = &g_notesched.buffer[i]; + i = (i == CONFIG_DRIVER_NOTESCHED_NBUFFERS - 1) ? 0 : i; + syslog(LOG_INFO, + "last_sched: [%u.%u] " 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