mirror of
https://github.com/apache/nuttx.git
synced 2026-08-31 14:13:04 +00:00
sched/procfs:use instrument to statistics run time max stack
Usage: 1. CONFIG_FS_PROCFS_MAX_STACK_RECORD > 0, such as 32, 2. add '-finstrument-functions' to CFLAGS for What you want to check stack. 3. mount porcfs 4. cat /proc/<pid>/stack will print backtace & size Signed-off-by: anjiahao <anjiahao@xiaomi.com>
This commit is contained in:
parent
7dfbd14eba
commit
d932e0af2a
12 changed files with 364 additions and 0 deletions
|
|
@ -146,6 +146,7 @@ static inline uintptr_t up_getsp(void)
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
noinstrument_function
|
||||
static inline bool up_interrupt_context(void)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
|
|
|
|||
|
|
@ -986,6 +986,9 @@ static ssize_t proc_stack(FAR struct proc_file_s *procfile,
|
|||
size_t linesize;
|
||||
size_t copysize;
|
||||
size_t totalsize;
|
||||
#if CONFIG_SCHED_STACK_RECORD > 0
|
||||
int i;
|
||||
#endif
|
||||
|
||||
remaining = buflen;
|
||||
totalsize = 0;
|
||||
|
|
@ -1033,6 +1036,56 @@ static ssize_t proc_stack(FAR struct proc_file_s *procfile,
|
|||
buffer += copysize;
|
||||
remaining -= copysize;
|
||||
|
||||
#if CONFIG_SCHED_STACK_RECORD > 0
|
||||
linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "%-12s%zu\n",
|
||||
"StackMax: ",
|
||||
tcb->stack_base_ptr +
|
||||
tcb->adj_stack_size - tcb->sp_deepest);
|
||||
copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining,
|
||||
&offset);
|
||||
|
||||
totalsize += copysize;
|
||||
buffer += copysize;
|
||||
remaining -= copysize;
|
||||
|
||||
linesize = procfs_snprintf(procfile->line, STATUS_LINELEN, "%-12s%-s\n",
|
||||
"Size", "Backtrace");
|
||||
copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining,
|
||||
&offset);
|
||||
|
||||
totalsize += copysize;
|
||||
buffer += copysize;
|
||||
remaining -= copysize;
|
||||
|
||||
for (i = tcb->level_deepest - 1; i > 0; i--)
|
||||
{
|
||||
linesize = procfs_snprintf(procfile->line, STATUS_LINELEN,
|
||||
"%-12zu%-pS\n",
|
||||
tcb->stackrecord_sp_deepest[i - 1] -
|
||||
tcb->stackrecord_sp_deepest[i],
|
||||
tcb->stackrecord_pc_deepest[i]);
|
||||
copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining,
|
||||
&offset);
|
||||
totalsize += copysize;
|
||||
buffer += copysize;
|
||||
remaining -= copysize;
|
||||
}
|
||||
|
||||
if (tcb->caller_deepest)
|
||||
{
|
||||
linesize = procfs_snprintf(procfile->line, STATUS_LINELEN,
|
||||
"Warning stack record buffer too small\n"
|
||||
"Max: %u Overflow: %zu\n",
|
||||
CONFIG_SCHED_STACK_RECORD,
|
||||
tcb->caller_deepest);
|
||||
copysize = procfs_memcpy(procfile->line, linesize, buffer, remaining,
|
||||
&offset);
|
||||
totalsize += copysize;
|
||||
buffer += copysize;
|
||||
remaining -= copysize;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
if (totalsize >= buflen)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -251,6 +251,10 @@
|
|||
|
||||
# define noinstrument_function __attribute__((no_instrument_function))
|
||||
|
||||
/* The nooptimiziation_function attribute no optimize */
|
||||
|
||||
# define nooptimiziation_function __attribute__((optimize(0)))
|
||||
|
||||
/* The nosanitize_address attribute informs GCC don't sanitize it */
|
||||
|
||||
# define nosanitize_address __attribute__((no_sanitize_address))
|
||||
|
|
@ -555,6 +559,7 @@
|
|||
# define always_inline_function
|
||||
# define noinline_function
|
||||
# define noinstrument_function
|
||||
# define nooptimiziation_function
|
||||
# define nosanitize_address
|
||||
# define nosanitize_undefined
|
||||
# define nostackprotect_function
|
||||
|
|
@ -698,6 +703,7 @@
|
|||
# define always_inline_function
|
||||
# define noinline_function
|
||||
# define noinstrument_function
|
||||
# define nooptimiziation_function
|
||||
# define nosanitize_address
|
||||
# define nosanitize_undefined
|
||||
# define nostackprotect_function
|
||||
|
|
@ -809,6 +815,7 @@
|
|||
# define always_inline_function
|
||||
# define noinline_function
|
||||
# define noinstrument_function
|
||||
# define nooptimiziation_function
|
||||
# define nosanitize_address
|
||||
# define nosanitize_undefined
|
||||
# define nostackprotect_function
|
||||
|
|
@ -899,6 +906,7 @@
|
|||
# define always_inline_function
|
||||
# define noinline_function
|
||||
# define noinstrument_function
|
||||
# define nooptimiziation_function
|
||||
# define nosanitize_address
|
||||
# define nosanitize_undefined
|
||||
# define nostackprotect_function
|
||||
|
|
@ -964,6 +972,7 @@
|
|||
# define always_inline_function
|
||||
# define noinline_function
|
||||
# define noinstrument_function
|
||||
# define nooptimiziation_function
|
||||
# define nosanitize_address
|
||||
# define nosanitize_undefined
|
||||
# define nostackprotect_function
|
||||
|
|
|
|||
|
|
@ -645,6 +645,17 @@ struct tcb_s
|
|||
#if CONFIG_TASK_NAME_SIZE > 0
|
||||
char name[CONFIG_TASK_NAME_SIZE + 1]; /* Task name (with NUL terminator */
|
||||
#endif
|
||||
|
||||
#if CONFIG_SCHED_STACK_RECORD > 0
|
||||
FAR void *stackrecord_pc[CONFIG_SCHED_STACK_RECORD];
|
||||
FAR void *stackrecord_sp[CONFIG_SCHED_STACK_RECORD];
|
||||
FAR void *stackrecord_pc_deepest[CONFIG_SCHED_STACK_RECORD];
|
||||
FAR void *stackrecord_sp_deepest[CONFIG_SCHED_STACK_RECORD];
|
||||
FAR void *sp_deepest;
|
||||
size_t caller_deepest;
|
||||
size_t level_deepest;
|
||||
size_t level;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* struct task_tcb_s ********************************************************/
|
||||
|
|
|
|||
|
|
@ -1221,6 +1221,19 @@ config SCHED_INSTRUMENTATION_FUNCTION
|
|||
endif # SCHED_INSTRUMENTATION
|
||||
endmenu # Performance Monitoring
|
||||
|
||||
menu "System Auto Instrumentation"
|
||||
|
||||
config SCHED_STACK_RECORD
|
||||
int "Maximum stack backtrace to record"
|
||||
default 0
|
||||
---help---
|
||||
Specifies the maximum number of stack backtrace to record in the
|
||||
TCB. Useful if scheduler instrumentation is selected. Set to zero
|
||||
to disable.Through instrumentation, record the backtrace at
|
||||
the deepest point in the stack.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Files and I/O"
|
||||
|
||||
config DEV_CONSOLE
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ include clock/Make.defs
|
|||
include environ/Make.defs
|
||||
include group/Make.defs
|
||||
include init/Make.defs
|
||||
include instrument/Make.defs
|
||||
include irq/Make.defs
|
||||
include misc/Make.defs
|
||||
include mqueue/Make.defs
|
||||
|
|
|
|||
|
|
@ -56,6 +56,7 @@
|
|||
#include "irq/irq.h"
|
||||
#include "group/group.h"
|
||||
#include "init/init.h"
|
||||
#include "instrument/instrument.h"
|
||||
#include "tls/tls.h"
|
||||
|
||||
/****************************************************************************
|
||||
|
|
@ -564,6 +565,10 @@ void nx_start(void)
|
|||
|
||||
sched_lock();
|
||||
|
||||
/* Initialize the instrument function */
|
||||
|
||||
instrument_initialize();
|
||||
|
||||
/* Initialize the file system (needed to support device drivers) */
|
||||
|
||||
fs_initialize();
|
||||
|
|
|
|||
27
sched/instrument/CMakeLists.txt
Normal file
27
sched/instrument/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# ##############################################################################
|
||||
# sched/instrument/CMakeLists.txt
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more contributor
|
||||
# license agreements. See the NOTICE file distributed with this work for
|
||||
# additional information regarding copyright ownership. The ASF licenses this
|
||||
# file to you under the Apache License, Version 2.0 (the "License"); you may not
|
||||
# use this file except in compliance with the License. You may obtain a copy of
|
||||
# the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations under
|
||||
# the License.
|
||||
#
|
||||
# ##############################################################################
|
||||
|
||||
set(SRCS instrument.c)
|
||||
|
||||
if(NOT "${CONFIG_SCHED_STACK_RECORD}" STREQUAL "0")
|
||||
list(APPEND SRCS stack_record.c)
|
||||
endif()
|
||||
|
||||
target_sources(sched PRIVATE ${SRCS})
|
||||
30
sched/instrument/Make.defs
Normal file
30
sched/instrument/Make.defs
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
############################################################################
|
||||
# sched/instrument/Make.defs
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
CSRCS += instrument.c
|
||||
|
||||
ifneq ($(CONFIG_SCHED_STACK_RECORD),0)
|
||||
CSRCS += stack_record.c
|
||||
endif
|
||||
|
||||
# Include instrument build support
|
||||
|
||||
DEPPATH += --dep-path instrument
|
||||
VPATH += :instrument
|
||||
58
sched/instrument/instrument.c
Normal file
58
sched/instrument/instrument.c
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/****************************************************************************
|
||||
* sched/instrument/instrument.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/instrument.h>
|
||||
|
||||
/****************************************************************************
|
||||
* External Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_SCHED_STACK_RECORD > 0
|
||||
extern struct instrument_s g_stack_record;
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: instrument_initialize
|
||||
*
|
||||
* Description:
|
||||
* This function is called to initialize all the instrument functions
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Does not return.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void instrument_initialize(void)
|
||||
{
|
||||
#if CONFIG_SCHED_STACK_RECORD > 0
|
||||
instrument_register(&g_stack_record);
|
||||
#endif
|
||||
}
|
||||
44
sched/instrument/instrument.h
Normal file
44
sched/instrument/instrument.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/****************************************************************************
|
||||
* sched/instrument/instrument.h
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __SCHED_INSTRUMENT_INSTRUMENT_H
|
||||
#define __SCHED_INSTRUMENT_INSTRUMENT_H
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions prototypes
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: instrument_initialize
|
||||
*
|
||||
* Description:
|
||||
* This function is called to initialize all the instrument functions
|
||||
*
|
||||
* Input Parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* Does not return.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void instrument_initialize(void);
|
||||
|
||||
#endif
|
||||
112
sched/instrument/stack_record.c
Normal file
112
sched/instrument/stack_record.c
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/****************************************************************************
|
||||
* sched/instrument/stack_record.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/instrument.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
static void stack_record_enter(FAR void *this_fn, FAR void *call_site,
|
||||
FAR void *arg) noinstrument_function
|
||||
nooptimiziation_function;
|
||||
static void stack_record_leave(FAR void *this_fn, FAR void *call_site,
|
||||
FAR void *arg) noinstrument_function
|
||||
nooptimiziation_function;
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
struct instrument_s g_stack_record =
|
||||
{
|
||||
.enter = stack_record_enter,
|
||||
.leave = stack_record_leave
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stack_statistics
|
||||
****************************************************************************/
|
||||
|
||||
static void stack_record_enter(FAR void *this_fn, FAR void *call_site,
|
||||
FAR void *arg)
|
||||
{
|
||||
FAR struct tcb_s *tcb = running_task();
|
||||
FAR void *sp = &tcb;
|
||||
size_t i;
|
||||
|
||||
if (tcb == NULL || sp < tcb->stack_base_ptr ||
|
||||
sp >= tcb->stack_base_ptr + tcb->adj_stack_size)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (tcb->level < CONFIG_SCHED_STACK_RECORD)
|
||||
{
|
||||
tcb->stackrecord_sp[tcb->level] = sp;
|
||||
tcb->stackrecord_pc[tcb->level++] = this_fn;
|
||||
}
|
||||
else if (tcb->caller_deepest < ++tcb->level)
|
||||
{
|
||||
tcb->caller_deepest = tcb->level;
|
||||
}
|
||||
|
||||
if (tcb->sp_deepest == NULL || sp < tcb->sp_deepest)
|
||||
{
|
||||
tcb->level_deepest = MIN(tcb->level, CONFIG_SCHED_STACK_RECORD);
|
||||
for (i = 0; i < tcb->level_deepest; i++)
|
||||
{
|
||||
tcb->stackrecord_pc_deepest[i] = tcb->stackrecord_pc[i];
|
||||
tcb->stackrecord_sp_deepest[i] = tcb->stackrecord_sp[i];
|
||||
}
|
||||
|
||||
tcb->sp_deepest = sp;
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: stackrecord_leave
|
||||
****************************************************************************/
|
||||
|
||||
static void stack_record_leave(FAR void *this_fn, FAR void *call_site,
|
||||
FAR void *arg)
|
||||
{
|
||||
FAR struct tcb_s *tcb = running_task();
|
||||
FAR void *sp = &tcb;
|
||||
|
||||
if (tcb == NULL || tcb->level == 0 || sp < tcb->stack_base_ptr ||
|
||||
sp >= tcb->stack_base_ptr + tcb->adj_stack_size)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
tcb->level--;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue