|
@@ -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);
|