From 34359972344523548c0fce4654916ae532bc9e37 Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Fri, 11 Aug 2023 10:31:02 +0800 Subject: [PATCH 1/7] drivers/noteram: move trace_dump to noteram Signed-off-by: yinshengkai --- drivers/note/noteram_driver.c | 737 ++++++++++++++++++++++++++++++++-- 1 file changed, 705 insertions(+), 32 deletions(-) diff --git a/drivers/note/noteram_driver.c b/drivers/note/noteram_driver.c index 2d0b116800ed7..ec7cbc9ba79c6 100644 --- a/drivers/note/noteram_driver.c +++ b/drivers/note/noteram_driver.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -39,6 +40,32 @@ #include #include +#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL +# ifdef CONFIG_LIB_SYSCALL +# include +# else +# define CONFIG_LIB_SYSCALL +# include +# undef CONFIG_LIB_SYSCALL +# endif +#endif + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define NCPUS CONFIG_SMP_NCPUS + +/* Renumber idle task PIDs + * In NuttX, PID number less than NCPUS are idle tasks. + * In Linux, there is only one idle task of PID 0. + */ + +#define get_pid(pid) ((pid) < NCPUS ? 0 : (pid)) + +#define get_task_state(s) \ + ((s) == 0 ? 'X' : ((s) <= LAST_READY_TO_RUN_STATE ? 'R' : 'S')) + /**************************************************************************** * Private Types ****************************************************************************/ @@ -55,17 +82,54 @@ struct noteram_driver_s spinlock_t lock; }; +/* The structure to hold the context data of trace dump */ + +struct noteram_dump_cpu_context_s +{ + int intr_nest; /* Interrupt nest level */ + bool pendingswitch; /* sched_switch pending flag */ + int current_state; /* Task state of the current line */ + pid_t current_pid; /* Task PID of the current line */ + pid_t next_pid; /* Task PID of the next line */ + uint8_t current_priority; /* Task Priority of the current line */ + uint8_t next_priority; /* Task Priority of the next line */ +}; + +struct noteram_dump_task_context_s +{ + FAR struct noteram_dump_task_context_s *next; + pid_t pid; /* Task PID */ + int syscall_nest; /* Syscall nest level */ + char name[CONFIG_TASK_NAME_SIZE + 1]; /* Task name (with NULL terminator) */ +}; + +struct noteram_dump_context_s +{ + int buflen; /* The length of the dumped data */ + char buffer[256]; /* Buffer to hold the line to be dumped */ + struct noteram_dump_cpu_context_s cpu[NCPUS]; + FAR struct noteram_dump_task_context_s *task; +}; + /**************************************************************************** * Private Function Prototypes ****************************************************************************/ static int noteram_open(FAR struct file *filep); +static int noteram_close(FAR struct file *filep); static ssize_t noteram_read(FAR struct file *filep, FAR char *buffer, size_t buflen); static int noteram_ioctl(struct file *filep, int cmd, unsigned long arg); static void noteram_add(FAR struct note_driver_s *drv, FAR const void *note, size_t len); +static void +noteram_dump_init_context(FAR struct noteram_dump_context_s *ctx); +static void +noteram_dump_fini_context(FAR struct noteram_dump_context_s *ctx); +static int noteram_dump_one(FAR uint8_t *p, + FAR struct noteram_dump_context_s *ctx); + /**************************************************************************** * Private Data ****************************************************************************/ @@ -73,7 +137,7 @@ static void noteram_add(FAR struct note_driver_s *drv, static const struct file_operations g_noteram_fops = { noteram_open, /* open */ - NULL, /* close */ + noteram_close, /* close */ noteram_read, /* read */ NULL, /* write */ NULL, /* seek */ @@ -391,14 +455,29 @@ static ssize_t noteram_size(FAR struct noteram_driver_s *drv) static int noteram_open(FAR struct file *filep) { - FAR struct noteram_driver_s *drv = - (FAR struct noteram_driver_s *)filep->f_inode->i_private; + FAR struct noteram_dump_context_s *ctx; + FAR struct noteram_driver_s *drv = (FAR struct noteram_driver_s *) + filep->f_inode->i_private; /* Reset the read index of the circular buffer */ - filep->f_priv = drv; drv->ni_read = drv->ni_tail; + ctx = kmm_zalloc(sizeof(*ctx)); + if (ctx == NULL) + { + return -ENOMEM; + } + filep->f_priv = ctx; + noteram_dump_init_context(ctx); + return OK; +} + +int noteram_close(FAR struct file *filep) +{ + FAR struct noteram_dump_context_s *ctx = filep->f_priv; + noteram_dump_fini_context(ctx); + kmm_free(ctx); return OK; } @@ -406,49 +485,71 @@ static int noteram_open(FAR struct file *filep) * Name: noteram_read ****************************************************************************/ -static ssize_t noteram_read(FAR struct file *filep, - FAR char *buffer, size_t buflen) +static ssize_t noteram_read(FAR struct file *filep, FAR char *buffer, + size_t buflen) { - ssize_t notelen; - ssize_t retlen ; + ssize_t ret = -EFBIG; + ssize_t retlen = 0; + uint8_t note[32]; irqstate_t flags; + FAR struct noteram_dump_context_s *ctx = filep->f_priv; FAR struct noteram_driver_s *drv = - (FAR struct noteram_driver_s *)filep->f_priv; + (FAR struct noteram_driver_s *)filep->f_inode->i_private; - DEBUGASSERT(filep != 0 && buffer != NULL && buflen > 0); + /* If we have parsed but unread data last time, + * we should save the last data first + */ + + if (ctx->buflen > 0) + { + if (ctx->buflen > buflen) + { + goto errout; + } + + strlcpy(buffer, ctx->buffer, buflen); + retlen = ctx->buflen; + buffer += ctx->buflen; + buflen -= ctx->buflen; + } /* Then loop, adding as many notes as possible to the user buffer. */ - retlen = 0; - flags = spin_lock_irqsave_wo_note(&drv->lock); do { /* Get the next note (removing it from the buffer) */ - notelen = noteram_get(drv, (FAR uint8_t *)buffer, buflen); - if (notelen < 0) + flags = spin_lock_irqsave_wo_note(&drv->lock); + ret = noteram_get(drv, note, sizeof(note)); + spin_unlock_irqrestore_wo_note(&drv->lock, flags); + if (ret <= 0) { - /* We were unable to read the next note, probably because it will - * not fit into the user buffer. - */ + ctx->buflen = 0; + break; + } - if (retlen == 0) - { - /* If nothing was read then report the error. Otherwise, - * just silently drop the note. - */ + /* Parse notes into text format */ - retlen = notelen; - } + ctx->buflen = noteram_dump_one(note, ctx); + + /* If the remaining space is insufficient, + * return the read data directly first + */ + if (ctx->buflen > buflen) + { + ret = -EFBIG; break; } /* Update pointers from the note that was transferred */ - retlen += notelen; - buffer += notelen; - buflen -= notelen; + strlcpy(buffer, ctx->buffer, buflen); + + retlen += ctx->buflen; + buffer += ctx->buflen; + buflen -= ctx->buflen; + ctx->buflen = 0; /* Will the next note fit? There is a race here and even if the next * note will fit, it may fail still when noteram_get() is called. @@ -457,12 +558,14 @@ static ssize_t noteram_read(FAR struct file *filep, * trying to get the next note (which would cause it to be deleted). */ - notelen = noteram_size(drv); + ret = noteram_size(drv); } - while (notelen > 0 && notelen <= buflen); + while (ret > 0); - spin_unlock_irqrestore_wo_note(&drv->lock, flags); - return retlen; + /* If no data is read, an error code is returned */ + +errout: + return retlen ? retlen : ret; } /**************************************************************************** @@ -473,7 +576,7 @@ static int noteram_ioctl(FAR struct file *filep, int cmd, unsigned long arg) { int ret = -ENOSYS; FAR struct noteram_driver_s *drv = - (FAR struct noteram_driver_s *)filep->f_priv; + (FAR struct noteram_driver_s *)filep->f_inode->i_private; irqstate_t flags = spin_lock_irqsave_wo_note(&drv->lock); /* Handle the ioctl commands */ @@ -626,6 +729,576 @@ static void noteram_add(FAR struct note_driver_s *driver, spin_unlock_irqrestore_wo_note(&drv->lock, flags); } +/**************************************************************************** + * Name: noteram_dump_unflatten + ****************************************************************************/ + +static void noteram_dump_unflatten(FAR void *dst, FAR uint8_t *src, + size_t len) +{ +#ifdef CONFIG_ENDIAN_BIG + FAR uint8_t *end = (FAR uint8_t *)dst + len - 1; + while (len-- > 0) + { + *end-- = *src++; + } +#else + memcpy(dst, src, len); +#endif +} + +/**************************************************************************** + * Name: noteram_dump_init_context + ****************************************************************************/ + +static void noteram_dump_init_context(FAR struct noteram_dump_context_s *ctx) +{ + int cpu; + + /* Initialize the trace dump context */ + + for (cpu = 0; cpu < NCPUS; cpu++) + { + ctx->cpu[cpu].intr_nest = 0; + ctx->cpu[cpu].pendingswitch = false; + ctx->cpu[cpu].current_state = TSTATE_TASK_RUNNING; + ctx->cpu[cpu].current_pid = -1; + ctx->cpu[cpu].next_pid = -1; + ctx->cpu[cpu].current_priority = -1; + ctx->cpu[cpu].next_priority = -1; + } + + ctx->task = NULL; +} + +/**************************************************************************** + * Name: noteram_dump_fini_context + ****************************************************************************/ + +static void noteram_dump_fini_context(FAR struct noteram_dump_context_s *ctx) +{ + FAR struct noteram_dump_task_context_s *tctx; + FAR struct noteram_dump_task_context_s *ntctx; + + /* Finalize the trace dump context */ + + tctx = ctx->task; + ctx->task = NULL; + while (tctx != NULL) + { + ntctx = tctx->next; + free(tctx); + tctx = ntctx; + } +} + +/**************************************************************************** + * Name: copy_task_name + ****************************************************************************/ + +#if CONFIG_TASK_NAME_SIZE > 0 +static void copy_task_name(FAR char *dst, FAR const char *src) +{ + char c; + int i; + + /* Replace space to underline + * Text trace data format cannot use a space as a task name. + */ + + for (i = 0; i < CONFIG_TASK_NAME_SIZE; i++) + { + c = *src++; + if (c == '\0') + { + break; + } + + *dst++ = (c == ' ') ? '_' : c; + } + + *dst = '\0'; +} +#endif + +/**************************************************************************** + * Name: get_task_context + ****************************************************************************/ + +FAR static struct noteram_dump_task_context_s * +get_task_context(pid_t pid, FAR struct noteram_dump_context_s *ctx) +{ + FAR struct noteram_dump_task_context_s **tctxp; + tctxp = &ctx->task; + while (*tctxp != NULL) + { + if ((*tctxp)->pid == pid) + { + return *tctxp; + } + + tctxp = &((*tctxp)->next); + } + + /* Create new trace dump task context */ + + *tctxp = (FAR struct noteram_dump_task_context_s *)malloc( + sizeof(struct noteram_dump_task_context_s)); + if (*tctxp != NULL) + { + (*tctxp)->next = NULL; + (*tctxp)->pid = pid; + (*tctxp)->syscall_nest = 0; + (*tctxp)->name[0] = '\0'; + +#ifdef NOTERAM_GETTASKNAME + { + struct noteram_get_taskname_s tnm; + int res; + + res = note_get_taskname(pid, tnm.taskname); + if (res == 0) + { + copy_task_name((*tctxp)->name, tnm.taskname); + } + } +#endif + } + + return *tctxp; +} + +/**************************************************************************** + * Name: get_task_name + ****************************************************************************/ + +static const char *get_task_name(pid_t pid, + FAR struct noteram_dump_context_s *ctx) +{ + FAR struct noteram_dump_task_context_s *tctx; + + tctx = get_task_context(pid, ctx); + if (tctx != NULL && tctx->name[0] != '\0') + { + return tctx->name; + } + + return ""; +} + +/**************************************************************************** + * Name: noteram_dump_header + ****************************************************************************/ + +static int noteram_dump_header(FAR char *offset, + FAR struct note_common_s *note, + FAR struct noteram_dump_context_s *ctx) +{ + pid_t pid; + uint32_t nsec; + uint32_t sec; + int ret; + + noteram_dump_unflatten(&nsec, note->nc_systime_nsec, sizeof(nsec)); + noteram_dump_unflatten(&sec, note->nc_systime_sec, sizeof(sec)); +#ifdef CONFIG_SMP + int cpu = note->nc_cpu; +#else + int cpu = 0; +#endif + + noteram_dump_unflatten(&pid, note->nc_pid, sizeof(pid)); + + ret = sprintf(offset, "%8s-%-3u [%d] %3" PRIu32 ".%09" PRIu32 ": ", + get_task_name(pid, ctx), get_pid(pid), cpu, sec, nsec); + return ret; +} + +#if (defined CONFIG_SCHED_INSTRUMENTATION_SWITCH) \ + || (defined CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER) +/**************************************************************************** + * Name: noteram_dump_sched_switch + ****************************************************************************/ + +static int noteram_dump_sched_switch(FAR char *offset, + FAR struct note_common_s *note, + FAR struct noteram_dump_context_s *ctx) +{ + FAR struct noteram_dump_cpu_context_s *cctx; + uint8_t current_priority; + uint8_t next_priority; + pid_t current_pid; + pid_t next_pid; + int ret; +#ifdef CONFIG_SMP + int cpu = note->nc_cpu; +#else + int cpu = 0; +#endif + + cctx = &ctx->cpu[cpu]; + current_pid = cctx->current_pid; + next_pid = cctx->next_pid; + + current_priority = cctx->current_priority; + next_priority = cctx->next_priority; + + ret = sprintf(offset, + "sched_switch: " + "prev_comm=%s prev_pid=%u prev_prio=%u prev_state=%c ==> " + "next_comm=%s next_pid=%u next_prio=%u\n", + get_task_name(current_pid, ctx), get_pid(current_pid), + current_priority, get_task_state(cctx->current_state), + get_task_name(next_pid, ctx), get_pid(next_pid), + next_priority); + + cctx->current_pid = cctx->next_pid; + cctx->current_priority = cctx->next_priority; + cctx->pendingswitch = false; + return ret; +} +#endif + +/**************************************************************************** + * Name: noteram_dump_one + ****************************************************************************/ + +static int noteram_dump_one(FAR uint8_t *p, + FAR struct noteram_dump_context_s *ctx) +{ + FAR struct note_common_s *note = (FAR struct note_common_s *)p; + FAR struct noteram_dump_cpu_context_s *cctx; + FAR char *buffer = (FAR char *)ctx->buffer; + FAR char *offset = (FAR char *)ctx->buffer; + pid_t pid; +#ifdef CONFIG_SMP + int cpu = note->nc_cpu; +#else + int cpu = 0; +#endif + + cctx = &ctx->cpu[cpu]; + noteram_dump_unflatten(&pid, note->nc_pid, sizeof(pid)); + + if (cctx->current_pid < 0) + { + cctx->current_pid = pid; + } + + /* Output one note */ + + switch (note->nc_type) + { + case NOTE_START: + { +#if CONFIG_TASK_NAME_SIZE > 0 + FAR struct note_start_s *nst = (FAR struct note_start_s *)p; + FAR struct noteram_dump_task_context_s *tctx; + + tctx = get_task_context(pid, ctx); + if (tctx != NULL) + { + copy_task_name(tctx->name, nst->nst_name); + } +#endif + + offset += noteram_dump_header(offset, note, ctx); + offset += sprintf(offset, + "sched_wakeup_new: comm=%s pid=%d target_cpu=%d\n", + get_task_name(pid, ctx), get_pid(pid), cpu); + } + break; + + case NOTE_STOP: + { + /* This note informs the task to be stopped. + * Change current task state for the succeeding NOTE_RESUME. + */ + + cctx->current_state = 0; + } + break; + +#ifdef CONFIG_SCHED_INSTRUMENTATION_SWITCH + case NOTE_SUSPEND: + { + FAR struct note_suspend_s *nsu = (FAR struct note_suspend_s *)p; + + /* This note informs the task to be suspended. + * Preserve the information for the succeeding NOTE_RESUME. + */ + + cctx->current_state = nsu->nsu_state; + } + break; + + case NOTE_RESUME: + { + /* This note informs the task to be resumed. + * The task switch timing depends on the running context. + */ + + cctx->next_pid = pid; + cctx->next_priority = note->nc_priority; + + if (cctx->intr_nest == 0) + { + /* If not in the interrupt context, the task switch is + * executed immediately. + */ + + offset += noteram_dump_header(offset, note, ctx); + offset += noteram_dump_sched_switch(offset, note, ctx); + } + else + { + /* If in the interrupt context, the task switch is postponed + * until leaving the interrupt handler. + */ + + offset += noteram_dump_header(offset, note, ctx); + offset += sprintf(offset, + "sched_waking: comm=%s pid=%d target_cpu=%d\n", + get_task_name(cctx->next_pid, ctx), + get_pid(cctx->next_pid), cpu); + cctx->pendingswitch = true; + } + } + break; +#endif + +#ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL + case NOTE_SYSCALL_ENTER: + { + FAR struct note_syscall_enter_s *nsc; + FAR struct noteram_dump_task_context_s *tctx; + int i; + int j; + uintptr_t arg; + + /* Exclude the case of syscall issued by an interrupt handler and + * nested syscalls to correct tracecompass display. + */ + + if (cctx->intr_nest > 0) + { + break; + } + + tctx = get_task_context(pid, ctx); + if (tctx == NULL) + { + break; + } + + tctx->syscall_nest++; + if (tctx->syscall_nest > 1) + { + break; + } + + nsc = (FAR struct note_syscall_enter_s *)p; + if (nsc->nsc_nr < CONFIG_SYS_RESERVED || + nsc->nsc_nr >= SYS_maxsyscall) + { + break; + } + + offset += noteram_dump_header(offset, note, ctx); + offset += sprintf(offset, "sys_%s(", + g_funcnames[nsc->nsc_nr - CONFIG_SYS_RESERVED]); + + for (i = j = 0; i < nsc->nsc_argc; i++) + { + noteram_dump_unflatten(&arg, nsc->nsc_args, sizeof(arg)); + if (i == 0) + { + offset += sprintf(offset, "arg%d: 0x%" PRIxPTR, i, arg); + } + else + { + offset += sprintf(offset, ", arg%d: 0x%" PRIxPTR, i, arg); + } + } + + offset += sprintf(offset, ")\n"); + } + break; + + case NOTE_SYSCALL_LEAVE: + { + FAR struct note_syscall_leave_s *nsc; + FAR struct noteram_dump_task_context_s *tctx; + uintptr_t result; + + /* Exclude the case of syscall issued by an interrupt handler and + * nested syscalls to correct tracecompass display. + */ + + if (cctx->intr_nest > 0) + { + break; + } + + tctx = get_task_context(pid, ctx); + if (tctx == NULL) + { + break; + } + + tctx->syscall_nest--; + if (tctx->syscall_nest > 0) + { + break; + } + + tctx->syscall_nest = 0; + + nsc = (FAR struct note_syscall_leave_s *)p; + if (nsc->nsc_nr < CONFIG_SYS_RESERVED || + nsc->nsc_nr >= SYS_maxsyscall) + { + break; + } + + offset += noteram_dump_header(offset, note, ctx); + noteram_dump_unflatten(&result, nsc->nsc_result, sizeof(result)); + offset += sprintf(offset, "sys_%s -> 0x%" PRIxPTR "\n", + g_funcnames[nsc->nsc_nr - CONFIG_SYS_RESERVED], + result); + } + break; +#endif + +#ifdef CONFIG_SCHED_INSTRUMENTATION_IRQHANDLER + case NOTE_IRQ_ENTER: + { + FAR struct note_irqhandler_s *nih; + + nih = (FAR struct note_irqhandler_s *)p; + offset += noteram_dump_header(offset, note, ctx); + offset += sprintf(offset, "irq_handler_entry: irq=%u name=%d\n", + nih->nih_irq, nih->nih_irq); + cctx->intr_nest++; + } + break; + + case NOTE_IRQ_LEAVE: + { + FAR struct note_irqhandler_s *nih; + + nih = (FAR struct note_irqhandler_s *)p; + offset += noteram_dump_header(offset, note, ctx); + offset += sprintf(offset, "irq_handler_exit: irq=%u ret=handled\n", + nih->nih_irq); + cctx->intr_nest--; + + if (cctx->intr_nest <= 0) + { + cctx->intr_nest = 0; + if (cctx->pendingswitch) + { + /* If the pending task switch exists, it is executed here */ + + offset += noteram_dump_header(offset, note, ctx); + offset += noteram_dump_sched_switch(offset, note, ctx); + } + } + } + break; +#endif + +#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION + case NOTE_CSECTION_ENTER: + case NOTE_CSECTION_LEAVE: + { + struct note_csection_s *ncs; + ncs = (FAR struct note_csection_s *)p; + offset += noteram_dump_header(offset, &ncs->ncs_cmn, ctx); + offset += sprintf(offset, + "tracing_mark_write: %c|%d|" + "critical_section\n", + note->nc_type == NOTE_CSECTION_ENTER ? + 'B' : 'E', pid); + } + break; +#endif + +#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION + case NOTE_PREEMPT_LOCK: + case NOTE_PREEMPT_UNLOCK: + { + struct note_preempt_s *npr; + int16_t count; + npr = (FAR struct note_preempt_s *)p; + noteram_dump_unflatten(&count, npr->npr_count, sizeof(count)); + offset += noteram_dump_header(offset, &npr->npr_cmn, ctx); + offset += sprintf(offset, "tracing_mark_write: " + "%c|%d|sched_lock:%d\n", + note->nc_type == NOTE_PREEMPT_LOCK ? + 'B' : 'E', pid, count); + } + break; +#endif + +#ifdef CONFIG_SCHED_INSTRUMENTATION_DUMP + case NOTE_DUMP_STRING: + { + FAR struct note_string_s *nst; + uintptr_t ip; + + nst = (FAR struct note_string_s *)p; + offset += noteram_dump_header(offset, note, ctx); + noteram_dump_unflatten(&ip, nst->nst_ip, sizeof(ip)); + + if (nst->nst_data[1] == '\0' && + (nst->nst_data[0] == 'B' || nst->nst_data[0] == 'E')) + { + offset += sprintf(offset, "tracing_mark_write: %c|%d|%pS\n", + nst->nst_data[0], pid, (FAR void *)ip); + } + else + { + offset += sprintf(offset, "tracing_mark_write: %s\n", + nst->nst_data); + } + } + break; + + case NOTE_DUMP_BINARY: + { + FAR struct note_binary_s *nbi; + uint8_t count; + uintptr_t ip; + int i; + + nbi = (FAR struct note_binary_s *)p; + offset += noteram_dump_header(offset, note, ctx); + count = note->nc_length - sizeof(struct note_binary_s) + 1; + + noteram_dump_unflatten(&ip, nbi->nbi_ip, sizeof(ip)); + + offset += sprintf(offset, "0x%" PRIdPTR ": event=%u count=%u", ip, + nbi->nbi_event, count); + for (i = 0; i < count; i++) + { + offset += sprintf(offset, " 0x%x", nbi->nbi_data[i]); + } + + offset += sprintf(offset, "\n"); + } + break; +#endif + + default: + break; + } + + /* Return the length of the processed note */ + + return offset - buffer; +} + /**************************************************************************** * Public Functions ****************************************************************************/ From 5d712a73ce0a6ae81427f451d52b6c4f87810e35 Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Fri, 11 Aug 2023 10:31:03 +0800 Subject: [PATCH 2/7] note: remove NOTERAM_GETTASKNAME Signed-off-by: yinshengkai --- .../components/drivers/character/note.rst | 9 ------ drivers/note/noteram_driver.c | 32 +++---------------- include/nuttx/note/noteram_driver.h | 20 +----------- 3 files changed, 5 insertions(+), 56 deletions(-) diff --git a/Documentation/components/drivers/character/note.rst b/Documentation/components/drivers/character/note.rst index aa0b946c9384d..48b2155ed61d6 100644 --- a/Documentation/components/drivers/character/note.rst +++ b/Documentation/components/drivers/character/note.rst @@ -237,15 +237,6 @@ Noteram Device (``/dev/note``) :return: If success, 0 (``OK``) is returned and the given overwriter mode is set as the current settings. If failed, a negated ``errno`` is returned. -.. c:macro:: NOTERAM_GETTASKNAME - - Get task name string - - :argument: A writable pointer to :c:struct:`noteram_get_taskname_s` - - :return: If success, 0 (``OK``) is returned and the task name corresponding to given pid is stored into the given pointer. - If failed, a negated ``errno`` is returned. - Filter control APIs =================== diff --git a/drivers/note/noteram_driver.c b/drivers/note/noteram_driver.c index ec7cbc9ba79c6..3721cf8c42885 100644 --- a/drivers/note/noteram_driver.c +++ b/drivers/note/noteram_driver.c @@ -627,30 +627,6 @@ static int noteram_ioctl(FAR struct file *filep, int cmd, unsigned long arg) } break; -#ifdef NOTERAM_GETTASKNAME - /* NOTERAM_GETTASKNAME - * - Get task name string - * Argument: A writable pointer to struct note_get_taskname_s - * Result: If -ESRCH, the corresponding task name doesn't - * exist. - */ - - case NOTERAM_GETTASKNAME: - { - FAR struct noteram_get_taskname_s *param; - - if (arg == 0) - { - ret = -EINVAL; - break; - } - - param = (FAR struct noteram_get_taskname_s *)arg; - ret = note_get_taskname(param->pid, param->taskname); - } - break; -#endif - default: break; } @@ -851,15 +827,15 @@ get_task_context(pid_t pid, FAR struct noteram_dump_context_s *ctx) (*tctxp)->syscall_nest = 0; (*tctxp)->name[0] = '\0'; -#ifdef NOTERAM_GETTASKNAME +#ifdef CONFIG_DRIVERS_NOTE_TASKNAME_BUFSIZE { - struct noteram_get_taskname_s tnm; + char taskname[CONFIG_DRIVERS_NOTE_TASKNAME_BUFSIZE]; int res; - res = note_get_taskname(pid, tnm.taskname); + res = note_get_taskname(pid, taskname); if (res == 0) { - copy_task_name((*tctxp)->name, tnm.taskname); + copy_task_name((*tctxp)->name, taskname); } } #endif diff --git a/include/nuttx/note/noteram_driver.h b/include/nuttx/note/noteram_driver.h index c2e85a3f4e4af..ae9ccc195854b 100644 --- a/include/nuttx/note/noteram_driver.h +++ b/include/nuttx/note/noteram_driver.h @@ -46,22 +46,12 @@ * NOTERAM_SETMODE * - Set overwrite mode * Argument: A read-only pointer to unsigned int - * NOTERAM_GETTASKNAME - * - Get task name string - * Argument: A writable pointer to struct - * noteram_get_taskname_s - * Result: If -ESRCH, the corresponding task name doesn't - * exist. */ #ifdef CONFIG_DRIVERS_NOTERAM #define NOTERAM_CLEAR _NOTERAMIOC(0x01) #define NOTERAM_GETMODE _NOTERAMIOC(0x02) #define NOTERAM_SETMODE _NOTERAMIOC(0x03) -#if defined(CONFIG_DRIVERS_NOTE_TASKNAME_BUFSIZE) && \ - CONFIG_DRIVERS_NOTE_TASKNAME_BUFSIZE > 0 -#define NOTERAM_GETTASKNAME _NOTERAMIOC(0x04) -#endif #endif /* Overwrite mode definitions */ @@ -76,15 +66,7 @@ * Public Types ****************************************************************************/ -/* This is the type of the argument passed to the NOTERAM_GETTASKNAME ioctl */ - -#ifdef NOTERAM_GETTASKNAME -struct noteram_get_taskname_s -{ - pid_t pid; - char taskname[CONFIG_TASK_NAME_SIZE + 1]; -}; -#endif +struct noteram_driver_s; /**************************************************************************** * Public Data From a3a784404b322dcb1e97e25e1a681c8c1b59e3ce Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Fri, 11 Aug 2023 10:31:03 +0800 Subject: [PATCH 3/7] sched: remove space in task name Signed-off-by: yinshengkai --- sched/init/nx_start.c | 4 ++-- sched/task/task_setup.c | 18 +++++++++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/sched/init/nx_start.c b/sched/init/nx_start.c index d4bc7f1bc4037..f912e57c48275 100644 --- a/sched/init/nx_start.c +++ b/sched/init/nx_start.c @@ -278,9 +278,9 @@ static struct task_tcb_s g_idletcb[CONFIG_SMP_NCPUS]; #if CONFIG_TASK_NAME_SIZE <= 0 || !defined(CONFIG_SMP) # ifdef CONFIG_SMP -static const char g_idlename[] = "CPU Idle"; +static const char g_idlename[] = "CPU_Idle"; # else -static const char g_idlename[] = "Idle Task"; +static const char g_idlename[] = "Idle_Task"; # endif #endif diff --git a/sched/task/task_setup.c b/sched/task/task_setup.c index 157d0def9df0d..3adf7df2577d0 100644 --- a/sched/task/task_setup.c +++ b/sched/task/task_setup.c @@ -25,6 +25,7 @@ #include #include +#include #include #include #include @@ -484,9 +485,24 @@ static int nxthread_setup_scheduler(FAR struct tcb_s *tcb, int priority, static void nxtask_setup_name(FAR struct task_tcb_s *tcb, FAR const char *name) { + FAR char *dst = tcb->cmn.name; + int i; + /* Copy the name into the TCB */ - strlcpy(tcb->cmn.name, name, sizeof(tcb->cmn.name)); + for (i = 0; i < CONFIG_TASK_NAME_SIZE; i++) + { + char c = *name++; + + if (c == '\0') + { + break; + } + + *dst++ = isspace(c) ? '_' : c; + } + + *dst = '\0'; } #else # define nxtask_setup_name(t,n) From 63a5b93ff02a4e127ec57208889be2bffd39a4f6 Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Fri, 11 Aug 2023 10:31:03 +0800 Subject: [PATCH 4/7] note: directly returns the taskname pointer Signed-off-by: yinshengkai --- drivers/note/note_driver.c | 23 ++++++----------------- drivers/note/noteram_driver.c | 7 +++---- include/nuttx/note/note_driver.h | 6 ++---- 3 files changed, 11 insertions(+), 25 deletions(-) diff --git a/drivers/note/note_driver.c b/drivers/note/note_driver.c index d7bcc01182acd..3c88fa241e8b0 100644 --- a/drivers/note/note_driver.c +++ b/drivers/note/note_driver.c @@ -177,8 +177,7 @@ FAR static struct note_driver_s * static struct note_taskname_s g_note_taskname; #endif -#if defined(CONFIG_SCHED_INSTRUMENTATION_FILTER) || \ - (CONFIG_DRIVERS_NOTE_TASKNAME_BUFSIZE > 0) +#if defined(CONFIG_SCHED_INSTRUMENTATION_FILTER) static spinlock_t g_note_lock; #endif @@ -1933,39 +1932,29 @@ void sched_note_filter_tag(FAR struct note_filter_tag_s *oldf, * * Input Parameters: * PID - Task ID - * name - Task name buffer - * this buffer must be greater than CONFIG_TASK_NAME_SIZE + 1 * * Returned Value: - * Retrun OK if task name can be retrieved, otherwise -ESRCH - * + * Retrun name if task name can be retrieved, otherwise NULL ****************************************************************************/ -int note_get_taskname(pid_t pid, FAR char *buffer) +FAR const char *note_get_taskname(pid_t pid) { FAR struct note_taskname_info_s *ti; FAR struct tcb_s *tcb; - irqstate_t irq_mask; - irq_mask = spin_lock_irqsave_wo_note(&g_note_lock); tcb = nxsched_get_tcb(pid); if (tcb != NULL) { - strlcpy(buffer, tcb->name, CONFIG_TASK_NAME_SIZE + 1); - spin_unlock_irqrestore_wo_note(&g_note_lock, irq_mask); - return OK; + return tcb->name; } ti = note_find_taskname(pid); if (ti != NULL) { - strlcpy(buffer, ti->name, CONFIG_TASK_NAME_SIZE + 1); - spin_unlock_irqrestore_wo_note(&g_note_lock, irq_mask); - return OK; + return ti->name; } - spin_unlock_irqrestore_wo_note(&g_note_lock, irq_mask); - return -ESRCH; + return NULL; } #endif diff --git a/drivers/note/noteram_driver.c b/drivers/note/noteram_driver.c index 3721cf8c42885..a1c4107fe1353 100644 --- a/drivers/note/noteram_driver.c +++ b/drivers/note/noteram_driver.c @@ -829,11 +829,10 @@ get_task_context(pid_t pid, FAR struct noteram_dump_context_s *ctx) #ifdef CONFIG_DRIVERS_NOTE_TASKNAME_BUFSIZE { - char taskname[CONFIG_DRIVERS_NOTE_TASKNAME_BUFSIZE]; - int res; + FAR const char *taskname; - res = note_get_taskname(pid, taskname); - if (res == 0) + taskname = note_get_taskname(pid); + if (taskname != NULL) { copy_task_name((*tctxp)->name, taskname); } diff --git a/include/nuttx/note/note_driver.h b/include/nuttx/note/note_driver.h index 70d8617a45a97..66d52bde068ed 100644 --- a/include/nuttx/note/note_driver.h +++ b/include/nuttx/note/note_driver.h @@ -145,15 +145,13 @@ int note_initialize(void); * * Input Parameters: * PID - Task ID - * name - Task name buffer - * this buffer must be greater than CONFIG_TASK_NAME_SIZE + 1 * * Returned Value: - * Retrun OK if task name can be retrieved, otherwise -ESRCH + * Retrun name if task name can be retrieved, otherwise NULL * ****************************************************************************/ -int note_get_taskname(pid_t pid, FAR char *name); +FAR const char *note_get_taskname(pid_t pid); #endif /* defined(CONFIG_DRIVERS_NOTE_TASKNAME_BUFSIZE) && \ * CONFIG_DRIVERS_NOTE_TASKNAME_BUFSIZE > 0 From 1ae67f7b1d63a652dcad2d390b2b54e2a8aedd40 Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Fri, 11 Aug 2023 10:31:03 +0800 Subject: [PATCH 5/7] note: remove the name field of task_context Signed-off-by: yinshengkai --- drivers/note/noteram_driver.c | 75 +++++------------------------------ 1 file changed, 10 insertions(+), 65 deletions(-) diff --git a/drivers/note/noteram_driver.c b/drivers/note/noteram_driver.c index a1c4107fe1353..3fb8099f10271 100644 --- a/drivers/note/noteram_driver.c +++ b/drivers/note/noteram_driver.c @@ -100,7 +100,6 @@ struct noteram_dump_task_context_s FAR struct noteram_dump_task_context_s *next; pid_t pid; /* Task PID */ int syscall_nest; /* Syscall nest level */ - char name[CONFIG_TASK_NAME_SIZE + 1]; /* Task name (with NULL terminator) */ }; struct noteram_dump_context_s @@ -768,35 +767,6 @@ static void noteram_dump_fini_context(FAR struct noteram_dump_context_s *ctx) } } -/**************************************************************************** - * Name: copy_task_name - ****************************************************************************/ - -#if CONFIG_TASK_NAME_SIZE > 0 -static void copy_task_name(FAR char *dst, FAR const char *src) -{ - char c; - int i; - - /* Replace space to underline - * Text trace data format cannot use a space as a task name. - */ - - for (i = 0; i < CONFIG_TASK_NAME_SIZE; i++) - { - c = *src++; - if (c == '\0') - { - break; - } - - *dst++ = (c == ' ') ? '_' : c; - } - - *dst = '\0'; -} -#endif - /**************************************************************************** * Name: get_task_context ****************************************************************************/ @@ -825,19 +795,6 @@ get_task_context(pid_t pid, FAR struct noteram_dump_context_s *ctx) (*tctxp)->next = NULL; (*tctxp)->pid = pid; (*tctxp)->syscall_nest = 0; - (*tctxp)->name[0] = '\0'; - -#ifdef CONFIG_DRIVERS_NOTE_TASKNAME_BUFSIZE - { - FAR const char *taskname; - - taskname = note_get_taskname(pid); - if (taskname != NULL) - { - copy_task_name((*tctxp)->name, taskname); - } - } -#endif } return *tctxp; @@ -847,15 +804,14 @@ get_task_context(pid_t pid, FAR struct noteram_dump_context_s *ctx) * Name: get_task_name ****************************************************************************/ -static const char *get_task_name(pid_t pid, - FAR struct noteram_dump_context_s *ctx) +static const char *get_task_name(pid_t pid) { - FAR struct noteram_dump_task_context_s *tctx; + FAR const char *taskname; - tctx = get_task_context(pid, ctx); - if (tctx != NULL && tctx->name[0] != '\0') + taskname = note_get_taskname(pid); + if (taskname != NULL) { - return tctx->name; + return taskname; } return ""; @@ -885,7 +841,7 @@ static int noteram_dump_header(FAR char *offset, noteram_dump_unflatten(&pid, note->nc_pid, sizeof(pid)); ret = sprintf(offset, "%8s-%-3u [%d] %3" PRIu32 ".%09" PRIu32 ": ", - get_task_name(pid, ctx), get_pid(pid), cpu, sec, nsec); + get_task_name(pid), get_pid(pid), cpu, sec, nsec); return ret; } @@ -922,9 +878,9 @@ static int noteram_dump_sched_switch(FAR char *offset, "sched_switch: " "prev_comm=%s prev_pid=%u prev_prio=%u prev_state=%c ==> " "next_comm=%s next_pid=%u next_prio=%u\n", - get_task_name(current_pid, ctx), get_pid(current_pid), + get_task_name(current_pid), get_pid(current_pid), current_priority, get_task_state(cctx->current_state), - get_task_name(next_pid, ctx), get_pid(next_pid), + get_task_name(next_pid), get_pid(next_pid), next_priority); cctx->current_pid = cctx->next_pid; @@ -966,21 +922,10 @@ static int noteram_dump_one(FAR uint8_t *p, { case NOTE_START: { -#if CONFIG_TASK_NAME_SIZE > 0 - FAR struct note_start_s *nst = (FAR struct note_start_s *)p; - FAR struct noteram_dump_task_context_s *tctx; - - tctx = get_task_context(pid, ctx); - if (tctx != NULL) - { - copy_task_name(tctx->name, nst->nst_name); - } -#endif - offset += noteram_dump_header(offset, note, ctx); offset += sprintf(offset, "sched_wakeup_new: comm=%s pid=%d target_cpu=%d\n", - get_task_name(pid, ctx), get_pid(pid), cpu); + get_task_name(pid), get_pid(pid), cpu); } break; @@ -1034,7 +979,7 @@ static int noteram_dump_one(FAR uint8_t *p, offset += noteram_dump_header(offset, note, ctx); offset += sprintf(offset, "sched_waking: comm=%s pid=%d target_cpu=%d\n", - get_task_name(cctx->next_pid, ctx), + get_task_name(cctx->next_pid), get_pid(cctx->next_pid), cpu); cctx->pendingswitch = true; } From a1f2a118a54045101ef746908ba4f8921eeace17 Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Fri, 11 Aug 2023 10:31:04 +0800 Subject: [PATCH 6/7] noteram: remove task_context syscall cannot be called in syscall, if this happens, it should be fixed (interruption is similar) Signed-off-by: yinshengkai --- drivers/note/noteram_driver.c | 113 ---------------------------------- 1 file changed, 113 deletions(-) diff --git a/drivers/note/noteram_driver.c b/drivers/note/noteram_driver.c index 3fb8099f10271..6aead5bfe8726 100644 --- a/drivers/note/noteram_driver.c +++ b/drivers/note/noteram_driver.c @@ -95,19 +95,11 @@ struct noteram_dump_cpu_context_s uint8_t next_priority; /* Task Priority of the next line */ }; -struct noteram_dump_task_context_s -{ - FAR struct noteram_dump_task_context_s *next; - pid_t pid; /* Task PID */ - int syscall_nest; /* Syscall nest level */ -}; - struct noteram_dump_context_s { int buflen; /* The length of the dumped data */ char buffer[256]; /* Buffer to hold the line to be dumped */ struct noteram_dump_cpu_context_s cpu[NCPUS]; - FAR struct noteram_dump_task_context_s *task; }; /**************************************************************************** @@ -124,8 +116,6 @@ static void noteram_add(FAR struct note_driver_s *drv, static void noteram_dump_init_context(FAR struct noteram_dump_context_s *ctx); -static void -noteram_dump_fini_context(FAR struct noteram_dump_context_s *ctx); static int noteram_dump_one(FAR uint8_t *p, FAR struct noteram_dump_context_s *ctx); @@ -475,7 +465,6 @@ static int noteram_open(FAR struct file *filep) int noteram_close(FAR struct file *filep) { FAR struct noteram_dump_context_s *ctx = filep->f_priv; - noteram_dump_fini_context(ctx); kmm_free(ctx); return OK; } @@ -742,62 +731,6 @@ static void noteram_dump_init_context(FAR struct noteram_dump_context_s *ctx) ctx->cpu[cpu].current_priority = -1; ctx->cpu[cpu].next_priority = -1; } - - ctx->task = NULL; -} - -/**************************************************************************** - * Name: noteram_dump_fini_context - ****************************************************************************/ - -static void noteram_dump_fini_context(FAR struct noteram_dump_context_s *ctx) -{ - FAR struct noteram_dump_task_context_s *tctx; - FAR struct noteram_dump_task_context_s *ntctx; - - /* Finalize the trace dump context */ - - tctx = ctx->task; - ctx->task = NULL; - while (tctx != NULL) - { - ntctx = tctx->next; - free(tctx); - tctx = ntctx; - } -} - -/**************************************************************************** - * Name: get_task_context - ****************************************************************************/ - -FAR static struct noteram_dump_task_context_s * -get_task_context(pid_t pid, FAR struct noteram_dump_context_s *ctx) -{ - FAR struct noteram_dump_task_context_s **tctxp; - tctxp = &ctx->task; - while (*tctxp != NULL) - { - if ((*tctxp)->pid == pid) - { - return *tctxp; - } - - tctxp = &((*tctxp)->next); - } - - /* Create new trace dump task context */ - - *tctxp = (FAR struct noteram_dump_task_context_s *)malloc( - sizeof(struct noteram_dump_task_context_s)); - if (*tctxp != NULL) - { - (*tctxp)->next = NULL; - (*tctxp)->pid = pid; - (*tctxp)->syscall_nest = 0; - } - - return *tctxp; } /**************************************************************************** @@ -991,32 +924,10 @@ static int noteram_dump_one(FAR uint8_t *p, case NOTE_SYSCALL_ENTER: { FAR struct note_syscall_enter_s *nsc; - FAR struct noteram_dump_task_context_s *tctx; int i; int j; uintptr_t arg; - /* Exclude the case of syscall issued by an interrupt handler and - * nested syscalls to correct tracecompass display. - */ - - if (cctx->intr_nest > 0) - { - break; - } - - tctx = get_task_context(pid, ctx); - if (tctx == NULL) - { - break; - } - - tctx->syscall_nest++; - if (tctx->syscall_nest > 1) - { - break; - } - nsc = (FAR struct note_syscall_enter_s *)p; if (nsc->nsc_nr < CONFIG_SYS_RESERVED || nsc->nsc_nr >= SYS_maxsyscall) @@ -1048,32 +959,8 @@ static int noteram_dump_one(FAR uint8_t *p, case NOTE_SYSCALL_LEAVE: { FAR struct note_syscall_leave_s *nsc; - FAR struct noteram_dump_task_context_s *tctx; uintptr_t result; - /* Exclude the case of syscall issued by an interrupt handler and - * nested syscalls to correct tracecompass display. - */ - - if (cctx->intr_nest > 0) - { - break; - } - - tctx = get_task_context(pid, ctx); - if (tctx == NULL) - { - break; - } - - tctx->syscall_nest--; - if (tctx->syscall_nest > 0) - { - break; - } - - tctx->syscall_nest = 0; - nsc = (FAR struct note_syscall_leave_s *)p; if (nsc->nsc_nr < CONFIG_SYS_RESERVED || nsc->nsc_nr >= SYS_maxsyscall) From 0d99366334ca95976d68af742fe829cfa10495f6 Mon Sep 17 00:00:00 2001 From: yinshengkai Date: Fri, 11 Aug 2023 10:31:04 +0800 Subject: [PATCH 7/7] note: simplify noteram logic Signed-off-by: yinshengkai --- drivers/note/noteram_driver.c | 235 ++++++++++------------------------ 1 file changed, 68 insertions(+), 167 deletions(-) diff --git a/drivers/note/noteram_driver.c b/drivers/note/noteram_driver.c index 6aead5bfe8726..fe291e9cc7aa9 100644 --- a/drivers/note/noteram_driver.c +++ b/drivers/note/noteram_driver.c @@ -39,6 +39,7 @@ #include #include #include +#include #ifdef CONFIG_SCHED_INSTRUMENTATION_SYSCALL # ifdef CONFIG_LIB_SYSCALL @@ -97,8 +98,6 @@ struct noteram_dump_cpu_context_s struct noteram_dump_context_s { - int buflen; /* The length of the dumped data */ - char buffer[256]; /* Buffer to hold the line to be dumped */ struct noteram_dump_cpu_context_s cpu[NCPUS]; }; @@ -113,10 +112,9 @@ static ssize_t noteram_read(FAR struct file *filep, static int noteram_ioctl(struct file *filep, int cmd, unsigned long arg); static void noteram_add(FAR struct note_driver_s *drv, FAR const void *note, size_t len); - static void noteram_dump_init_context(FAR struct noteram_dump_context_s *ctx); -static int noteram_dump_one(FAR uint8_t *p, +static int noteram_dump_one(FAR uint8_t *p, FAR struct lib_outstream_s *s, FAR struct noteram_dump_context_s *ctx); /**************************************************************************** @@ -393,51 +391,6 @@ static ssize_t noteram_get(FAR struct noteram_driver_s *drv, return notelen; } -/**************************************************************************** - * Name: noteram_size - * - * Description: - * Return the size of the next note at the read index of the circular - * buffer. - * - * Input Parameters: - * None. - * - * Returned Value: - * Zero is returned if the circular buffer is empty. Otherwise, the size - * of the next note is returned. - * - ****************************************************************************/ - -static ssize_t noteram_size(FAR struct noteram_driver_s *drv) -{ - FAR struct note_common_s *note; - unsigned int read; - ssize_t notelen; - size_t circlen; - - /* Verify that the circular buffer is not empty */ - - circlen = noteram_unread_length(drv); - if (circlen <= 0) - { - return 0; - } - - /* Get the read index of the circular buffer */ - - read = drv->ni_read; - DEBUGASSERT(read < drv->ni_bufsize); - - /* Get the length of the note at the read index */ - - note = (FAR struct note_common_s *)&drv->ni_buffer[read]; - notelen = note->nc_length; - DEBUGASSERT(notelen <= circlen); - - return notelen; -} - /**************************************************************************** * Name: noteram_open ****************************************************************************/ @@ -476,35 +429,18 @@ int noteram_close(FAR struct file *filep) static ssize_t noteram_read(FAR struct file *filep, FAR char *buffer, size_t buflen) { - ssize_t ret = -EFBIG; - ssize_t retlen = 0; - uint8_t note[32]; - irqstate_t flags; FAR struct noteram_dump_context_s *ctx = filep->f_priv; - FAR struct noteram_driver_s *drv = - (FAR struct noteram_driver_s *)filep->f_inode->i_private; + FAR struct noteram_driver_s *drv = filep->f_inode->i_private; + FAR struct lib_memoutstream_s stream; + ssize_t ret; - /* If we have parsed but unread data last time, - * we should save the last data first - */ - - if (ctx->buflen > 0) - { - if (ctx->buflen > buflen) - { - goto errout; - } - - strlcpy(buffer, ctx->buffer, buflen); - retlen = ctx->buflen; - buffer += ctx->buflen; - buflen -= ctx->buflen; - } - - /* Then loop, adding as many notes as possible to the user buffer. */ + lib_memoutstream(&stream, buffer, buflen); do { + irqstate_t flags; + uint8_t note[64]; + /* Get the next note (removing it from the buffer) */ flags = spin_lock_irqsave_wo_note(&drv->lock); @@ -512,48 +448,17 @@ static ssize_t noteram_read(FAR struct file *filep, FAR char *buffer, spin_unlock_irqrestore_wo_note(&drv->lock, flags); if (ret <= 0) { - ctx->buflen = 0; - break; + return ret; } /* Parse notes into text format */ - ctx->buflen = noteram_dump_one(note, ctx); - - /* If the remaining space is insufficient, - * return the read data directly first - */ - - if (ctx->buflen > buflen) - { - ret = -EFBIG; - break; - } - - /* Update pointers from the note that was transferred */ - - strlcpy(buffer, ctx->buffer, buflen); - - retlen += ctx->buflen; - buffer += ctx->buflen; - buflen -= ctx->buflen; - ctx->buflen = 0; - - /* Will the next note fit? There is a race here and even if the next - * note will fit, it may fail still when noteram_get() is called. - * - * It won't fit (or an error occurred). Return what we have without - * trying to get the next note (which would cause it to be deleted). - */ - - ret = noteram_size(drv); + ret = noteram_dump_one(note, (FAR struct lib_outstream_s *)&stream, + ctx); } - while (ret > 0); - - /* If no data is read, an error code is returned */ + while (ret == 0); -errout: - return retlen ? retlen : ret; + return ret; } /**************************************************************************** @@ -754,7 +659,7 @@ static const char *get_task_name(pid_t pid) * Name: noteram_dump_header ****************************************************************************/ -static int noteram_dump_header(FAR char *offset, +static int noteram_dump_header(FAR struct lib_outstream_s *s, FAR struct note_common_s *note, FAR struct noteram_dump_context_s *ctx) { @@ -773,8 +678,8 @@ static int noteram_dump_header(FAR char *offset, noteram_dump_unflatten(&pid, note->nc_pid, sizeof(pid)); - ret = sprintf(offset, "%8s-%-3u [%d] %3" PRIu32 ".%09" PRIu32 ": ", - get_task_name(pid), get_pid(pid), cpu, sec, nsec); + ret = lib_sprintf(s, "%8s-%-3u [%d] %3" PRIu32 ".%09" PRIu32 ": ", + get_task_name(pid), get_pid(pid), cpu, sec, nsec); return ret; } @@ -784,7 +689,7 @@ static int noteram_dump_header(FAR char *offset, * Name: noteram_dump_sched_switch ****************************************************************************/ -static int noteram_dump_sched_switch(FAR char *offset, +static int noteram_dump_sched_switch(FAR struct lib_outstream_s *s, FAR struct note_common_s *note, FAR struct noteram_dump_context_s *ctx) { @@ -807,14 +712,13 @@ static int noteram_dump_sched_switch(FAR char *offset, current_priority = cctx->current_priority; next_priority = cctx->next_priority; - ret = sprintf(offset, - "sched_switch: " - "prev_comm=%s prev_pid=%u prev_prio=%u prev_state=%c ==> " - "next_comm=%s next_pid=%u next_prio=%u\n", - get_task_name(current_pid), get_pid(current_pid), - current_priority, get_task_state(cctx->current_state), - get_task_name(next_pid), get_pid(next_pid), - next_priority); + ret = lib_sprintf(s, "sched_switch: prev_comm=%s prev_pid=%u " + "prev_prio=%u prev_state=%c ==> " + "next_comm=%s next_pid=%u next_prio=%u\n", + get_task_name(current_pid), get_pid(current_pid), + current_priority, get_task_state(cctx->current_state), + get_task_name(next_pid), get_pid(next_pid), + next_priority); cctx->current_pid = cctx->next_pid; cctx->current_priority = cctx->next_priority; @@ -827,13 +731,12 @@ static int noteram_dump_sched_switch(FAR char *offset, * Name: noteram_dump_one ****************************************************************************/ -static int noteram_dump_one(FAR uint8_t *p, +static int noteram_dump_one(FAR uint8_t *p, FAR struct lib_outstream_s *s, FAR struct noteram_dump_context_s *ctx) { FAR struct note_common_s *note = (FAR struct note_common_s *)p; FAR struct noteram_dump_cpu_context_s *cctx; - FAR char *buffer = (FAR char *)ctx->buffer; - FAR char *offset = (FAR char *)ctx->buffer; + int ret = 0; pid_t pid; #ifdef CONFIG_SMP int cpu = note->nc_cpu; @@ -855,10 +758,10 @@ static int noteram_dump_one(FAR uint8_t *p, { case NOTE_START: { - offset += noteram_dump_header(offset, note, ctx); - offset += sprintf(offset, - "sched_wakeup_new: comm=%s pid=%d target_cpu=%d\n", - get_task_name(pid), get_pid(pid), cpu); + ret += noteram_dump_header(s, note, ctx); + ret += lib_sprintf(s, "sched_wakeup_new: comm=%s pid=%d " + "target_cpu=%d\n", + get_task_name(pid), get_pid(pid), cpu); } break; @@ -900,8 +803,8 @@ static int noteram_dump_one(FAR uint8_t *p, * executed immediately. */ - offset += noteram_dump_header(offset, note, ctx); - offset += noteram_dump_sched_switch(offset, note, ctx); + ret += noteram_dump_header(s, note, ctx); + ret += noteram_dump_sched_switch(s, note, ctx); } else { @@ -909,11 +812,11 @@ static int noteram_dump_one(FAR uint8_t *p, * until leaving the interrupt handler. */ - offset += noteram_dump_header(offset, note, ctx); - offset += sprintf(offset, - "sched_waking: comm=%s pid=%d target_cpu=%d\n", - get_task_name(cctx->next_pid), - get_pid(cctx->next_pid), cpu); + ret += noteram_dump_header(s, note, ctx); + ret += lib_sprintf(s, "sched_waking: comm=%s " + "pid=%d target_cpu=%d\n", + get_task_name(cctx->next_pid), + get_pid(cctx->next_pid), cpu); cctx->pendingswitch = true; } } @@ -935,24 +838,24 @@ static int noteram_dump_one(FAR uint8_t *p, break; } - offset += noteram_dump_header(offset, note, ctx); - offset += sprintf(offset, "sys_%s(", - g_funcnames[nsc->nsc_nr - CONFIG_SYS_RESERVED]); + ret += noteram_dump_header(s, note, ctx); + ret += lib_sprintf(s, "sys_%s(", + g_funcnames[nsc->nsc_nr - CONFIG_SYS_RESERVED]); for (i = j = 0; i < nsc->nsc_argc; i++) { noteram_dump_unflatten(&arg, nsc->nsc_args, sizeof(arg)); if (i == 0) { - offset += sprintf(offset, "arg%d: 0x%" PRIxPTR, i, arg); + ret += lib_sprintf(s, "arg%d: 0x%" PRIxPTR, i, arg); } else { - offset += sprintf(offset, ", arg%d: 0x%" PRIxPTR, i, arg); + ret += lib_sprintf(s, ", arg%d: 0x%" PRIxPTR, i, arg); } } - offset += sprintf(offset, ")\n"); + ret += lib_sprintf(s, ")\n"); } break; @@ -968,9 +871,9 @@ static int noteram_dump_one(FAR uint8_t *p, break; } - offset += noteram_dump_header(offset, note, ctx); + ret += noteram_dump_header(s, note, ctx); noteram_dump_unflatten(&result, nsc->nsc_result, sizeof(result)); - offset += sprintf(offset, "sys_%s -> 0x%" PRIxPTR "\n", + ret += lib_sprintf(s, "sys_%s -> 0x%" PRIxPTR "\n", g_funcnames[nsc->nsc_nr - CONFIG_SYS_RESERVED], result); } @@ -983,8 +886,8 @@ static int noteram_dump_one(FAR uint8_t *p, FAR struct note_irqhandler_s *nih; nih = (FAR struct note_irqhandler_s *)p; - offset += noteram_dump_header(offset, note, ctx); - offset += sprintf(offset, "irq_handler_entry: irq=%u name=%d\n", + ret += noteram_dump_header(s, note, ctx); + ret += lib_sprintf(s, "irq_handler_entry: irq=%u name=%d\n", nih->nih_irq, nih->nih_irq); cctx->intr_nest++; } @@ -995,9 +898,9 @@ static int noteram_dump_one(FAR uint8_t *p, FAR struct note_irqhandler_s *nih; nih = (FAR struct note_irqhandler_s *)p; - offset += noteram_dump_header(offset, note, ctx); - offset += sprintf(offset, "irq_handler_exit: irq=%u ret=handled\n", - nih->nih_irq); + ret += noteram_dump_header(s, note, ctx); + ret += lib_sprintf(s, "irq_handler_exit: irq=%u ret=handled\n", + nih->nih_irq); cctx->intr_nest--; if (cctx->intr_nest <= 0) @@ -1007,8 +910,8 @@ static int noteram_dump_one(FAR uint8_t *p, { /* If the pending task switch exists, it is executed here */ - offset += noteram_dump_header(offset, note, ctx); - offset += noteram_dump_sched_switch(offset, note, ctx); + ret += noteram_dump_header(s, note, ctx); + ret += noteram_dump_sched_switch(s, note, ctx); } } } @@ -1021,10 +924,8 @@ static int noteram_dump_one(FAR uint8_t *p, { struct note_csection_s *ncs; ncs = (FAR struct note_csection_s *)p; - offset += noteram_dump_header(offset, &ncs->ncs_cmn, ctx); - offset += sprintf(offset, - "tracing_mark_write: %c|%d|" - "critical_section\n", + ret += noteram_dump_header(s, &ncs->ncs_cmn, ctx); + ret += lib_sprintf(s, "tracing_mark_write: %c|%d|critical_section\n", note->nc_type == NOTE_CSECTION_ENTER ? 'B' : 'E', pid); } @@ -1039,8 +940,8 @@ static int noteram_dump_one(FAR uint8_t *p, int16_t count; npr = (FAR struct note_preempt_s *)p; noteram_dump_unflatten(&count, npr->npr_count, sizeof(count)); - offset += noteram_dump_header(offset, &npr->npr_cmn, ctx); - offset += sprintf(offset, "tracing_mark_write: " + ret += noteram_dump_header(s, &npr->npr_cmn, ctx); + ret += lib_sprintf(s, "tracing_mark_write: " "%c|%d|sched_lock:%d\n", note->nc_type == NOTE_PREEMPT_LOCK ? 'B' : 'E', pid, count); @@ -1055,19 +956,19 @@ static int noteram_dump_one(FAR uint8_t *p, uintptr_t ip; nst = (FAR struct note_string_s *)p; - offset += noteram_dump_header(offset, note, ctx); + ret += noteram_dump_header(s, note, ctx); noteram_dump_unflatten(&ip, nst->nst_ip, sizeof(ip)); if (nst->nst_data[1] == '\0' && (nst->nst_data[0] == 'B' || nst->nst_data[0] == 'E')) { - offset += sprintf(offset, "tracing_mark_write: %c|%d|%pS\n", - nst->nst_data[0], pid, (FAR void *)ip); + ret += lib_sprintf(s, "tracing_mark_write: %c|%d|%pS\n", + nst->nst_data[0], pid, (FAR void *)ip); } else { - offset += sprintf(offset, "tracing_mark_write: %s\n", - nst->nst_data); + ret += lib_sprintf(s, "tracing_mark_write: %s\n", + nst->nst_data); } } break; @@ -1080,19 +981,19 @@ static int noteram_dump_one(FAR uint8_t *p, int i; nbi = (FAR struct note_binary_s *)p; - offset += noteram_dump_header(offset, note, ctx); + ret += noteram_dump_header(s, note, ctx); count = note->nc_length - sizeof(struct note_binary_s) + 1; noteram_dump_unflatten(&ip, nbi->nbi_ip, sizeof(ip)); - offset += sprintf(offset, "0x%" PRIdPTR ": event=%u count=%u", ip, - nbi->nbi_event, count); + ret += lib_sprintf(s, "0x%" PRIdPTR ": event=%u count=%u", ip, + nbi->nbi_event, count); for (i = 0; i < count; i++) { - offset += sprintf(offset, " 0x%x", nbi->nbi_data[i]); + ret += lib_sprintf(s, " 0x%x", nbi->nbi_data[i]); } - offset += sprintf(offset, "\n"); + ret += lib_sprintf(s, "\n"); } break; #endif @@ -1103,7 +1004,7 @@ static int noteram_dump_one(FAR uint8_t *p, /* Return the length of the processed note */ - return offset - buffer; + return ret; } /****************************************************************************