From: Chuck Ebbert <76306.1226@compuserve.com> Print stack backtraces in multiple columns, saving screen space. Number of columns is configurable and defaults to one so behavior is backwards-compatible. Also removes the brackets around addresses when printing more that one entry per line so they print as:
instead of: [
] This helps multiple entries fit better on one line. Original idea by Dave Jones, taken from x86_64. Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Signed-off-by: Dave Jones Signed-off-by: Andrew Morton --- arch/i386/Kconfig.debug | 9 +++++++++ arch/i386/kernel/traps.c | 32 +++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 5 deletions(-) diff -puN arch/i386/Kconfig.debug~i386-multi-column-stack-backtraces arch/i386/Kconfig.debug --- devel/arch/i386/Kconfig.debug~i386-multi-column-stack-backtraces 2006-02-10 02:07:33.000000000 -0800 +++ devel-akpm/arch/i386/Kconfig.debug 2006-02-10 02:07:35.000000000 -0800 @@ -31,6 +31,15 @@ config DEBUG_STACK_USAGE This option will slow down process creation somewhat. +config STACK_BACKTRACE_COLS + int "Stack backtraces per line" if DEBUG_KERNEL + range 1 3 + default 2 + help + Selects how many stack backtrace entries per line to display. + + This can save screen space when displaying traces. + comment "Page alloc debug is incompatible with Software Suspend on i386" depends on DEBUG_KERNEL && SOFTWARE_SUSPEND diff -puN arch/i386/kernel/traps.c~i386-multi-column-stack-backtraces arch/i386/kernel/traps.c --- devel/arch/i386/kernel/traps.c~i386-multi-column-stack-backtraces 2006-02-10 02:07:33.000000000 -0800 +++ devel-akpm/arch/i386/kernel/traps.c 2006-02-10 02:07:33.000000000 -0800 @@ -112,12 +112,30 @@ static inline int valid_stack_ptr(struct p < (void *)tinfo + THREAD_SIZE - 3; } -static void print_addr_and_symbol(unsigned long addr, char *log_lvl) +/* + * Print CONFIG_STACK_BACKTRACE_COLS address/symbol entries per line. + */ +static inline int print_addr_and_symbol(unsigned long addr, char *log_lvl, + int printed) { - printk(log_lvl); + if (!printed) + printk(log_lvl); + +#if CONFIG_STACK_BACKTRACE_COLS == 1 printk(" [<%08lx>] ", addr); +#else + printk(" <%08lx> ", addr); +#endif print_symbol("%s", addr); - printk("\n"); + + printed = (printed + 1) % CONFIG_STACK_BACKTRACE_COLS; + + if (printed) + printk(" "); + else + printk("\n"); + + return printed; } static inline unsigned long print_context_stack(struct thread_info *tinfo, @@ -125,20 +143,24 @@ static inline unsigned long print_contex char *log_lvl) { unsigned long addr; + int printed = 0; /* nr of entries already printed on current line */ #ifdef CONFIG_FRAME_POINTER while (valid_stack_ptr(tinfo, (void *)ebp)) { addr = *(unsigned long *)(ebp + 4); - print_addr_and_symbol(addr, log_lvl); + printed = print_addr_and_symbol(addr, log_lvl, printed); ebp = *(unsigned long *)ebp; } #else while (valid_stack_ptr(tinfo, stack)) { addr = *stack++; if (__kernel_text_address(addr)) - print_addr_and_symbol(addr, log_lvl); + printed = print_addr_and_symbol(addr, log_lvl, printed); } #endif + if (printed) + printk("\n"); + return ebp; } _