diff options
author | Jeff Dike <jdike@addtoit.com> | 2007-07-16 02:38:48 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-16 12:05:38 -0400 |
commit | e18eecb8b35703a5eea73ee2b45324262029e62c (patch) | |
tree | 8c276ae6633b8116ca366274091b00491fd50bbe /kernel/exit.c | |
parent | 84812217e395f5272eac36856c0a2415d61fe139 (diff) |
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>
Diffstat (limited to 'kernel/exit.c')
-rw-r--r-- | kernel/exit.c | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/kernel/exit.c b/kernel/exit.c index ca6a11b73023..64a5263c8c7b 100644 --- a/kernel/exit.c +++ b/kernel/exit.c | |||
@@ -858,6 +858,34 @@ static void exit_notify(struct task_struct *tsk) | |||
858 | release_task(tsk); | 858 | release_task(tsk); |
859 | } | 859 | } |
860 | 860 | ||
861 | #ifdef CONFIG_DEBUG_STACK_USAGE | ||
862 | static void check_stack_usage(void) | ||
863 | { | ||
864 | static DEFINE_SPINLOCK(low_water_lock); | ||
865 | static int lowest_to_date = THREAD_SIZE; | ||
866 | unsigned long *n = end_of_stack(current); | ||
867 | unsigned long free; | ||
868 | |||
869 | while (*n == 0) | ||
870 | n++; | ||
871 | free = (unsigned long)n - (unsigned long)end_of_stack(current); | ||
872 | |||
873 | if (free >= lowest_to_date) | ||
874 | return; | ||
875 | |||
876 | spin_lock(&low_water_lock); | ||
877 | if (free < lowest_to_date) { | ||
878 | printk(KERN_WARNING "%s used greatest stack depth: %lu bytes " | ||
879 | "left\n", | ||
880 | current->comm, free); | ||
881 | lowest_to_date = free; | ||
882 | } | ||
883 | spin_unlock(&low_water_lock); | ||
884 | } | ||
885 | #else | ||
886 | static inline void check_stack_usage(void) {} | ||
887 | #endif | ||
888 | |||
861 | fastcall NORET_TYPE void do_exit(long code) | 889 | fastcall NORET_TYPE void do_exit(long code) |
862 | { | 890 | { |
863 | struct task_struct *tsk = current; | 891 | struct task_struct *tsk = current; |
@@ -949,6 +977,7 @@ fastcall NORET_TYPE void do_exit(long code) | |||
949 | exit_sem(tsk); | 977 | exit_sem(tsk); |
950 | __exit_files(tsk); | 978 | __exit_files(tsk); |
951 | __exit_fs(tsk); | 979 | __exit_fs(tsk); |
980 | check_stack_usage(); | ||
952 | exit_thread(); | 981 | exit_thread(); |
953 | cpuset_exit(tsk); | 982 | cpuset_exit(tsk); |
954 | exit_keys(tsk); | 983 | exit_keys(tsk); |