drivers/note: Move taskname related functions to note_driver.c

so all note drivers can retrieve the task name even after the task exit

Signed-off-by: yinshengkai <yinshengkai@xiaomi.com>
This commit is contained in:
yinshengkai 2022-12-26 13:18:33 +08:00 committed by Xiang Xiao
parent 7322eafba7
commit dd32eccfc3
6 changed files with 245 additions and 267 deletions

View File

@ -46,18 +46,18 @@ The following configurations are configurable parameters for trace.
- If enabled, use higher resolution system timer for instrumentation. - If enabled, use higher resolution system timer for instrumentation.
- ``CONFIG_DRIVER_NOTERAM_BUFSIZE`` - ``CONFIG_DRIVER_NOTE_TASKNAME_BUFSIZE``
- Specify the note buffer size in bytes.
Higher value can hold more note records, but consumes more kernel memory.
- ``CONFIG_DRIVER_NOTERAM_TASKNAME_BUFSIZE``
- Specify the task name buffer size in bytes. - Specify the task name buffer size in bytes.
The buffer is used to hold the name of the task during instrumentation. The buffer is used to hold the name of the task during instrumentation.
Trace dump can find and show a task name corresponding to given pid in the instrumentation data by using this buffer. Trace dump can find and show a task name corresponding to given pid in the instrumentation data by using this buffer.
If 0 is specified, this feature is disabled and trace dump shows only the name of the newly created task. If 0 is specified, this feature is disabled and trace dump shows only the name of the newly created task.
- ``CONFIG_DRIVER_NOTERAM_BUFSIZE``
- Specify the note buffer size in bytes.
Higher value can hold more note records, but consumes more kernel memory.
- ``CONFIG_DRIVER_NOTERAM_DEFAULT_NOOVERWRITE`` - ``CONFIG_DRIVER_NOTERAM_DEFAULT_NOOVERWRITE``
- If enabled, stop overwriting old notes in the circular buffer when the buffer is full by default. - If enabled, stop overwriting old notes in the circular buffer when the buffer is full by default.

View File

@ -16,6 +16,18 @@ config DRIVER_NOTE_MAX
---help--- ---help---
sched_note supports the maximum number of drivers sched_note supports the maximum number of drivers
config DRIVER_NOTE_TASKNAME_BUFSIZE
int "Note task name buffer size"
default 256 if TASK_NAME_SIZE > 0
default 0 if TASK_NAME_SIZE = 0
---help---
The size of the in-memory task name buffer (in bytes).
The buffer is used to hold the name of the task during instrumentation.
Trace dump can find and show a task name corresponding to given pid in
the instrumentation data by using this buffer.
If 0 is specified, this feature is disabled and trace dump shows only
the name of the newly created task.
choice choice
prompt "Note driver selection" prompt "Note driver selection"
default DRIVER_NOTERAM default DRIVER_NOTERAM
@ -79,19 +91,6 @@ config DRIVER_NOTERAM_BUFSIZE
---help--- ---help---
The size of the in-memory, circular instrumentation buffer (in bytes). The size of the in-memory, circular instrumentation buffer (in bytes).
config DRIVER_NOTERAM_TASKNAME_BUFSIZE
int "Note RAM task name buffer size"
depends on DRIVER_NOTERAM
default 256 if TASK_NAME_SIZE > 0
default 0 if TASK_NAME_SIZE = 0
---help---
The size of the in-memory task name buffer (in bytes).
The buffer is used to hold the name of the task during instrumentation.
Trace dump can find and show a task name corresponding to given pid in
the instrumentation data by using this buffer.
If 0 is specified, this feature is disabled and trace dump shows only
the name of the newly created task.
config DRIVER_NOTERAM_DEFAULT_NOOVERWRITE config DRIVER_NOTERAM_DEFAULT_NOOVERWRITE
bool "Disable overwrite by default" bool "Disable overwrite by default"
depends on DRIVER_NOTERAM depends on DRIVER_NOTERAM

View File

@ -119,6 +119,22 @@ struct note_startalloc_s
# define SIZEOF_NOTE_START(n) (sizeof(struct note_start_s)) # define SIZEOF_NOTE_START(n) (sizeof(struct note_start_s))
#endif #endif
#if CONFIG_DRIVER_NOTE_TASKNAME_BUFSIZE > 0
struct note_taskname_info_s
{
uint8_t size;
uint8_t pid[2];
char name[1];
};
struct note_taskname_s
{
size_t head;
size_t tail;
char buffer[CONFIG_DRIVER_NOTE_TASKNAME_BUFSIZE];
};
#endif
/**************************************************************************** /****************************************************************************
* Private Data * Private Data
****************************************************************************/ ****************************************************************************/
@ -146,6 +162,10 @@ FAR static struct note_driver_s *g_note_drivers[CONFIG_DRIVER_NOTE_MAX + 1] =
#endif #endif
}; };
#if CONFIG_DRIVER_NOTE_TASKNAME_BUFSIZE > 0
static struct note_taskname_s g_note_taskname;
#endif
/**************************************************************************** /****************************************************************************
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
@ -435,6 +455,128 @@ static inline int note_isenabled_dump(void)
} }
#endif #endif
#if CONFIG_DRIVER_NOTE_TASKNAME_BUFSIZE > 0
/****************************************************************************
* Name: note_find_taskname
*
* Description:
* Find task name info corresponding to the specified PID
*
* Input Parameters:
* PID - Task ID
*
* Returned Value:
* Pointer to the task name info
* If the corresponding info doesn't exist in the buffer, NULL is returned.
*
****************************************************************************/
static FAR struct note_taskname_info_s *note_find_taskname(pid_t pid)
{
FAR struct note_taskname_info_s *ti;
int n = g_note_taskname.tail;
while (n != g_note_taskname.head)
{
ti = (FAR struct note_taskname_info_s *)
&g_note_taskname.buffer[n];
if (ti->pid[0] + (ti->pid[1] << 8) == pid)
{
return ti;
}
n += ti->size;
if (n >= CONFIG_DRIVER_NOTE_TASKNAME_BUFSIZE)
{
n -= CONFIG_DRIVER_NOTE_TASKNAME_BUFSIZE;
}
}
return NULL;
}
/****************************************************************************
* Name: note_record_taskname
*
* Description:
* Record the task name info of the specified task
*
* Input Parameters:
* PID - Task ID
* name - task name
*
* Returned Value:
* None
*
****************************************************************************/
static void note_record_taskname(pid_t pid, FAR const char *name)
{
FAR struct note_taskname_info_s *ti;
size_t tilen;
size_t namelen;
size_t skiplen;
size_t remain;
namelen = strlen(name);
DEBUGASSERT(namelen <= CONFIG_TASK_NAME_SIZE);
tilen = sizeof(struct note_taskname_info_s) + namelen;
DEBUGASSERT(tilen <= UCHAR_MAX);
skiplen = CONFIG_DRIVER_NOTE_TASKNAME_BUFSIZE - g_note_taskname.head;
if (skiplen >= tilen + sizeof(struct note_taskname_info_s))
{
skiplen = 0; /* Have enough space at the tail - needn't skip */
}
if (g_note_taskname.head >= g_note_taskname.tail)
{
remain = CONFIG_DRIVER_NOTE_TASKNAME_BUFSIZE -
(g_note_taskname.head - g_note_taskname.tail);
}
else
{
remain = g_note_taskname.tail - g_note_taskname.head;
}
while (skiplen + tilen >= remain)
{
/* No enough space, drop the old info */
ti = (FAR struct note_taskname_info_s *)
&g_note_taskname.buffer[g_note_taskname.tail];
g_note_taskname.tail = (g_note_taskname.tail + ti->size) %
CONFIG_DRIVER_NOTE_TASKNAME_BUFSIZE;
remain += ti->size;
}
if (skiplen)
{
/* Fill the skipped region with an invalid info */
ti = (FAR struct note_taskname_info_s *)
&g_note_taskname.buffer[g_note_taskname.head];
ti->size = skiplen;
ti->pid[0] = 0xff;
ti->pid[1] = 0xff;
ti->name[0] = '\0';
/* Move to the begin of circle buffer */
g_note_taskname.head = 0;
}
ti = (FAR struct note_taskname_info_s *)
&g_note_taskname.buffer[g_note_taskname.head];
ti->size = tilen;
ti->pid[0] = pid & 0xff;
ti->pid[1] = (pid >> 8) & 0xff;
strlcpy(ti->name, name, namelen + 1);
g_note_taskname.head += tilen;
}
#endif
/**************************************************************************** /****************************************************************************
* Public Functions * Public Functions
****************************************************************************/ ****************************************************************************/
@ -522,6 +664,10 @@ void sched_note_stop(FAR struct tcb_s *tcb)
FAR struct note_driver_s **driver; FAR struct note_driver_s **driver;
bool formatted = false; bool formatted = false;
#if CONFIG_DRIVER_NOTE_TASKNAME_BUFSIZE > 0
note_record_taskname(tcb->pid, tcb->name);
#endif
if (!note_isenabled()) if (!note_isenabled())
{ {
return; return;
@ -1699,3 +1845,50 @@ void sched_note_filter_irq(FAR struct note_filter_irq_s *oldf,
#endif #endif
#endif /* CONFIG_SCHED_INSTRUMENTATION_FILTER */ #endif /* CONFIG_SCHED_INSTRUMENTATION_FILTER */
#if CONFIG_DRIVER_NOTE_TASKNAME_BUFSIZE > 0
/****************************************************************************
* Name: note_get_taskname
*
* Description:
* Get the task name string of the specified PID
*
* 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
*
****************************************************************************/
int note_get_taskname(pid_t pid, FAR char *buffer)
{
FAR struct note_taskname_info_s *ti;
FAR struct tcb_s *tcb;
irqstate_t irq_mask;
irq_mask = enter_critical_section();
tcb = nxsched_get_tcb(pid);
if (tcb != NULL)
{
strlcpy(buffer, tcb->name, CONFIG_TASK_NAME_SIZE + 1);
leave_critical_section(irq_mask);
return OK;
}
ti = note_find_taskname(pid);
if (ti != NULL)
{
strlcpy(buffer, ti->name, CONFIG_TASK_NAME_SIZE + 1);
leave_critical_section(irq_mask);
return OK;
}
leave_critical_section(irq_mask);
return -ESRCH;
}
#endif

View File

@ -51,21 +51,6 @@ struct noteram_info_s
uint8_t ni_buffer[CONFIG_DRIVER_NOTERAM_BUFSIZE]; uint8_t ni_buffer[CONFIG_DRIVER_NOTERAM_BUFSIZE];
}; };
#if CONFIG_DRIVER_NOTERAM_TASKNAME_BUFSIZE > 0
struct noteram_taskname_info_s
{
uint8_t size;
uint8_t pid[2];
char name[1];
};
struct noteram_taskname_s
{
int buffer_used;
char buffer[CONFIG_DRIVER_NOTERAM_TASKNAME_BUFSIZE];
};
#endif
/**************************************************************************** /****************************************************************************
* Private Function Prototypes * Private Function Prototypes
****************************************************************************/ ****************************************************************************/
@ -104,10 +89,6 @@ static struct noteram_info_s g_noteram_info =
#endif #endif
}; };
#if CONFIG_DRIVER_NOTERAM_TASKNAME_BUFSIZE > 0
static struct noteram_taskname_s g_noteram_taskname;
#endif
static const struct note_driver_ops_s g_noteram_ops = static const struct note_driver_ops_s g_noteram_ops =
{ {
noteram_add noteram_add
@ -130,170 +111,6 @@ struct note_driver_s g_noteram_driver =
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
/****************************************************************************
* Name: noteram_find_taskname
*
* Description:
* Find task name info corresponding to the specified PID
*
* Input Parameters:
* PID - Task ID
*
* Returned Value:
* Pointer to the task name info
* If the corresponding info doesn't exist in the buffer, NULL is returned.
*
****************************************************************************/
#if CONFIG_DRIVER_NOTERAM_TASKNAME_BUFSIZE > 0
static FAR struct noteram_taskname_info_s *noteram_find_taskname(pid_t pid)
{
int n;
FAR struct noteram_taskname_info_s *ti;
for (n = 0; n < g_noteram_taskname.buffer_used; )
{
ti = (FAR struct noteram_taskname_info_s *)
&g_noteram_taskname.buffer[n];
if (ti->pid[0] + (ti->pid[1] << 8) == pid)
{
return ti;
}
n += ti->size;
}
return NULL;
}
#endif
/****************************************************************************
* Name: noteram_record_taskname
*
* Description:
* Record the task name info of the specified task
*
* Input Parameters:
* PID - Task ID
* name - task name
*
* Returned Value:
* None
*
****************************************************************************/
#if CONFIG_DRIVER_NOTERAM_TASKNAME_BUFSIZE > 0
static void noteram_record_taskname(pid_t pid, const char *name)
{
FAR struct noteram_taskname_info_s *ti;
size_t tilen;
size_t namelen;
namelen = strlen(name);
DEBUGASSERT(namelen <= CONFIG_TASK_NAME_SIZE);
tilen = sizeof(struct noteram_taskname_info_s) + namelen;
DEBUGASSERT(tilen <= UCHAR_MAX);
if (g_noteram_taskname.buffer_used + tilen >
CONFIG_DRIVER_NOTERAM_TASKNAME_BUFSIZE)
{
/* No space in the buffer - ignored */
return;
}
ti = (FAR struct noteram_taskname_info_s *)
&g_noteram_taskname.buffer[g_noteram_taskname.buffer_used];
ti->size = tilen;
ti->pid[0] = pid & 0xff;
ti->pid[1] = (pid >> 8) & 0xff;
strlcpy(ti->name, name, namelen + 1);
g_noteram_taskname.buffer_used += tilen;
}
#endif
/****************************************************************************
* Name: noteram_remove_taskname
*
* Description:
* Remove the task name info corresponding to the specified PID
*
* Input Parameters:
* PID - Task ID
*
* Returned Value:
* None
*
****************************************************************************/
#if CONFIG_DRIVER_NOTERAM_TASKNAME_BUFSIZE > 0
static void noteram_remove_taskname(pid_t pid)
{
FAR struct noteram_taskname_info_s *ti;
size_t tilen;
char *src;
int sindex;
ti = noteram_find_taskname(pid);
if (ti == NULL)
{
return;
}
tilen = ti->size;
src = (char *)ti + tilen;
sindex = src - g_noteram_taskname.buffer;
memcpy(ti, src, g_noteram_taskname.buffer_used - sindex);
g_noteram_taskname.buffer_used -= tilen;
}
#endif
/****************************************************************************
* Name: noteram_get_taskname
*
* Description:
* Get the task name string of the specified PID
*
* Input Parameters:
* PID - Task ID
*
* Returned Value:
* Pointer to the task name string
* If the corresponding name doesn't exist in the buffer, NULL is returned.
*
****************************************************************************/
#if CONFIG_DRIVER_NOTERAM_TASKNAME_BUFSIZE > 0
static const char *noteram_get_taskname(pid_t pid)
{
irqstate_t irq_mask;
const char *ret = NULL;
FAR struct noteram_taskname_info_s *ti;
FAR struct tcb_s *tcb;
irq_mask = enter_critical_section();
ti = noteram_find_taskname(pid);
if (ti != NULL)
{
ret = ti->name;
}
else
{
tcb = nxsched_get_tcb(pid);
if (tcb != NULL)
{
noteram_record_taskname(pid, tcb->name);
ret = tcb->name;
}
}
leave_critical_section(irq_mask);
return ret;
}
#endif
/**************************************************************************** /****************************************************************************
* Name: noteram_buffer_clear * Name: noteram_buffer_clear
* *
@ -322,10 +139,6 @@ static void noteram_buffer_clear(void)
g_noteram_info.ni_overwrite = NOTERAM_MODE_OVERWRITE_DISABLE; g_noteram_info.ni_overwrite = NOTERAM_MODE_OVERWRITE_DISABLE;
} }
#if CONFIG_DRIVER_NOTERAM_TASKNAME_BUFSIZE > 0
g_noteram_taskname.buffer_used = 0;
#endif
leave_critical_section(flags); leave_critical_section(flags);
} }
@ -442,27 +255,6 @@ static void noteram_remove(void)
length = g_noteram_info.ni_buffer[tail]; length = g_noteram_info.ni_buffer[tail];
DEBUGASSERT(length <= noteram_length()); DEBUGASSERT(length <= noteram_length());
#if CONFIG_DRIVER_NOTERAM_TASKNAME_BUFSIZE > 0
if (g_noteram_info.ni_buffer[noteram_next(tail, 1)] == NOTE_STOP)
{
uint8_t nc_pid[2];
/* The name of the task is no longer needed because the task is deleted
* and the corresponding notes are lost.
*/
#ifdef CONFIG_SMP
nc_pid[0] = g_noteram_info.ni_buffer[noteram_next(tail, 4)];
nc_pid[1] = g_noteram_info.ni_buffer[noteram_next(tail, 5)];
#else
nc_pid[0] = g_noteram_info.ni_buffer[noteram_next(tail, 3)];
nc_pid[1] = g_noteram_info.ni_buffer[noteram_next(tail, 4)];
#endif
noteram_remove_taskname(nc_pid[0] + (nc_pid[1] << 8));
}
#endif
/* Increment the tail index to remove the entire note from the circular /* Increment the tail index to remove the entire note from the circular
* buffer. * buffer.
*/ */
@ -690,7 +482,7 @@ static ssize_t noteram_read(FAR struct file *filep,
* Name: noteram_ioctl * Name: noteram_ioctl
****************************************************************************/ ****************************************************************************/
static int noteram_ioctl(struct file *filep, int cmd, unsigned long arg) static int noteram_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
{ {
int ret = -ENOSYS; int ret = -ENOSYS;
@ -742,7 +534,7 @@ static int noteram_ioctl(struct file *filep, int cmd, unsigned long arg)
} }
break; break;
#if CONFIG_DRIVER_NOTERAM_TASKNAME_BUFSIZE > 0 #ifdef NOTERAM_GETTASKNAME
/* NOTERAM_GETTASKNAME /* NOTERAM_GETTASKNAME
* - Get task name string * - Get task name string
* Argument: A writable pointer to struct note_get_taskname_s * Argument: A writable pointer to struct note_get_taskname_s
@ -752,28 +544,16 @@ static int noteram_ioctl(struct file *filep, int cmd, unsigned long arg)
case NOTERAM_GETTASKNAME: case NOTERAM_GETTASKNAME:
{ {
struct noteram_get_taskname_s *param; FAR struct noteram_get_taskname_s *param;
const char *taskname;
if (arg == 0) if (arg == 0)
{ {
ret = -EINVAL; ret = -EINVAL;
break; break;
} }
param = (struct noteram_get_taskname_s *)arg; param = (FAR struct noteram_get_taskname_s *)arg;
taskname = noteram_get_taskname(param->pid); ret = note_get_taskname(param->pid, param->taskname);
if (taskname != NULL)
{
strlcpy(param->taskname, taskname, CONFIG_TASK_NAME_SIZE + 1);
param->taskname[CONFIG_TASK_NAME_SIZE] = '\0';
ret = 0;
}
else
{
param->taskname[0] = '\0';
ret = -ESRCH;
}
} }
break; break;
#endif #endif
@ -825,22 +605,6 @@ static void noteram_add(FAR struct note_driver_s *drv,
return; return;
} }
#if CONFIG_DRIVER_NOTERAM_TASKNAME_BUFSIZE > 0
/* Record the name if the new task was created */
{
FAR struct note_start_s *note_st;
note_st = (FAR struct note_start_s *)note;
if (note_st->nst_cmn.nc_type == NOTE_START)
{
noteram_record_taskname(note_st->nst_cmn.nc_pid[0] +
(note_st->nst_cmn.nc_pid[1] << 8),
note_st->nst_name);
}
}
#endif
/* Get the index to the head of the circular buffer */ /* Get the index to the head of the circular buffer */
DEBUGASSERT(note != NULL && notelen < CONFIG_DRIVER_NOTERAM_BUFSIZE); DEBUGASSERT(note != NULL && notelen < CONFIG_DRIVER_NOTERAM_BUFSIZE);

View File

@ -130,4 +130,26 @@ int note_initialize(void);
#endif /* defined(__KERNEL__) || defined(CONFIG_BUILD_FLAT) */ #endif /* defined(__KERNEL__) || defined(CONFIG_BUILD_FLAT) */
#if CONFIG_DRIVER_NOTE_TASKNAME_BUFSIZE > 0
/****************************************************************************
* Name: note_get_taskname
*
* Description:
* Get the task name string of the specified PID
*
* 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
*
****************************************************************************/
int note_get_taskname(pid_t pid, FAR char *name);
#endif /* CONFIG_DRIVER_NOTE_TASKNAME_BUFSIZE > 0 */
#endif /* __INCLUDE_NUTTX_NOTE_NOTE_DRIVER_H */ #endif /* __INCLUDE_NUTTX_NOTE_NOTE_DRIVER_H */

View File

@ -56,7 +56,7 @@
#define NOTERAM_CLEAR _NOTERAMIOC(0x01) #define NOTERAM_CLEAR _NOTERAMIOC(0x01)
#define NOTERAM_GETMODE _NOTERAMIOC(0x02) #define NOTERAM_GETMODE _NOTERAMIOC(0x02)
#define NOTERAM_SETMODE _NOTERAMIOC(0x03) #define NOTERAM_SETMODE _NOTERAMIOC(0x03)
#if CONFIG_DRIVER_NOTERAM_TASKNAME_BUFSIZE > 0 #if CONFIG_DRIVER_NOTE_TASKNAME_BUFSIZE > 0
#define NOTERAM_GETTASKNAME _NOTERAMIOC(0x04) #define NOTERAM_GETTASKNAME _NOTERAMIOC(0x04)
#endif #endif
#endif #endif
@ -75,7 +75,7 @@
/* This is the type of the argument passed to the NOTERAM_GETTASKNAME ioctl */ /* This is the type of the argument passed to the NOTERAM_GETTASKNAME ioctl */
#if CONFIG_DRIVER_NOTERAM_TASKNAME_BUFSIZE > 0 #ifdef NOTERAM_GETTASKNAME
struct noteram_get_taskname_s struct noteram_get_taskname_s
{ {
pid_t pid; pid_t pid;