sched/: Add option to buffer scheduler instrumentation data in memory.

This commit is contained in:
Gregory Nutt 2016-03-17 09:49:43 -06:00
parent 1951b9df57
commit 7f19631338
16 changed files with 789 additions and 46 deletions

View File

@ -11562,4 +11562,7 @@
* sched/tls and include/nuttx/tls.h: Basic definitions needed to support
thread local storage (TLS). Not used anywhere yet (and may not be used
in the near future either) (2016-03-10).
* sched/sched_note.c and include/nuttx/sched_note.c: Add a configuration
option to buffer RTOS instrumentation data in an in-memory buffer
(2016-03-17).

View File

@ -843,48 +843,6 @@ void sched_suspend_scheduler(FAR struct tcb_s *tcb);
# define sched_suspend_scheduler(tcb)
#endif
/********************************************************************************
* Name: sched_note_*
*
* Description:
* If instrumentation of the scheduler is enabled, then some outboard logic
* must provide the following interfaces. These interfaces are not availalble
* to application code.
*
* Input Parameters:
* tcb - The TCB of the thread.
*
* Returned Value:
* None
*
********************************************************************************/
#ifdef CONFIG_SCHED_INSTRUMENTATION
void sched_note_start(FAR struct tcb_s *tcb);
void sched_note_stop(FAR struct tcb_s *tcb);
void sched_note_switch(FAR struct tcb_s *fromtcb, FAR struct tcb_s *totcb);
#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION
void sched_note_premption(FAR struct tcb_s *tcb, bool locked);
#else
# define sched_note_premption(t,l)
#endif
#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION
void sched_note_csection(FAR struct tcb_s *tcb, bool enter);
#else
# define sched_note_csection(t,e)
#endif
#else
# define sched_note_start(t)
# define sched_note_stop(t)
# define sched_note_switch(t1, t2)
# define sched_note_premption(t,l)
# define sched_note_csection(t,e)
#endif /* CONFIG_SCHED_INSTRUMENTATION */
#undef EXTERN
#if defined(__cplusplus)
}

219
include/nuttx/sched_note.h Normal file
View File

@ -0,0 +1,219 @@
/****************************************************************************
* include/nuttx/sched_note.h
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#ifndef __INCLUDE_NUTTX_SCHED_NOTE_H
#define __INCLUDE_NUTTX_SCHED_NOTE_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <nuttx/sched.h>
#ifdef CONFIG_SCHED_INSTRUMENTATION
/****************************************************************************
* Public Types
****************************************************************************/
#ifdef CONFIG_SCHED_INSTRUMENTATION_BUFFER
/* This type identifies a note structure */
enum note_type_e
{
NOTE_START = 0,
NOTE_STOP,
NOTE_SWITCH
#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION
,
NOTE_PREEMPT_LOCK,
NOTE_PREEMPT_UNLOCK
#endif
#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION
,
NOTE_CSECTION_ENTER,
NOTE_CSECTION_LEAVE
#endif
};
/* This structure provides the common header of each note */
struct note_common_s
{
uint8_t nc_length; /* Length of the note */
uint8_t nc_type; /* See enum note_type_e */
uint8_t nc_systime[4]; /* Time when note buffered */
};
/* This is the specific form of the NOTE_START note */
struct note_start_s
{
uint8_t nst_length; /* Length of the note */
uint8_t nst_type; /* Must be NOTE_START */
uint8_t nst_systime[4]; /* Time when note buffered */
uint8_t nst_pid[2]; /* ID of the new thread/task */
#if CONFIG_TASK_NAME_SIZE > 0
char nst_name[1]; /* Start of the name of the thread/task */
#endif
};
/* This is the specific form of the NOTE_STOP note */
struct note_stop_s
{
uint8_t nsp_length; /* Length of the note */
uint8_t nsp_type; /* Must be NOTE_STOP */
uint8_t nsp_systime[4]; /* Time when note buffered */
uint8_t nsp_pid[2]; /* ID of the thread/task that stopped */
};
/* This is the specific form of the NOTE_SWITCH note */
struct note_switch_s
{
uint8_t nsw_length; /* Length of the note */
uint8_t nsw_type; /* Must be NOTE_SWITCH */
uint8_t nsw_systime[4]; /* Time when note buffered */
uint8_t nsw_pidout[2]; /* ID of the thread/task that was blocked */
uint8_t nsw_pidin[2]; /* ID of the thread/task that was started */
};
#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION
/* This is the specific form of the NOTE_PREEMPT_LOCK/UNLOCK note */
struct note_preempt_s
{
uint8_t npr_length; /* Length of the note */
uint8_t npr_type; /* Must be NOTE_PREEMPT_LOCK or _UNLOCK */
uint8_t npr_systime[4]; /* Time when note buffered */
uint8_t npr_pid[2]; /* ID of the thread/task that change pre-emption */
uint8_t npr_count[2]; /* Count of nested locks */
};
#endif /* CONFIG_SCHED_INSTRUMENTATION_PREEMPTION */
#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION
/* This is the specific form of the NOTE_CSECTION_ENTER/LEAVE note */
struct note_csection_s
{
uint8_t ncs_length; /* Length of the note */
uint8_t ncs_type; /* Must be NOTE_CSECTION_ENTER or _LEAVE */
uint8_t ncs_systime[4]; /* Time when note buffered */
uint8_t ncs_pid[2]; /* ID of the thread/task that changed critical section */
#ifdef CONFIG_SMP
uint8_t ncs_count[2]; /* Count of nested csections */
#endif
};
#endif /* CONFIG_SCHED_INSTRUMENTATION_CSECTION */
#endif /* CONFIG_SCHED_INSTRUMENTATION_BUFFER */
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/********************************************************************************
* Name: sched_note_*
*
* Description:
* If instrumentation of the scheduler is enabled, then some outboard logic
* must provide the following interfaces. These interfaces are not availalble
* to application code.
*
* NOTE: if CONFIG_SCHED_INSTRUMENTATION_BUFFER, then these interfaces are
* *not* available to the platform-specific logic. Rather, they provided by
* the note buffering logic. See sched_note_get() below.
*
* Input Parameters:
* tcb - The TCB of the thread.
*
* Returned Value:
* None
*
********************************************************************************/
void sched_note_start(FAR struct tcb_s *tcb);
void sched_note_stop(FAR struct tcb_s *tcb);
void sched_note_switch(FAR struct tcb_s *fromtcb, FAR struct tcb_s *totcb);
#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION
void sched_note_premption(FAR struct tcb_s *tcb, bool locked);
#endif
#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION
void sched_note_csection(FAR struct tcb_s *tcb, bool enter);
#endif
/****************************************************************************
* Name: sched_note_get
*
* Description:
* Remove the next note from the tail of the circular buffer. The note
* is also removed from the circular buffer to make room for futher notes.
*
* Input Parameters:
* buffer - Location to return the next note
* buflen - The length of the user provided buffer.
*
* Returned Value:
* None
*
* Assumptions:
* On success, the length of the return note is provided. A negated
* errno value is returned on failure.
*
****************************************************************************/
#ifdef CONFIG_SCHED_INSTRUMENTATION_BUFFER
ssize_t sched_note_get(FAR uint8_t *buffer, size_t buflen);
#endif
#else /* CONFIG_SCHED_INSTRUMENTATION */
# define sched_note_start(t)
# define sched_note_stop(t)
# define sched_note_switch(t1, t2)
# define sched_note_premption(t,l)
# define sched_note_csection(t,e)
#endif /* CONFIG_SCHED_INSTRUMENTATION */
#endif /* __INCLUDE_NUTTX_SCHED_NOTE_H */

View File

@ -370,10 +370,10 @@ config SPORADIC_INSTRUMENTATION
scheduler behavior. If enabled, then the board-specific logic must
provide the following functions:
void arch_sporadic_start(FAR struct tcb_s *tcb);
void arch_sporadic_lowpriority(FAR struct tcb_s *tcb);
void arch_sporadic_suspend(FAR struct tcb_s *tcb);
void arch_sporadic_resume(FAR struct tcb_s *tcb);
void arch_sporadic_start(FAR struct tcb_s *tcb);
void arch_sporadic_lowpriority(FAR struct tcb_s *tcb);
void arch_sporadic_suspend(FAR struct tcb_s *tcb);
void arch_sporadic_resume(FAR struct tcb_s *tcb);
endif # SCHED_SPORADIC
@ -605,7 +605,15 @@ config SCHED_INSTRUMENTATION
void sched_note_stop(FAR struct tcb_s *tcb);
void sched_note_switch(FAR struct tcb_s *pFromTcb, FAR struct tcb_s *pToTcb);
NOTE: These are internal OS interfaces and are called at at very
critical locations in the OS. There is very little that can be
done in these interfaces. For example, normal devices may not be
used; syslog output cannot be performed.
An option is to use SCHED_INSTRUMENTATION_BUFFER below.
if SCHED_INSTRUMENTATION
config SCHED_INSTRUMENTATION_PREEMPTION
bool "Preemption monitor hooks"
default n
@ -626,6 +634,38 @@ config SCHED_INSTRUMENTATION_CSECTION
void sched_note_csection(FAR struct tcb_s *tcb, bool state);
config SCHED_INSTRUMENTATION_BUFFER
bool "Buffer instrumentation data in memory"
default n
---help---
If this option is selected, then in-memory buffering logic is
enabled to capature scheduler instrumentation data. This has
the advantage that (1) the platform logic does not have to provide
the sched_note_* interaces described for the previous settings.
Instead, the buffering logic catches all of these. It encodes
timestamps the scheduler note and adds the note to an in-memory,
circular buffer. And (2) buffering the scheduler instrumentation
data (versus performing some output operation) minimizes the impact
of the instrumentation on the behavior of the system.
If the in-memory buffer becomes full, then older notes are
overwritten by newer notes. The following interface is provided:
ssize_t sched_note_get(FAR uint8_t *buffer, size_t buflen);
Platform specific information must call this function and dispose
of it quickly so that overwriting of the tail of the circular buffer
does not occur. See include/nuttx/sched_note.h for additional
information.
config SCHED_NOTE_BUFSIZE
int "Instrumentation buffer size"
default 2048
depends on SCHED_INSTRUMENTATION_BUFFER
---help---
The size of the in-memory, circular instrumentation buffer (in
bytes).
endif # SCHED_INSTRUMENTATION
endmenu # Performance Monitoring

View File

@ -96,10 +96,20 @@ static const char g_idlename[] = "CPUn Idle"
void os_idle_trampoline(void)
{
#ifdef CONFIG_SCHED_INSTRUMENTATION
FAR struct tcb_s *tcb = this_task();
#endif
/* Perform architecture-specific initialization for this CPU */
up_cpu_initialize();
#ifdef CONFIG_SCHED_INSTRUMENTATION
/* Announce that the IDLE task has started */
sched_note_start(tcb);
#endif
/* Then transfer control to the IDLE task */
(void)os_idle_task(0, NULL);

View File

@ -53,6 +53,7 @@
#include <nuttx/mm/mm.h>
#include <nuttx/mm/shm.h>
#include <nuttx/kmalloc.h>
#include <nuttx/sched_note.h>
#include <nuttx/init.h>
#include "sched/sched.h"
@ -708,8 +709,13 @@ void os_start(void)
lib_initialize();
/* IDLE Group Initialization **********************************************/
/* Announce that the CPU0 IDLE task has started */
sched_note_start(&g_idletcb[0].cmn);
#ifdef CONFIG_SMP
/* Initialize the IDLE group for the IDLE task of each CPU */
for (cpu = 0; cpu < CONFIG_SMP_NCPUS; cpu++)
#endif
{

View File

@ -42,6 +42,7 @@
#include <sys/types.h>
#include <nuttx/spinlock.h>
#include <nuttx/sched_note.h>
#include <arch/irq.h>
#include "sched/sched.h"

View File

@ -82,6 +82,10 @@ else
CSRCS += sched_processtimer.c
endif
ifeq ($(CONFIG_SCHED_INSTRUMENTATION_BUFFER),y)
CSRCS += sched_note.c
endif
# Include sched build support
DEPPATH += --dep-path sched

View File

@ -43,6 +43,8 @@
#include <queue.h>
#include <assert.h>
#include <nuttx/sched_note.h>
#include "irq/irq.h"
#include "sched/sched.h"

View File

@ -44,6 +44,8 @@
#include <assert.h>
#include <nuttx/arch.h>
#include <nuttx/sched_note.h>
#include "sched/sched.h"
/****************************************************************************

View File

@ -44,6 +44,8 @@
#include <queue.h>
#include <assert.h>
#include <nuttx/sched_note.h>
#include "sched/sched.h"
/****************************************************************************

491
sched/sched/sched_note.c Normal file
View File

@ -0,0 +1,491 @@
/****************************************************************************
* sched/sched/sched_note.c
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name NuttX nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdint.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <nuttx/sched.h>
#include <nuttx/clock.h>
#include <nuttx/sched_note.h>
#ifdef CONFIG_SCHED_INSTRUMENTATION_BUFFER
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Types
****************************************************************************/
struct note_info_s
{
unsigned int ni_head;
unsigned int ni_tail;
uint8_t ni_buffer[CONFIG_SCHED_NOTE_BUFSIZE];
};
struct note_startalloc_s
{
uint8_t nsa_length;
uint8_t nsa_type;
uint8_t nsa_systime[4];
uint8_t nsa_pid[2];
#if CONFIG_TASK_NAME_SIZE > 0
char nsa_name[CONFIG_TASK_NAME_SIZE + 1];
#endif
};
#if CONFIG_TASK_NAME_SIZE > 0
# define SIZEOF_NOTE_START(n) (sizeof(struct note_start_s) + (n) - 1)
#else
# define SIZEOF_NOTE_START(n) (sizeof(struct note_start_s))
#endif
/****************************************************************************
* Private Data
****************************************************************************/
static struct note_info_s g_note_info;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: note_next
*
* Description:
* Return the circular buffer index at offset from the specified index
* value, handling wraparound
*
* Input Parameters:
* ndx - Old circular buffer index
*
* Returned Value:
* New circular buffer index
*
****************************************************************************/
static inline unsigned int note_next(unsigned int ndx, unsigned int offset)
{
ndx += offset;
if (ndx >= CONFIG_SCHED_NOTE_BUFSIZE)
{
ndx -= CONFIG_SCHED_NOTE_BUFSIZE;
}
return ndx;
}
/****************************************************************************
* Name: note_systime
*
* Description:
* Save the current system time in the note structure as a 32-bit value.
*
* Input Parameters:
* note - The note structure to use
*
* Returned Value:
* None
*
****************************************************************************/
static void note_systime(FAR struct note_common_s *note)
{
uint32_t systime = (uint32_t)clock_systimer();
/* Save the LS 32-bits of the system timer in little endian order */
note->nc_systime[0] = (uint8_t)( systime & 0xff);
note->nc_systime[1] = (uint8_t)((systime >> 8) & 0xff);
note->nc_systime[2] = (uint8_t)((systime >> 16) & 0xff);
note->nc_systime[3] = (uint8_t)((systime >> 24) & 0xff);
}
/****************************************************************************
* Name: note_length
*
* Description:
* Length of data currently in circular buffer.
*
* Input Parameters:
* None
*
* Returned Value:
* Length of data currently in circular buffer.
*
****************************************************************************/
#ifdef CONFIG_DEBUG
static unsigned int note_length(void)
{
unsigned int head = g_note_info.ni_head;
unsigned int tail = g_note_info.ni_tail;
if (tail > head)
{
head += CONFIG_SCHED_NOTE_BUFSIZE;
}
return head - tail;
}
#endif
/****************************************************************************
* Name: note_remove
*
* Description:
* Remove the variable length note from the tail of the circular buffer
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions:
* We are within a critical section.
*
****************************************************************************/
static void note_remove(void)
{
FAR struct note_common_s *note;
unsigned int tail;
unsigned int length;
/* Get the tail index of the circular buffer */
tail = g_note_info.ni_tail;
DEBUGASSERT(tail < CONFIG_SCHED_NOTE_BUFSIZE);
/* Get the length of the note at the tail index */
note = (FAR struct note_common_s *)&g_note_info.ni_buffer[tail];
length = note->nc_length;
DEBUGASSERT(length <= note_length());
/* Increment the tail index to remove the entire note from the circular
* buffer.
*/
g_note_info.ni_tail = note_next(tail, length);
}
/****************************************************************************
* Name: note_add
*
* Description:
* Add the variable length note to the head of the circular buffer
*
* Input Parameters:
* None
*
* Returned Value:
* None
*
* Assumptions:
* We are within a critical section.
*
****************************************************************************/
static void note_add(FAR const uint8_t *note, uint8_t notelen)
{
unsigned int head;
unsigned int next;
/* Get the index to the head of the circular buffer */
DEBUGASSERT(note != NULL && notelen < CONFIG_SCHED_NOTE_BUFSIZE);
head = g_note_info.ni_head;
/* Loop until all bytes have been transferred to the circular buffer */
while (notelen > 0)
{
/* Get the next head index. Would it collide with the current tail
* index?
*/
next = note_next(head, 1);
if (next == g_note_info.ni_tail)
{
/* Yes, then remove the note at the tail index */
note_remove();
}
/* Save the next byte at the head index */
g_note_info.ni_buffer[head] = *note++;
head = next;
notelen--;
}
g_note_info.ni_head = head;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: sched_note_*
*
* Description:
* These are the hooks into the scheduling instrumentation logic. Each
* simply formats the note associated with the schedule event and adds
* that note to the circular buffer.
*
* Input Parameters:
* tcb - The TCB of the thread.
*
* Returned Value:
* None
*
* Assumptions:
* We are within a critical section.
*
****************************************************************************/
void sched_note_start(FAR struct tcb_s *tcb)
{
struct note_startalloc_s note;
unsigned int length;
#if CONFIG_TASK_NAME_SIZE > 0
int namelen;
#endif
/* Copy the task name (if possible) and get the length of the note */
#if CONFIG_TASK_NAME_SIZE > 0
namelen = strlen(tcb->name);
DEBUGASSERT(namelen <= CONFIG_TASK_NAME_SIZE);
strncpy(note.nsa_name, tcb->name, CONFIG_TASK_NAME_SIZE + 1);
length = SIZEOF_NOTE_START(namelen + 1);
#else
length = SIZEOF_NOTE_START(0)
#endif
/* Finish formatting the note */
note.nsa_length = length;
note.nsa_type = NOTE_START;
note.nsa_pid[0] = (uint8_t)(tcb->pid & 0xff);
note.nsa_pid[1] = (uint8_t)((tcb->pid >> 8) & 0xff);
note_systime((FAR struct note_common_s *)&note);
/* Add the note to circular buffer */
note_add((FAR const uint8_t *)&note, length);
}
void sched_note_stop(FAR struct tcb_s *tcb)
{
struct note_stop_s note;
/* Format the note */
note.nsp_length = sizeof(struct note_stop_s);
note.nsp_type = NOTE_STOP;
note.nsp_pid[0] = (uint8_t)(tcb->pid & 0xff);
note.nsp_pid[1] = (uint8_t)((tcb->pid >> 8) & 0xff);
note_systime((FAR struct note_common_s *)&note);
/* Add the note to circular buffer */
note_add((FAR const uint8_t *)&note, sizeof(struct note_stop_s));
}
void sched_note_switch(FAR struct tcb_s *fromtcb, FAR struct tcb_s *totcb)
{
struct note_switch_s note;
/* Format the note */
note.nsw_length = sizeof(struct note_switch_s);
note.nsw_type = NOTE_SWITCH;
note.nsw_pidout[0] = (uint8_t)(fromtcb->pid & 0xff);
note.nsw_pidout[1] = (uint8_t)((fromtcb->pid >> 8) & 0xff);
note.nsw_pidin[0] = (uint8_t)(totcb->pid & 0xff);
note.nsw_pidin[1] = (uint8_t)((totcb->pid >> 8) & 0xff);
note_systime((FAR struct note_common_s *)&note);
/* Add the note to circular buffer */
note_add((FAR const uint8_t *)&note, sizeof(struct note_switch_s));
}
#ifdef CONFIG_SCHED_INSTRUMENTATION_PREEMPTION
void sched_note_premption(FAR struct tcb_s *tcb, bool locked)
{
struct note_preempt_s note;
/* Format the note */
note.npr_length = sizeof(struct note_preempt_s);
note.npr_type = locked ? NOTE_PREEMPT_LOCK : NOTE_PREEMPT_UNLOCK;
note.npr_pid[0] = (uint8_t)(tcb->pid & 0xff);
note.npr_pid[1] = (uint8_t)((tcb->pid >> 8) & 0xff);
note.npr_count[0] = (uint8_t)(tcb->lockcount & 0xff);
note.npr_count[1] = (uint8_t)((tcb->lockcount >> 8) & 0xff);
note_systime((FAR struct note_common_s *)&note);
/* Add the note to circular buffer */
note_add((FAR const uint8_t *)&note, sizeof(struct note_preempt_s));
}
#endif
#ifdef CONFIG_SCHED_INSTRUMENTATION_CSECTION
void sched_note_csection(FAR struct tcb_s *tcb, bool enter)
{
struct note_preempt_s note;
/* Format the note */
note.ncs_length = sizeof(struct note_preempt_s);
note.ncs_type = enter ? NOTE_CSECTION_ENTER : NOTE_CSECTION_LEAVE;
note.ncs_pid[0] = (uint8_t)(tcb->pid & 0xff);
note.ncs_pid[1] = (uint8_t)((tcb->pid >> 8) & 0xff);
#ifdef CONFIG_SMP
note.ncs_count[0] = (uint8_t)(tcb->irqcount & 0xff);
note.ncs_count[1] = (uint8_t)((tcb->irqcount >> 8) & 0xff);
#endif
note_systime((FAR struct note_common_s *)&note);
/* Add the note to circular buffer */
note_add((FAR const uint8_t *)&note, sizeof(struct note_preempt_s));
}
#endif
/****************************************************************************
* Name: sched_note_get
*
* Description:
* Remove the next note from the tail of the circular buffer. The note
* is also removed from the circular buffer to make room for futher notes.
*
* Input Parameters:
* buffer - Location to return the next note
* buflen - The length of the user provided buffer.
*
* Returned Value:
* None
*
* Assumptions:
* On success, the length of the return note is provided. A negated
* errno value is returned on failure.
*
****************************************************************************/
ssize_t sched_note_get(FAR uint8_t *buffer, size_t buflen)
{
FAR struct note_common_s *note;
irqstate_t flags;
unsigned int remaining;
unsigned int tail;
ssize_t notelen;
DEBUGASSERT(buffer != NULL);
flags = enter_critical_section();
/* Get the index to the tail of the circular buffer */
tail = g_note_info.ni_tail;
DEBUGASSERT(tail < CONFIG_SCHED_NOTE_BUFSIZE);
/* Get the length of the note at the tail index */
note = (FAR struct note_common_s *)&g_note_info.ni_buffer[tail];
notelen = note->nc_length;
DEBUGASSERT(notelen <= note_length());
/* Is the user buffer large enough to hold the note? */
if (buflen < notelen)
{
/* Remove the large note so that we do not get constipated. */
note_remove();
/* and return and error */
notelen = -EFBIG;
goto errout_with_csection;
}
/* Loop until the note has been transferred to the user buffer */
remaining = (unsigned int)notelen;
while (remaining > 0)
{
/* Copy the next byte at the tail index */
*buffer++ = g_note_info.ni_buffer[tail];
/* Adjust indices and counts */
tail = note_next(tail, 1);
remaining--;
}
g_note_info.ni_tail = tail;
errout_with_csection:
leave_critical_section(flags);
return notelen;
}
#endif /* CONFIG_SCHED_INSTRUMENTATION_BUFFER */

View File

@ -43,6 +43,8 @@
#include <queue.h>
#include <assert.h>
#include <nuttx/sched_note.h>
#include "irq/irq.h"
#include "sched/sched.h"

View File

@ -42,6 +42,7 @@
#include <nuttx/irq.h>
#include <nuttx/clock.h>
#include <nuttx/arch.h>
#include <nuttx/sched_note.h>
#include "sched/sched.h"

View File

@ -44,6 +44,7 @@
#include <nuttx/irq.h>
#include <nuttx/arch.h>
#include <nuttx/sched_note.h>
/****************************************************************************
* Public Functions

View File

@ -46,6 +46,7 @@
#include <nuttx/sched.h>
#include <nuttx/irq.h>
#include <nuttx/sched_note.h>
#include "sched/sched.h"
#ifndef CONFIG_DISABLE_SIGNALS