소스 검색

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>
Jeff Dike 18 년 전
부모
커밋
e18eecb8b3
4개의 변경된 파일48개의 추가작업 그리고 0개의 파일을 삭제
  1. 9 0
      arch/um/Kconfig.debug
  2. 1 0
      arch/um/defconfig
  3. 9 0
      include/asm-um/thread_info.h
  4. 29 0
      kernel/exit.c

+ 9 - 0
arch/um/Kconfig.debug

@@ -47,4 +47,13 @@ config GCOV
         If you're involved in UML kernel development and want to use gcov,
         If you're involved in UML kernel development and want to use gcov,
         say Y.  If you're unsure, say N.
         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
 endmenu

+ 1 - 0
arch/um/defconfig

@@ -527,3 +527,4 @@ CONFIG_FORCED_INLINING=y
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_RCU_TORTURE_TEST is not set
 # CONFIG_GPROF is not set
 # CONFIG_GPROF is not set
 # CONFIG_GCOV is not set
 # CONFIG_GCOV is not set
+# CONFIG_DEBUG_STACK_USAGE is not set

+ 9 - 0
include/asm-um/thread_info.h

@@ -52,10 +52,19 @@ static inline struct thread_info *current_thread_info(void)
 	return ti;
 	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 */
 /* thread information allocation */
 #define alloc_thread_info(tsk) \
 #define alloc_thread_info(tsk) \
 	((struct thread_info *) __get_free_pages(GFP_KERNEL, \
 	((struct thread_info *) __get_free_pages(GFP_KERNEL, \
 						 CONFIG_KERNEL_STACK_ORDER))
 						 CONFIG_KERNEL_STACK_ORDER))
+#endif
+
 #define free_thread_info(ti) \
 #define free_thread_info(ti) \
 	free_pages((unsigned long)(ti),CONFIG_KERNEL_STACK_ORDER)
 	free_pages((unsigned long)(ti),CONFIG_KERNEL_STACK_ORDER)
 
 

+ 29 - 0
kernel/exit.c

@@ -858,6 +858,34 @@ static void exit_notify(struct task_struct *tsk)
 		release_task(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)
 fastcall NORET_TYPE void do_exit(long code)
 {
 {
 	struct task_struct *tsk = current;
 	struct task_struct *tsk = current;
@@ -949,6 +977,7 @@ fastcall NORET_TYPE void do_exit(long code)
 	exit_sem(tsk);
 	exit_sem(tsk);
 	__exit_files(tsk);
 	__exit_files(tsk);
 	__exit_fs(tsk);
 	__exit_fs(tsk);
+	check_stack_usage();
 	exit_thread();
 	exit_thread();
 	cpuset_exit(tsk);
 	cpuset_exit(tsk);
 	exit_keys(tsk);
 	exit_keys(tsk);