diff --git a/drivers/note/Kconfig b/drivers/note/Kconfig index cc818645528..920a40743de 100644 --- a/drivers/note/Kconfig +++ b/drivers/note/Kconfig @@ -10,6 +10,12 @@ menuconfig DRIVER_NOTE if DRIVER_NOTE +config DRIVER_NOTE_MAX + int "Maximum number of sched_note drivers" + default 1 + ---help--- + sched_note supports the maximum number of drivers + choice prompt "Note driver selection" default DRIVER_NOTERAM diff --git a/drivers/note/note_driver.c b/drivers/note/note_driver.c index 0c0f952ebd4..c330ed1230a 100644 --- a/drivers/note/note_driver.c +++ b/drivers/note/note_driver.c @@ -35,11 +35,59 @@ #include #include #include +#include +#include #include #include #include "sched/sched.h" +#define note_add(drv, note, notelen) \ + ((drv)->ops->add(drv, note, notelen)) +#define note_start(drv, tcb) \ + ((drv)->ops->start && ((drv)->ops->start(drv, tcb), true)) +#define note_stop(drv, tcb) \ + ((drv)->ops->stop && ((drv)->ops->stop(drv, tcb), true)) +#define note_suspend(drv, tcb) \ + ((drv)->ops->suspend && ((drv)->ops->suspend(drv, tcb), true)) +#define note_resume(drv, tcb) \ + ((drv)->ops->resume && ((drv)->ops->resume(drv, tcb), true)) +#define note_cpu_start(drv, tcb, cpu) \ + ((drv)->ops->cpu_start && ((drv)->ops->cpu_start(drv, tcb, cpu), true)) +#define note_cpu_started(drv, tcb) \ + ((drv)->ops->cpu_started && ((drv)->ops->cpu_started(drv, tcb), true)) +#define note_cpu_pause(drv, tcb, cpu) \ + ((drv)->ops->cpu_pause && ((drv)->ops->cpu_pause(drv, tcb, cpu), true)) +#define note_cpu_paused(drv, tcb) \ + ((drv)->ops->cpu_paused && ((drv)->ops->cpu_paused(drv, tcb), true)) +#define note_cpu_resume(drv, tcb, cpu) \ + ((drv)->ops->cpu_resume && ((drv)->ops->cpu_resume(drv, tcb, cpu), true)) +#define note_cpu_resumed(drv, tcb) \ + ((drv)->ops->cpu_resumed && ((drv)->ops->cpu_resumed(drv, tcb), true)) +#define note_premption(drv, tcb, locked) \ + ((drv)->ops->premption && ((drv)->ops->premption(drv, tcb, locked), true)) +#define note_csection(drv, tcb, enter) \ + ((drv)->ops->csection && ((drv)->ops->csection(drv, tcb, enter), true)) +#define note_spinlock(drv, tcb, spinlock, type) \ + ((drv)->ops->spinlock && \ + ((drv)->ops->spinlock(drv, tcb, spinlock, type), true)) +#define note_syscall_enter(drv, nr) \ + ((drv)->ops->syscall_enter && ((drv)->ops->syscall_enter(drv, nr), true)) +#define note_syscall_leave(drv, nr) \ + ((drv)->ops->syscall_leave && ((drv)->ops->syscall_leave(drv, nr), true)) +#define note_irqhandler(drv, irq, handler, enter) \ + ((drv)->ops->irqhandler && \ + ((drv)->ops->irqhandler(drv, irq, handler, enter), true)) +#define note_string(drv, ip, buf) \ + ((drv)->ops->string && ((drv)->ops->string(drv, ip, buf), true)) +#define note_dump(drv, ip, buf, len) \ + ((drv)->ops->dump && ((drv)->ops->dump(drv, ip, event, buf, len), true)) +#define note_vprintf(drv, ip, fmt, va) \ + ((drv)->ops->vprintf && ((drv)->ops->vprintf(drv, ip, fmt, va), true)) +#define note_vbprintf(drv, ip, event, fmt, va) \ + ((drv)->ops->vbprintf && \ + ((drv)->ops->vbprintf(drv, ip, event, fmt, va), true)) + /**************************************************************************** * Private Types ****************************************************************************/ @@ -91,6 +139,13 @@ static unsigned int g_note_disabled_irq_nest[CONFIG_SMP_NCPUS]; #endif #endif +FAR static struct note_driver_s *g_note_drivers[CONFIG_DRIVER_NOTE_MAX + 1] = +{ +#ifdef CONFIG_DRIVER_NOTERAM + &g_noteram_driver +#endif +}; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -407,6 +462,9 @@ void sched_note_start(FAR struct tcb_s *tcb) { struct note_startalloc_s note; unsigned int length; + FAR struct note_driver_s **driver; + bool formatted = false; + #if CONFIG_TASK_NAME_SIZE > 0 int namelen; #endif @@ -416,83 +474,162 @@ void sched_note_start(FAR struct tcb_s *tcb) return; } - /* Copy the task name (if possible) and get the length of the note */ + for (driver = g_note_drivers; *driver; driver++) + { + if (note_start(*driver, tcb)) + { + continue; + } + + if ((*driver)->ops->add == NULL) + { + continue; + } + + if (!formatted) + { + formatted = true; + + /* Copy the task name (if possible) and + * get the length of the note + */ #if CONFIG_TASK_NAME_SIZE > 0 - namelen = strlen(tcb->name); + namelen = strlen(tcb->name); - DEBUGASSERT(namelen <= CONFIG_TASK_NAME_SIZE); - strlcpy(note.nsa_name, tcb->name, sizeof(note.nsa_name)); + DEBUGASSERT(namelen <= CONFIG_TASK_NAME_SIZE); + strlcpy(note.nsa_name, tcb->name, sizeof(note.nsa_name)); - length = SIZEOF_NOTE_START(namelen + 1); + length = SIZEOF_NOTE_START(namelen + 1); #else - length = SIZEOF_NOTE_START(0); + length = SIZEOF_NOTE_START(0); #endif - /* Finish formatting the note */ + /* Finish formatting the note */ - note_common(tcb, ¬e.nsa_cmn, length, NOTE_START); + note_common(tcb, ¬e.nsa_cmn, length, NOTE_START); + } - /* Add the note to circular buffer */ + /* Add the note to circular buffer */ - sched_note_add(¬e, length); + note_add(*driver, ¬e, length); + } } void sched_note_stop(FAR struct tcb_s *tcb) { struct note_stop_s note; + FAR struct note_driver_s **driver; + bool formatted = false; if (!note_isenabled()) { return; } - /* Format the note */ + for (driver = g_note_drivers; *driver; driver++) + { + if (note_stop(*driver, tcb)) + { + continue; + } - note_common(tcb, ¬e.nsp_cmn, sizeof(struct note_stop_s), NOTE_STOP); + if ((*driver)->ops->add == NULL) + { + continue; + } - /* Add the note to circular buffer */ + /* Format the note */ - sched_note_add(¬e, sizeof(struct note_stop_s)); + if (!formatted) + { + formatted = true; + note_common(tcb, ¬e.nsp_cmn, sizeof(struct note_stop_s), + NOTE_STOP); + } + + /* Add the note to circular buffer */ + + note_add(*driver, ¬e, sizeof(struct note_stop_s)); + } } #ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH void sched_note_suspend(FAR struct tcb_s *tcb) { struct note_suspend_s note; + FAR struct note_driver_s **driver; + bool formatted = false; if (!note_isenabled_switch()) { return; } - /* Format the note */ + for (driver = g_note_drivers; *driver; driver++) + { + if (!note_suspend(*driver, tcb)) + { + continue; + } - note_common(tcb, ¬e.nsu_cmn, sizeof(struct note_suspend_s), - NOTE_SUSPEND); - note.nsu_state = tcb->task_state; + if ((*driver)->ops->add == NULL) + { + continue; + } - /* Add the note to circular buffer */ + /* Format the note */ - sched_note_add(¬e, sizeof(struct note_suspend_s)); + if (!formatted) + { + formatted = true; + note_common(tcb, ¬e.nsu_cmn, sizeof(struct note_suspend_s), + NOTE_SUSPEND); + note.nsu_state = tcb->task_state; + } + + /* Add the note to circular buffer */ + + note_add(*driver, ¬e, sizeof(struct note_suspend_s)); + } } void sched_note_resume(FAR struct tcb_s *tcb) { struct note_resume_s note; + FAR struct note_driver_s **driver; + bool formatted = false; if (!note_isenabled_switch()) { return; } - /* Format the note */ + for (driver = g_note_drivers; *driver; driver++) + { + if (note_resume(*driver, tcb)) + { + continue; + } - note_common(tcb, ¬e.nre_cmn, sizeof(struct note_resume_s), NOTE_RESUME); + if ((*driver)->ops->add == NULL) + { + continue; + } - /* Add the note to circular buffer */ + /* Format the note */ - sched_note_add(¬e, sizeof(struct note_resume_s)); + if (!formatted) + { + formatted = true; + note_common(tcb, ¬e.nre_cmn, sizeof(struct note_resume_s), + NOTE_RESUME); + } + + /* Add the note to circular buffer */ + + note_add(*driver, ¬e, sizeof(struct note_resume_s)); + } } #endif @@ -500,119 +637,233 @@ void sched_note_resume(FAR struct tcb_s *tcb) void sched_note_cpu_start(FAR struct tcb_s *tcb, int cpu) { struct note_cpu_start_s note; + FAR struct note_driver_s **driver; + bool formatted = false; if (!note_isenabled()) { return; } - /* Format the note */ + for (driver = g_note_drivers; *driver; driver++) + { + if (note_cpu_start(*driver, tcb, cpu)) + { + continue; + } - note_common(tcb, ¬e.ncs_cmn, sizeof(struct note_cpu_start_s), - NOTE_CPU_START); - note.ncs_target = (uint8_t)cpu; + if ((*driver)->ops->add == NULL) + { + continue; + } - /* Add the note to circular buffer */ + /* Format the note */ - sched_note_add(¬e, sizeof(struct note_cpu_start_s)); + if (!formatted) + { + formatted = true; + note_common(tcb, ¬e.ncs_cmn, sizeof(struct note_cpu_start_s), + NOTE_CPU_START); + note.ncs_target = (uint8_t)cpu; + } + + /* Add the note to circular buffer */ + + note_add(*driver, ¬e, sizeof(struct note_cpu_start_s)); + } } void sched_note_cpu_started(FAR struct tcb_s *tcb) { struct note_cpu_started_s note; + FAR struct note_driver_s **driver; + bool formatted = false; if (!note_isenabled()) { return; } - /* Format the note */ + for (driver = g_note_drivers; *driver; driver++) + { + if (note_cpu_started(*driver, tcb)) + { + continue; + } - note_common(tcb, ¬e.ncs_cmn, sizeof(struct note_cpu_started_s), - NOTE_CPU_STARTED); + if ((*driver)->ops->add == NULL) + { + continue; + } - /* Add the note to circular buffer */ + /* Format the note */ - sched_note_add(¬e, sizeof(struct note_cpu_started_s)); + if (!formatted) + { + formatted = true; + note_common(tcb, ¬e.ncs_cmn, sizeof(struct note_cpu_started_s), + NOTE_CPU_STARTED); + } + + /* Add the note to circular buffer */ + + note_add(*driver, ¬e, sizeof(struct note_cpu_started_s)); + } } #ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH void sched_note_cpu_pause(FAR struct tcb_s *tcb, int cpu) { struct note_cpu_pause_s note; + FAR struct note_driver_s **driver; + bool formatted = false; if (!note_isenabled_switch()) { return; } - /* Format the note */ + for (driver = g_note_drivers; *driver; driver++) + { + if (note_cpu_pause(*driver, tcb, cpu)) + { + continue; + } - note_common(tcb, ¬e.ncp_cmn, sizeof(struct note_cpu_pause_s), - NOTE_CPU_PAUSE); - note.ncp_target = (uint8_t)cpu; + if ((*driver)->ops->add == NULL) + { + continue; + } - /* Add the note to circular buffer */ + /* Format the note */ - sched_note_add(¬e, sizeof(struct note_cpu_pause_s)); + if (!formatted) + { + formatted = true; + note_common(tcb, ¬e.ncp_cmn, sizeof(struct note_cpu_pause_s), + NOTE_CPU_PAUSE); + note.ncp_target = (uint8_t)cpu; + } + + /* Add the note to circular buffer */ + + note_add(*driver, ¬e, sizeof(struct note_cpu_pause_s)); + } } void sched_note_cpu_paused(FAR struct tcb_s *tcb) { struct note_cpu_paused_s note; + FAR struct note_driver_s **driver; + bool formatted = false; if (!note_isenabled_switch()) { return; } - /* Format the note */ + for (driver = g_note_drivers; *driver; driver++) + { + if (note_cpu_paused(*driver, tcb)) + { + continue; + } - note_common(tcb, ¬e.ncp_cmn, sizeof(struct note_cpu_paused_s), - NOTE_CPU_PAUSED); + if ((*driver)->ops->add == NULL) + { + continue; + } - /* Add the note to circular buffer */ + /* Format the note */ - sched_note_add(¬e, sizeof(struct note_cpu_paused_s)); + if (!formatted) + { + formatted = true; + note_common(tcb, ¬e.ncp_cmn, sizeof(struct note_cpu_paused_s), + NOTE_CPU_PAUSED); + } + + /* Add the note to circular buffer */ + + note_add(*driver, ¬e, sizeof(struct note_cpu_paused_s)); + } } void sched_note_cpu_resume(FAR struct tcb_s *tcb, int cpu) { struct note_cpu_resume_s note; + FAR struct note_driver_s **driver; + bool formatted = false; if (!note_isenabled_switch()) { return; } - /* Format the note */ + for (driver = g_note_drivers; *driver; driver++) + { + if (note_cpu_resume(*driver, tcb, cpu)) + { + continue; + } - note_common(tcb, ¬e.ncr_cmn, sizeof(struct note_cpu_resume_s), - NOTE_CPU_RESUME); - note.ncr_target = (uint8_t)cpu; + if ((*driver)->ops->add == NULL) + { + continue; + } - /* Add the note to circular buffer */ + /* Format the note */ - sched_note_add(¬e, sizeof(struct note_cpu_resume_s)); + if (!formatted) + { + formatted = true; + note_common(tcb, ¬e.ncr_cmn, sizeof(struct note_cpu_resume_s), + NOTE_CPU_RESUME); + note.ncr_target = (uint8_t)cpu; + } + + /* Add the note to circular buffer */ + + note_add(*driver, ¬e, sizeof(struct note_cpu_resume_s)); + } } void sched_note_cpu_resumed(FAR struct tcb_s *tcb) { struct note_cpu_resumed_s note; + FAR struct note_driver_s **driver; + bool formatted = false; if (!note_isenabled_switch()) { return; } - /* Format the note */ + for (driver = g_note_drivers; *driver; driver++) + { + if (note_cpu_resumed(*driver, tcb)) + { + continue; + } - note_common(tcb, ¬e.ncr_cmn, sizeof(struct note_cpu_resumed_s), - NOTE_CPU_RESUMED); + if ((*driver)->ops->add == NULL) + { + continue; + } - /* Add the note to circular buffer */ + /* Format the note */ - sched_note_add(¬e, sizeof(struct note_cpu_resumed_s)); + if (!formatted) + { + formatted = true; + note_common(tcb, ¬e.ncr_cmn, sizeof(struct note_cpu_resumed_s), + NOTE_CPU_RESUMED); + } + + /* Add the note to circular buffer */ + + note_add(*driver, ¬e, sizeof(struct note_cpu_resumed_s)); + } } #endif #endif @@ -621,22 +872,41 @@ void sched_note_cpu_resumed(FAR struct tcb_s *tcb) void sched_note_premption(FAR struct tcb_s *tcb, bool locked) { struct note_preempt_s note; + FAR struct note_driver_s **driver; + bool formatted = false; if (!note_isenabled()) { return; } - /* Format the note */ + for (driver = g_note_drivers; *driver; driver++) + { + if (note_premption(*driver, tcb, locked)) + { + continue; + } - note_common(tcb, ¬e.npr_cmn, sizeof(struct note_preempt_s), - locked ? NOTE_PREEMPT_LOCK : NOTE_PREEMPT_UNLOCK); - sched_note_flatten(note.npr_count, - &tcb->lockcount, sizeof(tcb->lockcount)); + if ((*driver)->ops->add == NULL) + { + continue; + } - /* Add the note to circular buffer */ + /* Format the note */ - sched_note_add(¬e, sizeof(struct note_preempt_s)); + if (!formatted) + { + formatted = true; + note_common(tcb, ¬e.npr_cmn, sizeof(struct note_preempt_s), + locked ? NOTE_PREEMPT_LOCK : NOTE_PREEMPT_UNLOCK); + sched_note_flatten(note.npr_count, &tcb->lockcount, + sizeof(tcb->lockcount)); + } + + /* Add the note to circular buffer */ + + note_add(*driver, ¬e, sizeof(struct note_preempt_s)); + } } #endif @@ -644,23 +914,43 @@ void sched_note_premption(FAR struct tcb_s *tcb, bool locked) void sched_note_csection(FAR struct tcb_s *tcb, bool enter) { struct note_csection_s note; + FAR struct note_driver_s **driver; + bool formatted = false; if (!note_isenabled()) { return; } - /* Format the note */ + for (driver = g_note_drivers; *driver; driver++) + { + if (note_csection(*driver, tcb, enter)) + { + continue; + } - note_common(tcb, ¬e.ncs_cmn, sizeof(struct note_csection_s), - enter ? NOTE_CSECTION_ENTER : NOTE_CSECTION_LEAVE); + if ((*driver)->ops->add == NULL) + { + continue; + } + + /* Format the note */ + + if (!formatted) + { + formatted = true; + note_common(tcb, ¬e.ncs_cmn, sizeof(struct note_csection_s), + enter ? NOTE_CSECTION_ENTER : NOTE_CSECTION_LEAVE); #ifdef CONFIG_SMP - sched_note_flatten(note.ncs_count, &tcb->irqcount, sizeof(tcb->irqcount)); + sched_note_flatten(note.ncs_count, &tcb->irqcount, + sizeof(tcb->irqcount)); #endif + } - /* Add the note to circular buffer */ + /* Add the note to circular buffer */ - sched_note_add(¬e, sizeof(struct note_csection_s)); + note_add(*driver, ¬e, sizeof(struct note_csection_s)); + } } #endif @@ -685,22 +975,41 @@ void sched_note_spinlock(FAR struct tcb_s *tcb, int type) { struct note_spinlock_s note; + FAR struct note_driver_s **driver; + bool formatted = false; if (!note_isenabled()) { return; } - /* Format the note */ + for (driver = g_note_drivers; *driver; driver++) + { + if (note_spinlock(*driver, tcb, spinlock, type)) + { + continue; + } - note_common(tcb, ¬e.nsp_cmn, sizeof(struct note_spinlock_s), type); + if ((*driver)->ops->add == NULL) + { + continue; + } - sched_note_flatten(note.nsp_spinlock, &spinlock, sizeof(spinlock)); - note.nsp_value = *(FAR uint8_t *)spinlock; + /* Format the note */ - /* Add the note to circular buffer */ + if (!formatted) + { + formatted = true; + note_common(tcb, ¬e.nsp_cmn, sizeof(struct note_spinlock_s), + type); + sched_note_flatten(note.nsp_spinlock, &spinlock, sizeof(spinlock)); + note.nsp_value = *(FAR uint8_t *)spinlock; + } - sched_note_add(¬e, sizeof(struct note_spinlock_s)); + /* Add the note to circular buffer */ + + note_add(*driver, ¬e, sizeof(struct note_spinlock_s)); + } } #endif @@ -708,6 +1017,8 @@ void sched_note_spinlock(FAR struct tcb_s *tcb, void sched_note_syscall_enter(int nr, int argc, ...) { struct note_syscall_enter_s note; + FAR struct note_driver_s **driver; + bool formatted = false; FAR struct tcb_s *tcb = this_task(); unsigned int length; FAR uint8_t *args; @@ -727,37 +1038,56 @@ void sched_note_syscall_enter(int nr, int argc, ...) } #endif - /* Format the note */ - - length = SIZEOF_NOTE_SYSCALL_ENTER(argc); - note_common(tcb, ¬e.nsc_cmn, length, NOTE_SYSCALL_ENTER); - DEBUGASSERT(nr <= UCHAR_MAX); - note.nsc_nr = nr; - DEBUGASSERT(argc <= MAX_SYSCALL_ARGS); - note.nsc_argc = argc; - - /* If needed, retrieve the given syscall arguments */ - - va_start(ap, argc); - - args = note.nsc_args; - for (i = 0; i < argc; i++) + for (driver = g_note_drivers; *driver; driver++) { - arg = (uintptr_t)va_arg(ap, uintptr_t); - sched_note_flatten(args, &arg, sizeof(arg)); - args += sizeof(uintptr_t); + if (note_syscall_enter(*driver, nr)) + { + continue; + } + + if ((*driver)->ops->add == NULL) + { + continue; + } + + /* Format the note */ + + if (!formatted) + { + formatted = true; + length = SIZEOF_NOTE_SYSCALL_ENTER(argc); + note_common(tcb, ¬e.nsc_cmn, length, NOTE_SYSCALL_ENTER); + DEBUGASSERT(nr <= UCHAR_MAX); + note.nsc_nr = nr; + DEBUGASSERT(argc <= MAX_SYSCALL_ARGS); + note.nsc_argc = argc; + + /* If needed, retrieve the given syscall arguments */ + + va_start(ap, argc); + + args = note.nsc_args; + for (i = 0; i < argc; i++) + { + arg = (uintptr_t)va_arg(ap, uintptr_t); + sched_note_flatten(args, &arg, sizeof(arg)); + args += sizeof(uintptr_t); + } + + va_end(ap); + } + + /* Add the note to circular buffer */ + + note_add(*driver, ¬e, length); } - - va_end(ap); - - /* Add the note to circular buffer */ - - sched_note_add((FAR const uint8_t *)¬e, length); } void sched_note_syscall_leave(int nr, uintptr_t result) { struct note_syscall_leave_s note; + FAR struct note_driver_s **driver; + bool formatted = false; FAR struct tcb_s *tcb = this_task(); if (!note_isenabled_syscall(nr)) @@ -765,18 +1095,36 @@ void sched_note_syscall_leave(int nr, uintptr_t result) return; } - /* Format the note */ + for (driver = g_note_drivers; *driver; driver++) + { + if (note_syscall_leave(*driver, nr)) + { + continue; + } - note_common(tcb, ¬e.nsc_cmn, sizeof(struct note_syscall_leave_s), - NOTE_SYSCALL_LEAVE); - DEBUGASSERT(nr <= UCHAR_MAX); - note.nsc_nr = nr; + if ((*driver)->ops->add == NULL) + { + continue; + } - sched_note_flatten(note.nsc_result, &result, sizeof(result)); + /* Format the note */ - /* Add the note to circular buffer */ + if (!formatted) + { + formatted = true; + note_common(tcb, ¬e.nsc_cmn, + sizeof(struct note_syscall_leave_s), + NOTE_SYSCALL_LEAVE); + DEBUGASSERT(nr <= UCHAR_MAX); + note.nsc_nr = nr; - sched_note_add(¬e, sizeof(struct note_syscall_leave_s)); + sched_note_flatten(note.nsc_result, &result, sizeof(result)); + } + + /* Add the note to circular buffer */ + + note_add(*driver, ¬e, sizeof(struct note_syscall_leave_s)); + } } #endif @@ -784,6 +1132,8 @@ void sched_note_syscall_leave(int nr, uintptr_t result) void sched_note_irqhandler(int irq, FAR void *handler, bool enter) { struct note_irqhandler_s note; + FAR struct note_driver_s **driver; + bool formatted = false; FAR struct tcb_s *tcb = this_task(); if (!note_isenabled_irq(irq, enter)) @@ -791,17 +1141,31 @@ void sched_note_irqhandler(int irq, FAR void *handler, bool enter) return; } - /* Format the note */ + for (driver = g_note_drivers; *driver; driver++) + { + if (note_irqhandler(*driver, irq, handler, enter)) + { + continue; + } - note_common(tcb, ¬e.nih_cmn, sizeof(struct note_irqhandler_s), - enter ? NOTE_IRQ_ENTER : NOTE_IRQ_LEAVE); - DEBUGASSERT(irq <= UCHAR_MAX); - note.nih_irq = irq; + if ((*driver)->ops->add == NULL) + { + continue; + } - /* Add the note to circular buffer */ + if (!formatted) + { + formatted = true; + note_common(tcb, ¬e.nih_cmn, sizeof(struct note_irqhandler_s), + enter ? NOTE_IRQ_ENTER : NOTE_IRQ_LEAVE); + DEBUGASSERT(irq <= UCHAR_MAX); + note.nih_irq = irq; + } - sched_note_add((FAR const uint8_t *)¬e, - sizeof(struct note_irqhandler_s)); + /* Add the note to circular buffer */ + + note_add(*driver, ¬e, sizeof(struct note_irqhandler_s)); + } } #endif @@ -811,6 +1175,8 @@ void sched_note_string(uintptr_t ip, FAR const char *buf) FAR struct note_string_s *note; uint8_t data[255]; unsigned int length; + FAR struct note_driver_s **driver; + bool formatted = false; FAR struct tcb_s *tcb = this_task(); if (!note_isenabled_dump()) @@ -818,31 +1184,48 @@ void sched_note_string(uintptr_t ip, FAR const char *buf) return; } - note = (FAR struct note_string_s *)data; - length = SIZEOF_NOTE_STRING(strlen(buf)); - if (length > sizeof(data)) + for (driver = g_note_drivers; *driver; driver++) { - length = sizeof(data); + if (note_string(*driver, ip, buf)) + { + continue; + } + + if ((*driver)->ops->add == NULL) + { + continue; + } + + /* Format the note */ + + if (!formatted) + { + formatted = true; + note = (FAR struct note_string_s *)data; + length = SIZEOF_NOTE_STRING(strlen(buf)); + if (length > sizeof(data)) + { + length = sizeof(data); + } + + note_common(tcb, ¬e->nst_cmn, length, NOTE_DUMP_STRING); + sched_note_flatten(note->nst_ip, &ip, sizeof(uintptr_t)); + memcpy(note->nst_data, buf, length - sizeof(struct note_string_s)); + data[length - 1] = '\0'; + } + + /* Add the note to circular buffer */ + + note_add(*driver, note, length); } - - /* Format the note */ - - note_common(tcb, ¬e->nst_cmn, length, - NOTE_DUMP_STRING); - - sched_note_flatten(note->nst_ip, &ip, sizeof(uintptr_t)); - memcpy(note->nst_data, buf, length - sizeof(struct note_string_s)); - data[length - 1] = '\0'; - - /* Add the note to circular buffer */ - - sched_note_add(note, length); } void sched_note_dump(uintptr_t ip, uint8_t event, FAR const void *buf, size_t len) { FAR struct note_binary_s *note; + FAR struct note_driver_s **driver; + bool formatted = false; char data[255]; unsigned int length; FAR struct tcb_s *tcb = this_task(); @@ -852,23 +1235,41 @@ void sched_note_dump(uintptr_t ip, uint8_t event, return; } - note = (FAR struct note_binary_s *)data; - length = SIZEOF_NOTE_BINARY(len); - if (length > sizeof(data)) + for (driver = g_note_drivers; *driver; driver++) { - length = sizeof(data); + if (note_dump(*driver, ip, buf, len)) + { + continue; + } + + if ((*driver)->ops->add == NULL) + { + continue; + } + + /* Format the note */ + + if (!formatted) + { + formatted = true; + note = (FAR struct note_binary_s *)data; + length = SIZEOF_NOTE_BINARY(len); + if (length > sizeof(data)) + { + length = sizeof(data); + } + + note_common(tcb, ¬e->nbi_cmn, length, NOTE_DUMP_BINARY); + sched_note_flatten(note->nbi_ip, &ip, sizeof(uintptr_t)); + note->nbi_event = event; + memcpy(note->nbi_data, buf, + length - sizeof(struct note_binary_s) + 1); + } + + /* Add the note to circular buffer */ + + note_add(*driver, note, length); } - - /* Format the note */ - - note_common(tcb, ¬e->nbi_cmn, length, NOTE_DUMP_BINARY); - sched_note_flatten(note->nbi_ip, &ip, sizeof(uintptr_t)); - note->nbi_event = event; - memcpy(note->nbi_data, buf, length - sizeof(struct note_binary_s) + 1); - - /* Add the note to circular buffer */ - - sched_note_add(note, length); } void sched_note_vprintf(uintptr_t ip, @@ -877,6 +1278,8 @@ void sched_note_vprintf(uintptr_t ip, FAR struct note_string_s *note; uint8_t data[255]; unsigned int length; + FAR struct note_driver_s **driver; + bool formatted = false; FAR struct tcb_s *tcb = this_task(); if (!note_isenabled_dump()) @@ -884,33 +1287,51 @@ void sched_note_vprintf(uintptr_t ip, return; } - note = (FAR struct note_string_s *)data; - length = vsnprintf(note->nst_data, - sizeof(data) - sizeof(struct note_string_s), - fmt, - va); - length = SIZEOF_NOTE_STRING(length); - if (length > sizeof(data)) + for (driver = g_note_drivers; *driver; driver++) { - length = sizeof(data); + if (note_vprintf(*driver, ip, fmt, va)) + { + continue; + } + + if ((*driver)->ops->add == NULL) + { + continue; + } + + /* Format the note */ + + if (!formatted) + { + formatted = true; + note = (FAR struct note_string_s *)data; + length = vsnprintf(note->nst_data, + sizeof(data) - sizeof(struct note_string_s), + fmt, + va); + length = SIZEOF_NOTE_STRING(length); + if (length > sizeof(data)) + { + length = sizeof(data); + } + + note_common(tcb, ¬e->nst_cmn, length, NOTE_DUMP_STRING); + + sched_note_flatten(note->nst_ip, &ip, sizeof(uintptr_t)); + } + + /* Add the note to circular buffer */ + + note_add(*driver, note, length); } - - /* Format the note */ - - note_common(tcb, ¬e->nst_cmn, length, - NOTE_DUMP_STRING); - - sched_note_flatten(note->nst_ip, &ip, sizeof(uintptr_t)); - - /* Add the note to circular buffer */ - - sched_note_add(note, length); } void sched_note_vbprintf(uintptr_t ip, uint8_t event, FAR const char *fmt, va_list va) { FAR struct note_binary_s *note; + FAR struct note_driver_s **driver; + bool formatted = false; uint8_t data[255]; begin_packed_struct union { @@ -948,163 +1369,180 @@ void sched_note_vbprintf(uintptr_t ip, uint8_t event, return; } - note = (FAR struct note_binary_s *)data; - length = sizeof(data) - sizeof(struct note_binary_s) + 1; - - while ((c = *fmt++) != '\0') + for (driver = g_note_drivers; *driver; driver++) { - if (c != '%' && search_fmt == 0) + if (note_vbprintf(*driver, ip, event, fmt, va)) { continue; } - search_fmt = 1; - var = (FAR void *)¬e->nbi_data[next]; - - if (c == 'd' || c == 'i' || c == 'u' || - c == 'o' || c == 'x' || c == 'X') + if ((*driver)->ops->add == NULL) { - if (*(fmt - 2) == 'h' && *(fmt - 3) == 'h') + continue; + } + + /* Format the note */ + + if (!formatted) + { + formatted = true; + note = (FAR struct note_binary_s *)data; + length = sizeof(data) - sizeof(struct note_binary_s) + 1; + + while ((c = *fmt++) != '\0') { - if (next + sizeof(var->c) > length) + if (c != '%' && search_fmt == 0) { - break; + continue; } - var->c = va_arg(va, int); - next += sizeof(var->c); - } - else if (*(fmt - 2) == 'h') - { - if (next + sizeof(var->s) > length) - { - break; - } + search_fmt = 1; + var = (FAR void *)¬e->nbi_data[next]; - var->s = va_arg(va, int); - next += sizeof(var->s); - } - else if (*(fmt - 2) == 'j') - { - if (next + sizeof(var->im) > length) + if (c == 'd' || c == 'i' || c == 'u' || + c == 'o' || c == 'x' || c == 'X') { - break; - } + if (*(fmt - 2) == 'h' && *(fmt - 3) == 'h') + { + if (next + sizeof(var->c) > length) + { + break; + } - var->im = va_arg(va, intmax_t); - next += sizeof(var->im); - } + var->c = va_arg(va, int); + next += sizeof(var->c); + } + else if (*(fmt - 2) == 'h') + { + if (next + sizeof(var->s) > length) + { + break; + } + + var->s = va_arg(va, int); + next += sizeof(var->s); + } + else if (*(fmt - 2) == 'j') + { + if (next + sizeof(var->im) > length) + { + break; + } + + var->im = va_arg(va, intmax_t); + next += sizeof(var->im); + } #ifdef CONFIG_HAVE_LONG_LONG - else if (*(fmt - 2) == 'l' && *(fmt - 3) == 'l') - { - if (next + sizeof(var->ll) > length) - { - break; - } + else if (*(fmt - 2) == 'l' && *(fmt - 3) == 'l') + { + if (next + sizeof(var->ll) > length) + { + break; + } - var->ll = va_arg(va, long long); - next += sizeof(var->ll); - } + var->ll = va_arg(va, long long); + next += sizeof(var->ll); + } #endif - else if (*(fmt - 2) == 'l') - { - if (next + sizeof(var->l) > length) - { - break; + else if (*(fmt - 2) == 'l') + { + if (next + sizeof(var->l) > length) + { + break; + } + + var->l = va_arg(va, long); + next += sizeof(var->l); + } + else if (*(fmt - 2) == 'z') + { + if (next + sizeof(var->sz) > length) + { + break; + } + + var->sz = va_arg(va, size_t); + next += sizeof(var->sz); + } + else if (*(fmt - 2) == 't') + { + if (next + sizeof(var->ptr) > length) + { + break; + } + + var->ptr = va_arg(va, ptrdiff_t); + next += sizeof(var->ptr); + } + else + { + if (next + sizeof(var->i) > length) + { + break; + } + + var->i = va_arg(va, int); + next += sizeof(var->i); + } + + search_fmt = 0; } - var->l = va_arg(va, long); - next += sizeof(var->l); - } - else if (*(fmt - 2) == 'z') - { - if (next + sizeof(var->sz) > length) + if (c == 'e' || c == 'f' || c == 'g' || + c == 'E' || c == 'F' || c == 'G') { - break; - } - - var->sz = va_arg(va, size_t); - next += sizeof(var->sz); - } - else if (*(fmt - 2) == 't') - { - if (next + sizeof(var->ptr) > length) - { - break; - } - - var->ptr = va_arg(va, ptrdiff_t); - next += sizeof(var->ptr); - } - else - { - if (next + sizeof(var->i) > length) - { - break; - } - - var->i = va_arg(va, int); - next += sizeof(var->i); - } - - search_fmt = 0; - } - - if (c == 'e' || c == 'f' || c == 'g' || - c == 'E' || c == 'F' || c == 'G') - { - if (*(fmt - 2) == 'L') - { + if (*(fmt - 2) == 'L') + { #ifdef CONFIG_HAVE_LONG_DOUBLE - if (next + sizeof(var->ld) > length) - { - break; - } + if (next + sizeof(var->ld) > length) + { + break; + } - var->ld = va_arg(va, long double); - next += sizeof(var->ld); + var->ld = va_arg(va, long double); + next += sizeof(var->ld); #endif - } - else if (*(fmt - 2) == 'l') - { + } + else if (*(fmt - 2) == 'l') + { #ifdef CONFIG_HAVE_DOUBLE - if (next + sizeof(var->d) > length) - { - break; - } + if (next + sizeof(var->d) > length) + { + break; + } - var->d = va_arg(va, double); - next += sizeof(var->d); + var->d = va_arg(va, double); + next += sizeof(var->d); #endif - } - else + } + else #ifdef CONFIG_HAVE_FLOAT - { - if (next + sizeof(var->l) > length) - { - break; - } + { + if (next + sizeof(var->l) > length) + { + break; + } - var->l = va_arg(va, double); - next += sizeof(var->l); + var->l = va_arg(va, double); + next += sizeof(var->l); #endif + } + + search_fmt = 0; + } } - search_fmt = 0; + length = SIZEOF_NOTE_BINARY(next); + + note_common(tcb, ¬e->nbi_cmn, length, NOTE_DUMP_BINARY); + sched_note_flatten(note->nbi_ip, &ip, sizeof(uintptr_t)); + note->nbi_event = event; } + + /* Add the note to circular buffer */ + + note_add(*driver, note, length); } - - length = SIZEOF_NOTE_BINARY(next); - - /* Format the note */ - - note_common(tcb, ¬e->nbi_cmn, length, NOTE_DUMP_BINARY); - sched_note_flatten(note->nbi_ip, &ip, sizeof(uintptr_t)); - note->nbi_event = event; - - /* Add the note to circular buffer */ - - sched_note_add(note, length); } void sched_note_printf(uintptr_t ip, diff --git a/drivers/note/noteram_driver.c b/drivers/note/noteram_driver.c index 09a3ecf49b1..39bb88263c7 100644 --- a/drivers/note/noteram_driver.c +++ b/drivers/note/noteram_driver.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include @@ -73,6 +74,8 @@ static int noteram_open(FAR struct file *filep); static ssize_t noteram_read(FAR struct file *filep, FAR char *buffer, size_t buflen); static int noteram_ioctl(struct file *filep, int cmd, unsigned long arg); +static void noteram_add(FAR struct note_driver_s *drv, + FAR const void *note, size_t len); /**************************************************************************** * Private Data @@ -105,10 +108,24 @@ static struct noteram_info_s g_noteram_info = static struct noteram_taskname_s g_noteram_taskname; #endif +static const struct note_driver_ops_s g_noteram_ops = +{ + noteram_add +}; + #ifdef CONFIG_SMP static volatile spinlock_t g_noteram_lock; #endif +/**************************************************************************** + * Public Data + ****************************************************************************/ + +struct note_driver_s g_noteram_driver = +{ + &g_noteram_ops, +}; + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -769,11 +786,7 @@ static int noteram_ioctl(struct file *filep, int cmd, unsigned long arg) } /**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: sched_note_add + * Name: noteram_add * * Description: * Add the variable length note to the transport layer @@ -790,7 +803,8 @@ static int noteram_ioctl(struct file *filep, int cmd, unsigned long arg) * ****************************************************************************/ -void sched_note_add(FAR const void *note, size_t notelen) +static void noteram_add(FAR struct note_driver_s *drv, + FAR const void *note, size_t notelen) { FAR const char *buf = note; unsigned int head; @@ -877,6 +891,10 @@ void sched_note_add(FAR const void *note, size_t notelen) up_irq_restore(flags); } +/**************************************************************************** + * Public Functions + ****************************************************************************/ + /**************************************************************************** * Name: noteram_register * diff --git a/include/nuttx/note/note_driver.h b/include/nuttx/note/note_driver.h index a312f2e5af9..ebd6bd952fa 100644 --- a/include/nuttx/note/note_driver.h +++ b/include/nuttx/note/note_driver.h @@ -25,7 +25,11 @@ * Included Files ****************************************************************************/ -#include +#include +#include +#include + +#include /**************************************************************************** * Pre-processor Definitions @@ -35,6 +39,70 @@ * Public Types ****************************************************************************/ +struct note_driver_s; + +struct note_driver_ops_s +{ + CODE void (*add)(FAR struct note_driver_s *drv, + FAR const void *note, size_t notelen); + CODE void (*start)(FAR struct note_driver_s *drv, FAR struct tcb_s *tcb); + CODE void (*stop)(FAR struct note_driver_s *drv, FAR struct tcb_s *tcb); +#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH + CODE void (*suspend)(FAR struct note_driver_s *drv, FAR struct tcb_s *tcb); + CODE void (*resume)(FAR struct note_driver_s *drv, FAR struct tcb_s *tcb); +# ifdef CONFIG_SMP + CODE void (*cpu_start)(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb, int cpu); + CODE void (*cpu_started)(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb); + CODE void (*cpu_pause)(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb, int cpu); + CODE void (*cpu_paused)(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb); + CODE void (*cpu_resume)(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb, int cpu); + CODE void (*cpu_resumed)(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb); +# endif +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION + CODE void (*premption)(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb, bool locked); +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION + CODE void (*csection)(FAR struct note_driver_s *drv, + FAR struct tcb_s *tcb, bool enter); +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_SPINLOCKS + CODE void (*spinlock)(FAR struct note_driver_s *drv, FAR struct tcb_s *tcb, + FAR volatile void *spinlock, int type); +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL + CODE void (*syscall_enter)(FAR struct note_driver_s *drv, int nr); + CODE void (*syscall_leave)(FAR struct note_driver_s *drv, int nr); +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER + CODE void (*irqhandler)(FAR struct note_driver_s *drv, int irq, + FAR void *handler, bool enter); +#endif +#ifdef CONFIG_SCHED_INSTRUMENTATION_DUMP + CODE void (*string)(FAR struct note_driver_s *drv, uintptr_t ip, + FAR const char *buf); + CODE void (*dump)(FAR struct note_driver_s *drv, uintptr_t ip, + uint8_t event, FAR const void *buf, size_t len); + CODE void (*vprintf)(FAR struct note_driver_s *drv, uintptr_t ip, + FAR const char *fmt, va_list va) printflike(3, 0); + CODE void (*vbprintf)(FAR struct note_driver_s *drv, uintptr_t ip, + uint8_t event, FAR const char *fmt, + va_list va) printflike(4, 0); +#endif +}; + +struct note_driver_s +{ + FAR const struct note_driver_ops_s *ops; +}; + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ diff --git a/include/nuttx/note/noteram_driver.h b/include/nuttx/note/noteram_driver.h index 784ecefb1fd..2757eb66846 100644 --- a/include/nuttx/note/noteram_driver.h +++ b/include/nuttx/note/noteram_driver.h @@ -83,6 +83,12 @@ struct noteram_get_taskname_s }; #endif +/**************************************************************************** + * Public Data + ****************************************************************************/ + +extern struct note_driver_s g_noteram_driver; + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ diff --git a/include/nuttx/sched_note.h b/include/nuttx/sched_note.h index 56bbe137c49..5cf23e9f5b3 100644 --- a/include/nuttx/sched_note.h +++ b/include/nuttx/sched_note.h @@ -557,26 +557,6 @@ void sched_note_bprintf(uintptr_t ip, uint8_t event, #if defined(__KERNEL__) || defined(CONFIG_BUILD_FLAT) -/**************************************************************************** - * Name: sched_note_add - * - * Description: - * Add the variable length note to the transport layer - * - * Input Parameters: - * note - The note buffer - * notelen - The buffer length - * - * Returned Value: - * None - * - * Assumptions: - * We are within a critical section. - * - ****************************************************************************/ - -void sched_note_add(FAR const void *note, size_t notelen); - /**************************************************************************** * Name: sched_note_filter_mode *