diff options
Diffstat (limited to '')
-rw-r--r-- | cpukit/libmisc/stackchk/check.c | 184 |
1 files changed, 120 insertions, 64 deletions
diff --git a/cpukit/libmisc/stackchk/check.c b/cpukit/libmisc/stackchk/check.c index a2b63345d9..53b96f462c 100644 --- a/cpukit/libmisc/stackchk/check.c +++ b/cpukit/libmisc/stackchk/check.c @@ -1,3 +1,5 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + /** * @file * @@ -15,9 +17,26 @@ * COPYRIGHT (c) 1989-2010. * On-Line Applications Research Corporation (OAR). * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rtems.org/license/LICENSE. + * 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. + * + * 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. * */ @@ -394,129 +413,166 @@ static inline void *Stack_check_Find_high_water_mark( return (void *) base; #endif - return (void *)0; + return NULL; } -static bool Stack_check_Dump_stack_usage( - const Stack_Control *stack, - const void *current, - const char *name, - uint32_t id, - const rtems_printer *printer +static void Stack_check_Visit_stack( + const Stack_Control *stack, + const void *current, + const char *name, + rtems_id id, + rtems_stack_checker_visitor visit, + void *arg ) { - uint32_t size; - uint32_t used; - void *low; - void *high_water_mark; + rtems_stack_checker_info info; - low = Stack_check_Usable_stack_start(stack); - size = Stack_check_Usable_stack_size(stack); + /* This is likely to occur if the stack checker is not actually enabled */ + if ( stack->area == NULL ) { + return; + } - high_water_mark = Stack_check_Find_high_water_mark(low, size); + info.id = id; + info.name = name; + info.current = current; + info.begin = Stack_check_Usable_stack_start( stack ); + info.size = Stack_check_Usable_stack_size( stack ); - if ( high_water_mark ) - used = Stack_check_Calculate_used( low, size, high_water_mark ); - else - used = 0; + if ( Stack_check_Initialized ) { + void *high_water_mark; - rtems_printf( - printer, - "0x%08" PRIx32 " %-21s 0x%08" PRIxPTR " 0x%08" PRIxPTR " 0x%08" PRIxPTR " %6" PRId32 " ", - id, - name, - (uintptr_t) stack->area, - (uintptr_t) stack->area + (uintptr_t) stack->size - 1, - (uintptr_t) current, - size - ); + high_water_mark = + Stack_check_Find_high_water_mark( info.begin, info.size ); - if (Stack_check_Initialized) { - rtems_printf( printer, "%6" PRId32 "\n", used ); + if ( high_water_mark != NULL ) { + info.used = + Stack_check_Calculate_used( info.begin, info.size, high_water_mark ); + } else { + info.used = 0; + } } else { - rtems_printf( printer, "N/A\n" ); + info.used = UINTPTR_MAX; } - return false; + ( *visit )( &info, arg ); } -static bool Stack_check_Dump_threads_usage( +typedef struct { + rtems_stack_checker_visitor visit; + void *arg; +} Stack_check_Visitor; + +static bool Stack_check_Visit_thread( Thread_Control *the_thread, void *arg ) { + Stack_check_Visitor *visitor; char name[ 22 ]; - const rtems_printer *printer; uintptr_t sp = _CPU_Context_Get_SP( &the_thread->Registers ); - printer = arg; + visitor = arg; _Thread_Get_name( the_thread, name, sizeof( name ) ); - Stack_check_Dump_stack_usage( + Stack_check_Visit_stack( &the_thread->Start.Initial_stack, (void *) sp, name, the_thread->Object.id, - printer + visitor->visit, + visitor->arg ); return false; } -static void Stack_check_Dump_interrupt_stack_usage( - const Stack_Control *stack, - uint32_t id, - const rtems_printer *printer +static void Stack_check_Visit_interrupt_stack( + const Stack_Control *stack, + uint32_t id, + rtems_stack_checker_visitor visit, + void *arg ) { - Stack_check_Dump_stack_usage( + Stack_check_Visit_stack( stack, NULL, "Interrupt Stack", id, - printer + visit, + arg ); } -/* - * rtems_stack_checker_report_usage - */ +static void Stack_check_Print_info( + const rtems_stack_checker_info *info, + void *arg +) +{ + const rtems_printer *printer; + + printer = arg; + + rtems_printf( + printer, + "0x%08" PRIx32 " %-21s 0x%08" PRIxPTR " 0x%08" PRIxPTR " 0x%08" PRIxPTR " %6" PRIuPTR " ", + info->id, + info->name, + (uintptr_t) info->begin, + (uintptr_t) info->begin + info->size - 1, + (uintptr_t) info->current, + info->size + ); + + if ( info->used != UINTPTR_MAX ) { + rtems_printf( printer, "%6" PRIuPTR "\n", info->used ); + } else { + rtems_printf( printer, "N/A\n" ); + } +} void rtems_stack_checker_report_usage_with_plugin( const rtems_printer* printer ) { - uint32_t cpu_max; - uint32_t cpu_index; - rtems_printf( printer, " STACK USAGE BY THREAD\n" "ID NAME LOW HIGH CURRENT AVAIL USED\n" ); - /* iterate over all threads and dump the usage */ - rtems_task_iterate( - Stack_check_Dump_threads_usage, + rtems_stack_checker_iterate( + Stack_check_Print_info, RTEMS_DECONST( rtems_printer *, printer ) ); +} + +void rtems_stack_checker_report_usage( void ) +{ + rtems_printer printer; + rtems_print_printer_printk(&printer); + rtems_stack_checker_report_usage_with_plugin( &printer ); +} + +void rtems_stack_checker_iterate( rtems_stack_checker_visitor visit, void *arg ) +{ + Stack_check_Visitor visitor; + uint32_t cpu_max; + uint32_t cpu_index; + + visitor.visit = visit; + visitor.arg = arg; + rtems_task_iterate( Stack_check_Visit_thread, &visitor ); cpu_max = rtems_scheduler_get_processor_maximum(); for ( cpu_index = 0; cpu_index < cpu_max; ++cpu_index ) { - Stack_check_Dump_interrupt_stack_usage( + Stack_check_Visit_interrupt_stack( &Stack_check_Interrupt_stack[ cpu_index ], cpu_index, - printer + visit, + arg ); } } -void rtems_stack_checker_report_usage( void ) -{ - rtems_printer printer; - rtems_print_printer_printk(&printer); - rtems_stack_checker_report_usage_with_plugin( &printer ); -} - static void Stack_check_Prepare_interrupt_stacks( void ) { Stack_Control stack; |