wchan in SHIFT+SCROLL_LOCK

Andrea Arcangeli (andrea@e-mind.com)
Tue, 10 Nov 1998 21:40:15 +0100 (CET)


This patch shows the right EIP of the sleeping process in the kernel in
the SHIFT+SCROLL_LOCK output. I don' t know what esp[3] was for but I
think it' s more useful the wchan information there...

Works fine on i386 and breaks _all_ other arch of course.

All other archs should implement their own get_wchan() specific functions.

Index: linux/arch/i386/kernel/process.c
diff -u linux/arch/i386/kernel/process.c:1.1.1.2 linux/arch/i386/kernel/process.c:1.1.1.2.4.1
--- linux/arch/i386/kernel/process.c:1.1.1.2 Fri Oct 9 17:39:01 1998
+++ linux/arch/i386/kernel/process.c Tue Nov 10 21:33:17 1998
@@ -751,6 +751,41 @@
}
}

+/*
+ * These bracket the sleeping functions..
+ */
+extern void scheduling_functions_start_here(void);
+extern void scheduling_functions_end_here(void);
+#define first_sched ((unsigned long) scheduling_functions_start_here)
+#define last_sched ((unsigned long) scheduling_functions_end_here)
+
+unsigned long get_wchan(struct task_struct *p)
+{
+ if (!p || p == current || p->state == TASK_RUNNING)
+ return 0;
+ {
+ unsigned long ebp, esp, eip;
+ unsigned long stack_page;
+ int count = 0;
+
+ stack_page = (unsigned long)p;
+ esp = p->tss.esp;
+ if (esp < stack_page || esp >= 8188+stack_page)
+ return 0;
+ /* include/asm-i386/system.h:switch_to() pushes ebp last. */
+ ebp = *(unsigned long *) esp;
+ do {
+ if (ebp < stack_page || ebp >= 8188+stack_page)
+ return 0;
+ eip = *(unsigned long *) (ebp+4);
+ if (eip < first_sched || eip >= last_sched)
+ return eip;
+ ebp = *(unsigned long *) ebp;
+ } while (count++ < 16);
+ }
+ return 0;
+}
+
asmlinkage int sys_fork(struct pt_regs regs)
{
return do_fork(SIGCHLD, regs.esp, &regs);
Index: linux/kernel/sched.c
diff -u linux/kernel/sched.c:1.1.1.4 linux/kernel/sched.c:1.1.1.1.16.14
--- linux/kernel/sched.c:1.1.1.4 Sun Nov 8 02:38:59 1998
+++ linux/kernel/sched.c Tue Nov 10 21:33:26 1998
@@ -40,6 +40,7 @@
#include <asm/pgtable.h>
#include <asm/mmu_context.h>
#include <asm/spinlock.h>
+#include <asm/processor.h> /* for get_wchan() */

#include <linux/timex.h>

@@ -1662,16 +1667,18 @@
else
printk(" ");
#if (BITS_PER_LONG == 32)
- if (p == current)
- printk(" current ");
- else
- printk(" %08lX ", thread_saved_pc(&p->tss));
-#else
+#define current_string " current "
+#define wchan_string " %08lX "
+#else /* 64bit archs */
+#define current_string " current task "
+#define wchan_string " %016lx "
+#endif
if (p == current)
- printk(" current task ");
+ printk(current_string);
else
- printk(" %016lx ", thread_saved_pc(&p->tss));
-#endif
+ printk(wchan_string, get_wchan(p));
+#undef current_string
+#undef wchan_string
{
unsigned long * n = (unsigned long *) (p+1);
while (!*n)
Index: linux/include/asm-i386/processor.h
diff -u linux/include/asm-i386/processor.h:1.1.1.2 linux/include/asm-i386/processor.h:1.1.1.2.4.1
--- linux/include/asm-i386/processor.h:1.1.1.2 Fri Oct 9 17:43:12 1998
+++ linux/include/asm-i386/processor.h Tue Nov 10 21:33:39 1998
@@ -304,11 +304,7 @@
/*
* Return saved PC of a blocked thread.
*/
-extern inline unsigned long thread_saved_pc(struct thread_struct *t)
-{
- return ((unsigned long *)t->esp)[3];
-}
-
+extern unsigned long get_wchan(struct task_struct *p);
extern struct task_struct * alloc_task_struct(void);
extern void free_task_struct(struct task_struct *);

Index: linux/fs/proc/array.c
diff -u linux/fs/proc/array.c:1.1.1.4 linux/fs/proc/array.c:1.1.1.2.4.3
--- linux/fs/proc/array.c:1.1.1.4 Wed Nov 4 13:08:23 1998
+++ linux/fs/proc/array.c Tue Nov 10 21:35:09 1998
@@ -62,6 +62,7 @@
#include <asm/uaccess.h>
#include <asm/pgtable.h>
#include <asm/io.h>
+#include <asm/processor.h> /* for get_wchan() */

#define LOAD_INT(x) ((x) >> FSHIFT)
#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
@@ -471,6 +472,7 @@
return get_array(p, p->mm->arg_start, p->mm->arg_end, buffer);
}

+#if 0 /* this should be moved in linux/arch/... */
/*
* These bracket the sleeping functions..
*/
@@ -589,6 +591,7 @@
#endif
return 0;
}
+#endif

#if defined(__i386__)
# define KSTK_EIP(tsk) (((unsigned long *)(4096+(unsigned long)(tsk)))[1019])

Andrea Arcangeli

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/