patch-1.3.37 linux/fs/proc/array.c
Next file: linux/fs/umsdos/dir.c
Previous file: linux/drivers/sound/soundcard.c
Back to the patch index
Back to the overall index
- Lines: 108
- Date:
Tue Oct 24 16:19:41 1995
- Orig file:
v1.3.36/linux/fs/proc/array.c
- Orig date:
Mon Oct 23 18:02:18 1995
diff -u --recursive --new-file v1.3.36/linux/fs/proc/array.c linux/fs/proc/array.c
@@ -373,32 +373,65 @@
static unsigned long get_wchan(struct task_struct *p)
{
-#ifdef __i386__
- unsigned long ebp, eip;
- unsigned long stack_page;
- int count = 0;
-
if (!p || p == current || p->state == TASK_RUNNING)
return 0;
- stack_page = p->kernel_stack_page;
- if (!stack_page)
- return 0;
- ebp = p->tss.ebp;
- do {
- if (ebp < stack_page || ebp >= 4092+stack_page)
+#if defined(__i386__)
+ {
+ unsigned long ebp, eip;
+ unsigned long stack_page;
+ int count = 0;
+
+ stack_page = p->kernel_stack_page;
+ if (!stack_page)
return 0;
- eip = *(unsigned long *) (ebp+4);
- if ((void *)eip != sleep_on &&
- (void *)eip != interruptible_sleep_on)
- return eip;
- ebp = *(unsigned long *) ebp;
- } while (count++ < 16);
+ ebp = p->tss.ebp;
+ do {
+ if (ebp < stack_page || ebp >= 4092+stack_page)
+ return 0;
+ eip = *(unsigned long *) (ebp+4);
+ if ((void *)eip != sleep_on &&
+ (void *)eip != interruptible_sleep_on)
+ return eip;
+ ebp = *(unsigned long *) ebp;
+ } while (count++ < 16);
+ }
+#elif defined(__alpha__)
+ /*
+ * This one depends on the frame size of schedule(). Do a
+ * "disass schedule" in gdb to find the frame size. Also, the
+ * code assumes that sleep_on() follows immediately after
+ * interruptible_sleep_on() and that add_timer() follows
+ * immediately after interruptible_sleep(). Ugly, isn't it?
+ * Maybe adding a wchan field to task_struct would be better,
+ * after all...
+ */
+ {
+ unsigned long schedule_frame;
+ unsigned long pc;
+
+ pc = thread_saved_pc(&p->tss);
+ if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) {
+ schedule_frame = ((unsigned long *)p->tss.ksp)[6];
+ return ((unsigned long *)schedule_frame)[12];
+ }
+ return pc;
+ }
#endif
return 0;
}
-#define KSTK_EIP(stack) (((unsigned long *)stack)[1019])
-#define KSTK_ESP(stack) (((unsigned long *)stack)[1022])
+#if defined(__i386__)
+# define KSTK_EIP(tsk) (((unsigned long *)tsk->kernel_stack_page)[1019])
+# define KSTK_ESP(tsk) (((unsigned long *)tsk->kernel_stack_page)[1022])
+#elif defined(__alpha__)
+ /*
+ * See arch/alpha/kernel/ptrace.c for details.
+ */
+# define PT_REG(reg) (PAGE_SIZE - sizeof(struct pt_regs) \
+ + (long)&((struct pt_regs *)0)->reg)
+# define KSTK_EIP(tsk) (*(unsigned long *)(tsk->kernel_stack_page + PT_REG(pc)))
+# define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->tss.usp)
+#endif
static int get_stat(int pid, char * buffer)
{
@@ -417,13 +450,15 @@
state = "RSDZTD"[tsk->state];
vsize = eip = esp = 0;
if (tsk->mm) {
- vsize = tsk->kernel_stack_page;
- if (vsize) {
- eip = KSTK_EIP(vsize);
- esp = KSTK_ESP(vsize);
- vsize = tsk->mm->brk - tsk->mm->start_code + PAGE_SIZE-1;
- if (esp)
- vsize += TASK_SIZE - esp;
+ if (tsk->kernel_stack_page) {
+ eip = KSTK_EIP(tsk);
+ esp = KSTK_ESP(tsk);
+ vsize = ( (tsk->mm->end_code - tsk->mm->start_code) /* text */
+ + (tsk->mm->end_data - tsk->mm->start_data) /* data */
+ + (tsk->mm->brk - tsk->mm->start_brk)); /* bss + heap */
+ if (esp) {
+ vsize += tsk->mm->start_stack - esp; /* stack */
+ }
}
}
wchan = get_wchan(tsk);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this