mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 12:11:40 +00:00
Add generic exit-time stack-depth checking to CONFIG_DEBUG_STACK_USAGE
Add generic exit-time stack-depth checking to CONFIG_DEBUG_STACK_USAGE. This also adds UML support. Tested on UML and i386. [akpm@linux-foundation.org: cleanups, speedups, tweaks] Signed-off-by: Jeff Dike <jdike@linux.intel.com> Cc: Oleg Nesterov <oleg@tv-sign.ru> Cc: Ingo Molnar <mingo@elte.hu> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
84812217e3
commit
e18eecb8b3
@ -47,4 +47,13 @@ config GCOV
|
||||
If you're involved in UML kernel development and want to use gcov,
|
||||
say Y. If you're unsure, say N.
|
||||
|
||||
config DEBUG_STACK_USAGE
|
||||
bool "Stack utilization instrumentation"
|
||||
default N
|
||||
help
|
||||
Track the maximum kernel stack usage - this will look at each
|
||||
kernel stack at process exit and log it if it's the deepest
|
||||
stack seen so far.
|
||||
|
||||
This option will slow down process creation and destruction somewhat.
|
||||
endmenu
|
||||
|
@ -527,3 +527,4 @@ CONFIG_FORCED_INLINING=y
|
||||
# CONFIG_RCU_TORTURE_TEST is not set
|
||||
# CONFIG_GPROF is not set
|
||||
# CONFIG_GCOV is not set
|
||||
# CONFIG_DEBUG_STACK_USAGE is not set
|
||||
|
@ -52,10 +52,19 @@ static inline struct thread_info *current_thread_info(void)
|
||||
return ti;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_STACK_USAGE
|
||||
|
||||
#define alloc_thread_info(tsk) \
|
||||
((struct thread_info *) __get_free_pages(GFP_KERNEL | __GFP_ZERO, \
|
||||
CONFIG_KERNEL_STACK_ORDER))
|
||||
#else
|
||||
|
||||
/* thread information allocation */
|
||||
#define alloc_thread_info(tsk) \
|
||||
((struct thread_info *) __get_free_pages(GFP_KERNEL, \
|
||||
CONFIG_KERNEL_STACK_ORDER))
|
||||
#endif
|
||||
|
||||
#define free_thread_info(ti) \
|
||||
free_pages((unsigned long)(ti),CONFIG_KERNEL_STACK_ORDER)
|
||||
|
||||
|
@ -858,6 +858,34 @@ static void exit_notify(struct task_struct *tsk)
|
||||
release_task(tsk);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_STACK_USAGE
|
||||
static void check_stack_usage(void)
|
||||
{
|
||||
static DEFINE_SPINLOCK(low_water_lock);
|
||||
static int lowest_to_date = THREAD_SIZE;
|
||||
unsigned long *n = end_of_stack(current);
|
||||
unsigned long free;
|
||||
|
||||
while (*n == 0)
|
||||
n++;
|
||||
free = (unsigned long)n - (unsigned long)end_of_stack(current);
|
||||
|
||||
if (free >= lowest_to_date)
|
||||
return;
|
||||
|
||||
spin_lock(&low_water_lock);
|
||||
if (free < lowest_to_date) {
|
||||
printk(KERN_WARNING "%s used greatest stack depth: %lu bytes "
|
||||
"left\n",
|
||||
current->comm, free);
|
||||
lowest_to_date = free;
|
||||
}
|
||||
spin_unlock(&low_water_lock);
|
||||
}
|
||||
#else
|
||||
static inline void check_stack_usage(void) {}
|
||||
#endif
|
||||
|
||||
fastcall NORET_TYPE void do_exit(long code)
|
||||
{
|
||||
struct task_struct *tsk = current;
|
||||
@ -949,6 +977,7 @@ fastcall NORET_TYPE void do_exit(long code)
|
||||
exit_sem(tsk);
|
||||
__exit_files(tsk);
|
||||
__exit_fs(tsk);
|
||||
check_stack_usage();
|
||||
exit_thread();
|
||||
cpuset_exit(tsk);
|
||||
exit_keys(tsk);
|
||||
|
Loading…
Reference in New Issue
Block a user