public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* use ELF sections for get_wchan()
@ 2003-11-18  7:44 William Lee Irwin III
  2003-11-18  8:43 ` Russell King
  2003-11-20 20:28 ` Anton Blanchard
  0 siblings, 2 replies; 10+ messages in thread
From: William Lee Irwin III @ 2003-11-18  7:44 UTC (permalink / raw)
  To: linux-kernel

I noticed a bunch of "FIXME: this depends on the order of these
functions" comments in/around wchan calculations.

So I decided I'd remove the dependency on the order of the functions by
dumping them all into an ELF section with clear delimiters.


-- wli


diff -prauN linux-2.6.0-test9-bk22/arch/alpha/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/alpha/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/alpha/kernel/process.c	2003-10-25 11:44:37.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/alpha/kernel/process.c	2003-11-17 23:20:01.000000000 -0800
@@ -513,11 +513,6 @@ thread_saved_pc(task_t *t)
 /*
  * 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)
 {
@@ -536,7 +531,8 @@ get_wchan(struct task_struct *p)
 	 */
 
 	pc = thread_saved_pc(p);
-	if (pc >= first_sched && pc < last_sched) {
+	if (pc >= scheduling_functions_start_here &&
+			pc < scheduling_functions_end_here) {
 		schedule_frame = ((unsigned long *)p->thread_info->pcb.ksp)[6];
 		return ((unsigned long *)schedule_frame)[12];
 	}
diff -prauN linux-2.6.0-test9-bk22/arch/alpha/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/alpha/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/alpha/kernel/vmlinux.lds.S	2003-10-25 11:43:42.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/alpha/kernel/vmlinux.lds.S	2003-11-17 23:12:42.000000000 -0800
@@ -17,6 +17,9 @@ SECTIONS
   _text = .;					/* Text and read-only data */
   .text : { 
 	*(.text) 
+	__scheduling_functions_start_here = .;
+	*(.text.sched)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
   } :kernel
diff -prauN linux-2.6.0-test9-bk22/arch/arm/boot/compressed/vmlinux.lds.in wchan-2.6.0-test9-bk22-1/arch/arm/boot/compressed/vmlinux.lds.in
--- linux-2.6.0-test9-bk22/arch/arm/boot/compressed/vmlinux.lds.in	2003-10-25 11:43:32.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/arm/boot/compressed/vmlinux.lds.in	2003-11-17 23:14:03.000000000 -0800
@@ -21,6 +21,9 @@ SECTIONS
     _start = .;
     *(.start)
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.text.sched)
+    __scheduling_functions_end_here = .;
     *(.fixup)
     *(.gnu.warning)
     *(.rodata)
diff -prauN linux-2.6.0-test9-bk22/arch/arm/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/arm/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/arm/kernel/process.c	2003-10-25 11:44:41.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/arm/kernel/process.c	2003-11-17 23:20:24.000000000 -0800
@@ -415,11 +415,6 @@ pid_t kernel_thread(int (*fn)(void *), v
 /*
  * 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)
 {
 	unsigned long fp, lr;
@@ -434,7 +429,8 @@ unsigned long get_wchan(struct task_stru
 		if (fp < stack_page || fp > 4092+stack_page)
 			return 0;
 		lr = pc_pointer (((unsigned long *)fp)[-1]);
-		if (lr < first_sched || lr > last_sched)
+		if (lr < scheduling_functions_start_here ||
+				lr > scheduling_functions_end_here)
 			return lr;
 		fp = *(unsigned long *) (fp - 12);
 	} while (count ++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/arm/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/arm/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/arm/kernel/vmlinux.lds.S	2003-10-25 11:43:22.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/arm/kernel/vmlinux.lds.S	2003-11-17 23:13:36.000000000 -0800
@@ -73,6 +73,9 @@ SECTIONS
 	.text : {			/* Real text segment		*/
 		_text = .;		/* Text and read-only data	*/
 			*(.text)
+			__scheduling_functions_start_here = .;
+			*(.text.sched)
+			__scheduling_functions_end_here = .;
 			*(.fixup)
 			*(.gnu.warning)
 			*(.rodata)
diff -prauN linux-2.6.0-test9-bk22/arch/arm26/boot/compressed/vmlinux.lds.in wchan-2.6.0-test9-bk22-1/arch/arm26/boot/compressed/vmlinux.lds.in
--- linux-2.6.0-test9-bk22/arch/arm26/boot/compressed/vmlinux.lds.in	2003-10-25 11:42:57.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/arm26/boot/compressed/vmlinux.lds.in	2003-11-17 23:09:47.000000000 -0800
@@ -21,6 +21,9 @@ SECTIONS
     _start = .;
     *(.start)
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.text.sched)
+    __scheduling_functions_end_here = .;
     *(.fixup)
     *(.gnu.warning)
     *(.rodata)
diff -prauN linux-2.6.0-test9-bk22/arch/arm26/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/arm26/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/arm26/kernel/process.c	2003-10-25 11:44:39.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/arm26/kernel/process.c	2003-11-17 23:20:47.000000000 -0800
@@ -400,11 +400,6 @@ pid_t kernel_thread(int (*fn)(void *), v
 /*
  * 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)
 {
 	unsigned long fp, lr;
@@ -419,7 +414,8 @@ unsigned long get_wchan(struct task_stru
 		if (fp < stack_page || fp > 4092+stack_page)
 			return 0;
 		lr = pc_pointer (((unsigned long *)fp)[-1]);
-		if (lr < first_sched || lr > last_sched)
+		if (lr < scheduling_functions_start_here ||
+				lr > scheduling_functions_end_here)
 			return lr;
 		fp = *(unsigned long *) (fp - 12);
 	} while (count ++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/arm26/kernel/vmlinux-arm26-xip.lds.in wchan-2.6.0-test9-bk22-1/arch/arm26/kernel/vmlinux-arm26-xip.lds.in
--- linux-2.6.0-test9-bk22/arch/arm26/kernel/vmlinux-arm26-xip.lds.in	2003-10-25 11:44:34.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/arm26/kernel/vmlinux-arm26-xip.lds.in	2003-11-17 23:11:07.000000000 -0800
@@ -66,6 +66,9 @@ SECTIONS
 	.text : {			/* Real text segment		*/
 		_text = .;		/* Text and read-only data	*/
 			*(.text)
+			__scheduling_functions_start_here = .;
+			*(.text.sched)
+			__scheduling_functions_end_here = .;
 			*(.fixup)
 			*(.gnu.warning)
 			*(.rodata)
diff -prauN linux-2.6.0-test9-bk22/arch/arm26/kernel/vmlinux-arm26.lds.in wchan-2.6.0-test9-bk22-1/arch/arm26/kernel/vmlinux-arm26.lds.in
--- linux-2.6.0-test9-bk22/arch/arm26/kernel/vmlinux-arm26.lds.in	2003-10-25 11:42:56.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/arm26/kernel/vmlinux-arm26.lds.in	2003-11-17 23:10:18.000000000 -0800
@@ -67,6 +67,9 @@ SECTIONS
 	.text : {			/* Real text segment		*/
 		_text = .;		/* Text and read-only data	*/
 			*(.text)
+			__scheduling_functions_start_here = .;
+			*(.text.sched)
+			__scheduling_functions_end_here = .;
 			*(.fixup)
 			*(.gnu.warning)
 			*(.rodata)
diff -prauN linux-2.6.0-test9-bk22/arch/cris/arch-v10/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/cris/arch-v10/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/cris/arch-v10/vmlinux.lds.S	2003-10-25 11:43:29.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/cris/arch-v10/vmlinux.lds.S	2003-11-17 23:08:52.000000000 -0800
@@ -25,6 +25,9 @@ SECTIONS
 	__stext = .;
 	.text : {
 		*(.text)
+		__scheduling_functions_start_here = .;
+		*(.text.sched)
+		__scheduling_functions_end_here = .;
 		*(.fixup)
 		*(.text.__*)
 	}
diff -prauN linux-2.6.0-test9-bk22/arch/h8300/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/h8300/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/h8300/kernel/process.c	2003-10-25 11:42:43.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/h8300/kernel/process.c	2003-11-17 23:21:15.000000000 -0800
@@ -264,11 +264,6 @@ out:
 /*
  * 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 thread_saved_pc(struct task_struct *tsk)
 {
 	return ((struct pt_regs *)tsk->thread.esp0)->pc;
@@ -289,8 +284,8 @@ unsigned long get_wchan(struct task_stru
 		    fp >= 8184+stack_page)
 			return 0;
 		pc = ((unsigned long *)fp)[1];
-		/* FIXME: This depends on the order of these functions. */
-		if (pc < first_sched || pc >= last_sched)
+		if (pc < scheduling_functions_start_here ||
+				pc >= scheduling_functions_end_here)
 			return pc;
 		fp = *(unsigned long *) fp;
 	} while (count++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/h8300/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/h8300/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/h8300/kernel/vmlinux.lds.S	2003-10-25 11:43:54.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/h8300/kernel/vmlinux.lds.S	2003-11-17 23:17:49.000000000 -0800
@@ -82,6 +82,9 @@ SECTIONS
 #endif
 	__stext = . ;
         	*(.text)
+	__scheduling_functions_start_here = .;
+		*(.text.sched)
+	__scheduling_functions_end_here = .;
 	. = ALIGN(0x4) ;
 		*(.exit.text)
 		*(.text.*)
diff -prauN linux-2.6.0-test9-bk22/arch/i386/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/i386/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/i386/kernel/process.c	2003-10-25 11:42:40.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/i386/kernel/process.c	2003-11-17 23:03:54.000000000 -0800
@@ -631,11 +631,6 @@ out:
 /*
  * 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)
 {
 	unsigned long ebp, esp, eip;
@@ -653,14 +648,13 @@ unsigned long get_wchan(struct task_stru
 		if (ebp < stack_page || ebp > 8184+stack_page)
 			return 0;
 		eip = *(unsigned long *) (ebp+4);
-		if (eip < first_sched || eip >= last_sched)
+		if (eip < scheduling_functions_start_here ||
+				eip >= scheduling_functions_end_here)
 			return eip;
 		ebp = *(unsigned long *) ebp;
 	} while (count++ < 16);
 	return 0;
 }
-#undef last_sched
-#undef first_sched
 
 /*
  * sys_alloc_thread_area: get a yet unused TLS descriptor index.
diff -prauN linux-2.6.0-test9-bk22/arch/i386/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/i386/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/i386/kernel/vmlinux.lds.S	2003-10-25 11:43:05.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/i386/kernel/vmlinux.lds.S	2003-11-17 23:01:42.000000000 -0800
@@ -15,6 +15,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.text.sched)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x9090
diff -prauN linux-2.6.0-test9-bk22/arch/ia64/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/ia64/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/ia64/kernel/process.c	2003-10-25 11:43:35.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/ia64/kernel/process.c	2003-11-17 23:31:04.000000000 -0800
@@ -638,11 +638,6 @@ get_wchan (struct task_struct *p)
 	/*
 	 * 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)
-
 	/*
 	 * Note: p may not be a blocked task (it could be current or
 	 * another process running on some other CPU.  Rather than
@@ -656,12 +651,11 @@ get_wchan (struct task_struct *p)
 		if (unw_unwind(&info) < 0)
 			return 0;
 		unw_get_ip(&info, &ip);
-		if (ip < first_sched || ip >= last_sched)
+		if (ip < scheduling_functions_start_here ||
+				ip >= scheduling_functions_end_here)
 			return ip;
 	} while (count++ < 16);
 	return 0;
-#	undef first_sched
-#	undef last_sched
 }
 
 void
diff -prauN linux-2.6.0-test9-bk22/arch/ia64/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/ia64/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/ia64/kernel/vmlinux.lds.S	2003-10-25 11:44:35.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/ia64/kernel/vmlinux.lds.S	2003-11-17 23:12:13.000000000 -0800
@@ -35,6 +35,9 @@ SECTIONS
     {
 	*(.text.ivt)
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.text.sched)
+	__scheduling_functions_end_here = .;
 	*(.gnu.linkonce.t*)
     }
   .text2 : AT(ADDR(.text2) - LOAD_OFFSET)
diff -prauN linux-2.6.0-test9-bk22/arch/m68k/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/m68k/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/m68k/kernel/process.c	2003-10-25 11:45:04.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/m68k/kernel/process.c	2003-11-17 23:22:49.000000000 -0800
@@ -65,12 +65,10 @@ asmlinkage void ret_from_fork(void);
  */
 unsigned long thread_saved_pc(struct task_struct *tsk)
 {
-	extern void scheduling_functions_start_here(void);
-	extern void scheduling_functions_end_here(void);
 	struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
 	/* Check whether the thread is blocked in resume() */
-	if (sw->retpc > (unsigned long)scheduling_functions_start_here &&
-	    sw->retpc < (unsigned long)scheduling_functions_end_here)
+	if (sw->retpc > scheduling_functions_start_here &&
+	    sw->retpc < scheduling_functions_end_here)
 		return ((unsigned long *)sw->a6)[1];
 	else
 		return sw->retpc;
@@ -387,11 +385,6 @@ out:
 /*
  * 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)
 {
 	unsigned long fp, pc;
@@ -407,8 +400,8 @@ unsigned long get_wchan(struct task_stru
 		    fp >= 8184+stack_page)
 			return 0;
 		pc = ((unsigned long *)fp)[1];
-		/* FIXME: This depends on the order of these functions. */
-		if (pc < first_sched || pc >= last_sched)
+		if (pc < scheduling_functions_start_here ||
+				pc >= scheduling_functions_end_here)
 			return pc;
 		fp = *(unsigned long *) fp;
 	} while (count++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/m68k/kernel/vmlinux-std.lds wchan-2.6.0-test9-bk22-1/arch/m68k/kernel/vmlinux-std.lds
--- linux-2.6.0-test9-bk22/arch/m68k/kernel/vmlinux-std.lds	2003-10-25 11:44:39.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/m68k/kernel/vmlinux-std.lds	2003-11-17 23:11:46.000000000 -0800
@@ -12,6 +12,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.text.sched)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x4e75
diff -prauN linux-2.6.0-test9-bk22/arch/m68k/kernel/vmlinux-sun3.lds wchan-2.6.0-test9-bk22-1/arch/m68k/kernel/vmlinux-sun3.lds
--- linux-2.6.0-test9-bk22/arch/m68k/kernel/vmlinux-sun3.lds	2003-10-25 11:42:41.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/m68k/kernel/vmlinux-sun3.lds	2003-11-17 23:11:27.000000000 -0800
@@ -13,6 +13,9 @@ SECTIONS
   .text : {
 	*(.head)
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.text.sched)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x4e75
diff -prauN linux-2.6.0-test9-bk22/arch/m68knommu/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/m68knommu/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/m68knommu/kernel/process.c	2003-10-25 11:43:07.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/m68knommu/kernel/process.c	2003-11-17 23:23:27.000000000 -0800
@@ -406,11 +406,6 @@ out:
 /*
  * 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)
 {
 	unsigned long fp, pc;
@@ -426,8 +421,8 @@ unsigned long get_wchan(struct task_stru
 		    fp >= 8184+stack_page)
 			return 0;
 		pc = ((unsigned long *)fp)[1];
-		/* FIXME: This depends on the order of these functions. */
-		if (pc < first_sched || pc >= last_sched)
+		if (pc < scheduling_functions_start_here ||
+				pc >= scheduling_functions_end_here)
 			return pc;
 		fp = *(unsigned long *) fp;
 	} while (count++ < 16);
@@ -439,13 +434,11 @@ unsigned long get_wchan(struct task_stru
  */
 unsigned long thread_saved_pc(struct task_struct *tsk)
 {
-	extern void scheduling_functions_start_here(void);
-	extern void scheduling_functions_end_here(void);
 	struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
 
 	/* Check whether the thread is blocked in resume() */
-	if (sw->retpc > (unsigned long)scheduling_functions_start_here &&
-	    sw->retpc < (unsigned long)scheduling_functions_end_here)
+	if (sw->retpc > scheduling_functions_start_here &&
+	    sw->retpc < scheduling_functions_end_here)
 		return ((unsigned long *)sw->a6)[1];
 	else
 		return sw->retpc;
diff -prauN linux-2.6.0-test9-bk22/arch/m68knommu/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/m68knommu/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/m68knommu/kernel/vmlinux.lds.S	2003-10-25 11:43:29.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/m68knommu/kernel/vmlinux.lds.S	2003-11-17 23:05:24.000000000 -0800
@@ -191,6 +191,9 @@ SECTIONS {
 	.text : {
 		_stext = . ;
         	*(.text)
+		__scheduling_functions_start_here = .;
+		*(.text.sched)
+		__scheduling_functions_end_here = .;
         	*(.text.lock)
 
 		. = ALIGN(16);          /* Exception table              */
diff -prauN linux-2.6.0-test9-bk22/arch/mips/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/mips/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/mips/kernel/process.c	2003-10-25 11:43:29.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/mips/kernel/process.c	2003-11-17 23:31:29.000000000 -0800
@@ -276,11 +276,6 @@ unsigned long thread_saved_pc(struct tas
 /*
  * 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)
-
 /* get_wchan - a maintenance nightmare^W^Wpain in the ass ...  */
 unsigned long get_wchan(struct task_struct *p)
 {
@@ -292,7 +287,8 @@ unsigned long get_wchan(struct task_stru
 	if (!mips_frame_info_initialized)
 		return 0;
 	pc = thread_saved_pc(p);
-	if (pc < first_sched || pc >= last_sched)
+	if (pc < scheduling_functions_start_here ||
+			pc >= scheduling_functions_end_here)
 		goto out;
 
 	if (pc >= (unsigned long) sleep_on_timeout)
@@ -326,7 +322,8 @@ schedule_timeout_caller:
 	 */
 	pc    = ((unsigned long *)frame)[schedule_timeout_frame.pc_offset];
 
-	if (pc >= first_sched && pc < last_sched) {
+	if (pc >= scheduling_functions_start_here &&
+			pc < scheduling_functions_end_here) {
 		/* schedule_timeout called by [interruptible_]sleep_on_timeout */
 		frame = ((unsigned long *)frame)[schedule_timeout_frame.frame_offset];
 		pc    = ((unsigned long *)frame)[sleep_on_timeout_frame.pc_offset];
diff -prauN linux-2.6.0-test9-bk22/arch/mips/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/mips/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/mips/kernel/vmlinux.lds.S	2003-10-25 11:43:21.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/mips/kernel/vmlinux.lds.S	2003-11-17 23:08:18.000000000 -0800
@@ -27,6 +27,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.text.sched)
+    __scheduling_functions_end_here = .;
     *(.fixup)
     *(.gnu.warning)
   } =0
diff -prauN linux-2.6.0-test9-bk22/arch/parisc/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/parisc/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/parisc/kernel/vmlinux.lds.S	2003-10-25 11:43:05.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/parisc/kernel/vmlinux.lds.S	2003-11-17 23:14:31.000000000 -0800
@@ -24,6 +24,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text BLOCK(16) : {
 	*(.text*)
+	__scheduling_functions_start_here = .;
+	*(.text.sched)
+	__scheduling_functions_end_here =.;
 	*(.PARISC.unwind)
 	*(.fixup)
 	*(.lock.text)		/* out-of-line lock text */
diff -prauN linux-2.6.0-test9-bk22/arch/ppc/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/ppc/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/ppc/kernel/process.c	2003-10-25 11:43:35.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/ppc/kernel/process.c	2003-11-17 23:25:35.000000000 -0800
@@ -650,11 +650,6 @@ void __init ll_puts(const char *s)
 /*
  * 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)
 {
 	unsigned long ip, sp;
@@ -669,7 +664,8 @@ unsigned long get_wchan(struct task_stru
 			return 0;
 		if (count > 0) {
 			ip = *(unsigned long *)(sp + 4);
-			if (ip < first_sched || ip >= last_sched)
+			if (ip < scheduling_functions_start_here ||
+					ip >= scheduling_functions_end_here)
 				return ip;
 		}
 	} while (count++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/ppc/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/ppc/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/ppc/kernel/vmlinux.lds.S	2003-11-17 22:51:23.000000000 -0800
+++ wchan-2.6.0-test9-bk22-1/arch/ppc/kernel/vmlinux.lds.S	2003-11-17 23:07:08.000000000 -0800
@@ -31,6 +31,9 @@ SECTIONS
   .text      :
   {
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.text.sched)
+    __scheduling_functions_end_here = .;
     *(.fixup)
     *(.got1)
     __got2_start = .;
diff -prauN linux-2.6.0-test9-bk22/arch/ppc64/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/ppc64/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/ppc64/kernel/process.c	2003-10-25 11:43:54.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/ppc64/kernel/process.c	2003-11-17 23:26:08.000000000 -0800
@@ -369,11 +369,6 @@ out:
 /*
  * 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)
 {
 	unsigned long ip, sp;
@@ -393,7 +388,8 @@ unsigned long get_wchan(struct task_stru
 			 * XXX we mask the upper 32 bits until procps
 			 * gets fixed.
 			 */
-			if (ip < first_sched || ip >= last_sched)
+			if (ip < scheduling_functions_start_here ||
+					ip >= scheduling_functions_end_here)
 				return (ip & 0xFFFFFFFF);
 		}
 	} while (count++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/ppc64/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/ppc64/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/ppc64/kernel/vmlinux.lds.S	2003-10-25 11:44:15.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/ppc64/kernel/vmlinux.lds.S	2003-11-17 23:13:13.000000000 -0800
@@ -33,6 +33,9 @@ SECTIONS
   .text      :
   {
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.text.sched)
+    __scheduling_functions_end_here = .;
     *(.fixup)
     *(.got1)
   }
diff -prauN linux-2.6.0-test9-bk22/arch/s390/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/s390/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/s390/kernel/process.c	2003-10-25 11:44:17.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/s390/kernel/process.c	2003-11-17 23:26:43.000000000 -0800
@@ -371,11 +371,6 @@ void dump_thread(struct pt_regs * regs, 
 /*
  * 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)
 {
 	unsigned long r14, r15, bc;
@@ -398,12 +393,10 @@ unsigned long get_wchan(struct task_stru
 #else
 		r14 = *(unsigned long *) (bc+112);
 #endif
-		if (r14 < first_sched || r14 >= last_sched)
+		if (r14 < scheduling_functions_start_here ||
+				r14 >= scheduling_functions_end_here)
 			return r14;
 		bc = (*(unsigned long *) bc) & PSW_ADDR_INSN;
 	} while (count++ < 16);
 	return 0;
 }
-#undef last_sched
-#undef first_sched
-
diff -prauN linux-2.6.0-test9-bk22/arch/s390/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/s390/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/s390/kernel/vmlinux.lds.S	2003-10-25 11:43:23.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/s390/kernel/vmlinux.lds.S	2003-11-17 23:18:44.000000000 -0800
@@ -23,6 +23,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.text.sched)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x0700
diff -prauN linux-2.6.0-test9-bk22/arch/sh/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/sh/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/sh/kernel/process.c	2003-10-25 11:44:08.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/sh/kernel/process.c	2003-11-17 23:28:29.000000000 -0800
@@ -375,11 +375,6 @@ out:
 /*
  * 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)
 {
 	unsigned long schedule_frame;
diff -prauN linux-2.6.0-test9-bk22/arch/sh/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/sh/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/sh/kernel/vmlinux.lds.S	2003-10-25 11:43:49.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/sh/kernel/vmlinux.lds.S	2003-11-17 23:09:23.000000000 -0800
@@ -22,6 +22,9 @@ SECTIONS
 	} = 0
   .text : {
 	*(.text)
+	__scheduling_functions_start_here =.;
+	*(.text.sched)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x0009
diff -prauN linux-2.6.0-test9-bk22/arch/sparc/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/sparc/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/sparc/kernel/process.c	2003-10-25 11:43:00.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/sparc/kernel/process.c	2003-11-17 23:29:13.000000000 -0800
@@ -692,9 +692,6 @@ pid_t kernel_thread(int (*fn)(void *), v
 	return retval;
 }
 
-extern void scheduling_functions_start_here(void);
-extern void scheduling_functions_end_here(void);
-
 unsigned long get_wchan(struct task_struct *task)
 {
 	unsigned long pc, fp, bias = 0;
@@ -715,8 +712,8 @@ unsigned long get_wchan(struct task_stru
 			break;
 		rw = (struct reg_window *) fp;
 		pc = rw->ins[7];
-		if (pc < ((unsigned long) scheduling_functions_start_here) ||
-                    pc >= ((unsigned long) scheduling_functions_end_here)) {
+		if (pc < scheduling_functions_start_here ||
+                    pc >= scheduling_functions_end_here) {
 			ret = pc;
 			goto out;
 		}
diff -prauN linux-2.6.0-test9-bk22/arch/sparc/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/sparc/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/sparc/kernel/vmlinux.lds.S	2003-10-25 11:42:53.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/sparc/kernel/vmlinux.lds.S	2003-11-17 23:06:33.000000000 -0800
@@ -12,6 +12,9 @@ SECTIONS
   .text 0xf0004000 :
   {
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.text.sched)
+    __scheduling_functions_end_here = .;
     *(.gnu.warning)
   } =0
   _etext = .;
diff -prauN linux-2.6.0-test9-bk22/arch/sparc64/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/sparc64/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/sparc64/kernel/process.c	2003-10-25 11:43:30.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/sparc64/kernel/process.c	2003-11-17 23:29:28.000000000 -0800
@@ -824,9 +824,6 @@ out:
 	return error;
 }
 
-extern void scheduling_functions_start_here(void);
-extern void scheduling_functions_end_here(void);
-
 unsigned long get_wchan(struct task_struct *task)
 {
 	unsigned long pc, fp, bias = 0;
@@ -850,8 +847,8 @@ unsigned long get_wchan(struct task_stru
 			break;
 		rw = (struct reg_window *) fp;
 		pc = rw->ins[7];
-		if (pc < ((unsigned long) scheduling_functions_start_here) ||
-		    pc >= ((unsigned long) scheduling_functions_end_here)) {
+		if (pc < scheduling_functions_start_here ||
+		    pc >= scheduling_functions_end_here) {
 			ret = pc;
 			goto out;
 		}
diff -prauN linux-2.6.0-test9-bk22/arch/sparc64/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/sparc64/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/sparc64/kernel/vmlinux.lds.S	2003-10-25 11:44:36.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/sparc64/kernel/vmlinux.lds.S	2003-11-17 23:06:07.000000000 -0800
@@ -15,6 +15,9 @@ SECTIONS
   .text 0x0000000000404000 :
   {
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.text.sched)
+    __scheduling_functions_end_here = .;
     *(.gnu.warning)
   } =0
   _etext = .;
diff -prauN linux-2.6.0-test9-bk22/arch/v850/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/v850/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/v850/kernel/process.c	2003-10-25 11:43:02.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/v850/kernel/process.c	2003-11-17 23:32:14.000000000 -0800
@@ -203,11 +203,6 @@ int sys_execve (char *name, char **argv,
 /*
  * 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 0  /* Barf.  Figure out the stack-layout later.  XXX  */
@@ -221,15 +216,16 @@ unsigned long get_wchan (struct task_str
 
 	/* This quite disgusting function walks up the stack, following
 	   saved return address, until it something that's out of bounds
-	   (as defined by `first_sched' and `last_sched').  It then
-	   returns the last PC that was in-bounds.  */
+	   (as defined by `scheduling_functions_start_here' and
+	   `scheduling_functions_end_here').  It then returns the last
+	   PC that was in-bounds.  */
 	do {
 		if (fp < stack_page + sizeof (struct task_struct) ||
 		    fp >= 8184+stack_page)
 			return 0;
 		pc = ((unsigned long *)fp)[1];
-		/* FIXME: This depends on the order of these functions. */
-		if (pc < first_sched || pc >= last_sched)
+		if (pc < scheduling_functions_start_here ||
+				pc >= scheduling_functions_end_here)
 			return pc;
 		fp = *(unsigned long *) fp;
 	} while (count++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/v850/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/v850/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/v850/kernel/vmlinux.lds.S	2003-10-25 11:43:58.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/v850/kernel/vmlinux.lds.S	2003-11-17 23:18:13.000000000 -0800
@@ -64,6 +64,9 @@
 #define TEXT_CONTENTS							      \
 		__stext = . ;						      \
         	*(.text)						      \
+		__scheduling_functions_start_here = .;
+		*(.text.sched)
+		__scheduling_functions_end_here = .;
 			*(.exit.text)	/* 2.5 convention */		      \
 			*(.text.exit)	/* 2.4 convention */		      \
 			*(.text.lock)					      \
diff -prauN linux-2.6.0-test9-bk22/arch/x86_64/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/x86_64/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/x86_64/kernel/process.c	2003-10-25 11:43:49.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/x86_64/kernel/process.c	2003-11-17 23:30:38.000000000 -0800
@@ -528,11 +528,6 @@ asmlinkage long sys_vfork(struct pt_regs
 /*
  * 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)
 {
 	u64 fp,rip;
@@ -547,14 +542,13 @@ unsigned long get_wchan(struct task_stru
 		if (fp < (unsigned long)p || fp > (unsigned long)p+THREAD_SIZE)
 			return 0; 
 		rip = *(u64 *)(fp+8); 
-		if (rip < first_sched || rip >= last_sched)
+		if (rip < scheduling_functions_start_here ||
+				rip >= scheduling_functions_end_here)
 			return rip; 
 		fp = *(u64 *)fp; 
 	} while (count++ < 16); 
 	return 0;
 }
-#undef last_sched
-#undef first_sched
 
 long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
 { 
diff -prauN linux-2.6.0-test9-bk22/arch/x86_64/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/x86_64/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/x86_64/kernel/vmlinux.lds.S	2003-10-25 11:42:51.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/x86_64/kernel/vmlinux.lds.S	2003-11-17 23:14:54.000000000 -0800
@@ -14,6 +14,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.text.sched)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x9090
diff -prauN linux-2.6.0-test9-bk22/include/linux/init.h wchan-2.6.0-test9-bk22-1/include/linux/init.h
--- linux-2.6.0-test9-bk22/include/linux/init.h	2003-10-25 11:42:50.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/include/linux/init.h	2003-11-17 23:01:42.000000000 -0800
@@ -45,6 +45,8 @@
 #define __exitdata	__attribute__ ((__section__(".exit.data")))
 #define __exit_call	__attribute_used__ __attribute__ ((__section__ (".exitcall.exit")))
 
+#define __sched		__attribute__((__section__(".text.sched")))
+
 #ifdef MODULE
 #define __exit		__attribute__ ((__section__(".exit.text")))
 #else
diff -prauN linux-2.6.0-test9-bk22/include/linux/sched.h wchan-2.6.0-test9-bk22-1/include/linux/sched.h
--- linux-2.6.0-test9-bk22/include/linux/sched.h	2003-11-17 22:51:24.000000000 -0800
+++ wchan-2.6.0-test9-bk22-1/include/linux/sched.h	2003-11-17 23:01:42.000000000 -0800
@@ -169,6 +169,8 @@ extern void update_one_process(struct ta
 			       unsigned long system, int cpu);
 extern void scheduler_tick(int user_tick, int system);
 extern unsigned long cache_decay_ticks;
+extern const unsigned long scheduling_functions_start_here;
+extern const unsigned long scheduling_functions_end_here;
 
 
 #define	MAX_SCHEDULE_TIMEOUT	LONG_MAX
diff -prauN linux-2.6.0-test9-bk22/kernel/sched.c wchan-2.6.0-test9-bk22-1/kernel/sched.c
--- linux-2.6.0-test9-bk22/kernel/sched.c	2003-11-17 22:51:24.000000000 -0800
+++ wchan-2.6.0-test9-bk22-1/kernel/sched.c	2003-11-17 23:01:42.000000000 -0800
@@ -221,6 +221,13 @@ static DEFINE_PER_CPU(struct runqueue, r
 #define task_rq(p)		cpu_rq(task_cpu(p))
 #define cpu_curr(cpu)		(cpu_rq(cpu)->curr)
 
+extern unsigned long __scheduling_functions_start_here;
+extern unsigned long __scheduling_functions_end_here;
+const unsigned long scheduling_functions_start_here =
+			(unsigned long)&__scheduling_functions_start_here;
+const unsigned long scheduling_functions_end_here =
+			(unsigned long)&__scheduling_functions_end_here;
+
 /*
  * Default context-switch locking:
  */
@@ -1463,12 +1470,10 @@ out:
 	rebalance_tick(rq, 0);
 }
 
-void scheduling_functions_start_here(void) { }
-
 /*
  * schedule() is the main scheduler function.
  */
-asmlinkage void schedule(void)
+asmlinkage __sched void schedule(void)
 {
 	task_t *prev, *next;
 	runqueue_t *rq;
@@ -1611,7 +1616,7 @@ EXPORT_SYMBOL(schedule);
  * off of preempt_enable.  Kernel preemptions off return from interrupt
  * occur there and call schedule directly.
  */
-asmlinkage void preempt_schedule(void)
+asmlinkage __sched void preempt_schedule(void)
 {
 	struct thread_info *ti = current_thread_info();
 
@@ -1636,7 +1641,7 @@ need_resched:
 EXPORT_SYMBOL(preempt_schedule);
 #endif /* CONFIG_PREEMPT */
 
-int default_wake_function(wait_queue_t *curr, unsigned mode, int sync)
+__sched int default_wake_function(wait_queue_t *curr, unsigned mode, int sync)
 {
 	task_t *p = curr->task;
 	return try_to_wake_up(p, mode, sync);
@@ -1653,7 +1658,7 @@ EXPORT_SYMBOL(default_wake_function);
  * started to run but is not in state TASK_RUNNING.  try_to_wake_up() returns
  * zero in this (rare) case, and we handle it by continuing to scan the queue.
  */
-static void __wake_up_common(wait_queue_head_t *q, unsigned int mode, int nr_exclusive, int sync)
+static __sched void __wake_up_common(wait_queue_head_t *q, unsigned int mode, int nr_exclusive, int sync)
 {
 	struct list_head *tmp, *next;
 
@@ -1675,7 +1680,7 @@ static void __wake_up_common(wait_queue_
  * @mode: which threads
  * @nr_exclusive: how many wake-one or wake-many threads to wake up
  */
-void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
+__sched void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
 {
 	unsigned long flags;
 
@@ -1707,7 +1712,7 @@ void __wake_up_locked(wait_queue_head_t 
  *
  * On UP it can prevent extra preemption.
  */
-void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
+__sched void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
 {
 	unsigned long flags;
 
@@ -1724,7 +1729,7 @@ void __wake_up_sync(wait_queue_head_t *q
 
 EXPORT_SYMBOL_GPL(__wake_up_sync);	/* For internal use only */
 
-void complete(struct completion *x)
+__sched void complete(struct completion *x)
 {
 	unsigned long flags;
 
@@ -1736,7 +1741,7 @@ void complete(struct completion *x)
 
 EXPORT_SYMBOL(complete);
 
-void complete_all(struct completion *x)
+__sched void complete_all(struct completion *x)
 {
 	unsigned long flags;
 
@@ -1746,7 +1751,7 @@ void complete_all(struct completion *x)
 	spin_unlock_irqrestore(&x->wait.lock, flags);
 }
 
-void wait_for_completion(struct completion *x)
+__sched void wait_for_completion(struct completion *x)
 {
 	might_sleep();
 	spin_lock_irq(&x->wait.lock);
@@ -1784,7 +1789,7 @@ EXPORT_SYMBOL(wait_for_completion);
 	__remove_wait_queue(q, &wait);				\
 	spin_unlock_irqrestore(&q->lock, flags);
 
-void interruptible_sleep_on(wait_queue_head_t *q)
+__sched void interruptible_sleep_on(wait_queue_head_t *q)
 {
 	SLEEP_ON_VAR
 
@@ -1797,7 +1802,7 @@ void interruptible_sleep_on(wait_queue_h
 
 EXPORT_SYMBOL(interruptible_sleep_on);
 
-long interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
+__sched long interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
 	SLEEP_ON_VAR
 
@@ -1812,7 +1817,7 @@ long interruptible_sleep_on_timeout(wait
 
 EXPORT_SYMBOL(interruptible_sleep_on_timeout);
 
-void sleep_on(wait_queue_head_t *q)
+__sched void sleep_on(wait_queue_head_t *q)
 {
 	SLEEP_ON_VAR
 
@@ -1825,7 +1830,7 @@ void sleep_on(wait_queue_head_t *q)
 
 EXPORT_SYMBOL(sleep_on);
 
-long sleep_on_timeout(wait_queue_head_t *q, long timeout)
+__sched long sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
 	SLEEP_ON_VAR
 
@@ -1840,8 +1845,6 @@ long sleep_on_timeout(wait_queue_head_t 
 
 EXPORT_SYMBOL(sleep_on_timeout);
 
-void scheduling_functions_end_here(void) { }
-
 void set_user_nice(task_t *p, long nice)
 {
 	unsigned long flags;
@@ -2291,7 +2294,7 @@ asmlinkage long sys_sched_yield(void)
 	return 0;
 }
 
-void __cond_resched(void)
+__sched void __cond_resched(void)
 {
 	set_current_state(TASK_RUNNING);
 	schedule();
@@ -2305,7 +2308,7 @@ EXPORT_SYMBOL(__cond_resched);
  * this is a shortcut for kernel-space yielding - it marks the
  * thread runnable and calls sys_sched_yield().
  */
-void yield(void)
+__sched void yield(void)
 {
 	set_current_state(TASK_RUNNING);
 	sys_sched_yield();
@@ -2320,7 +2323,7 @@ EXPORT_SYMBOL(yield);
  * But don't do that if it is a deliberate, throttling IO wait (this task
  * has set its backing_dev_info: the queue against which it should throttle)
  */
-void io_schedule(void)
+__sched void io_schedule(void)
 {
 	struct runqueue *rq = this_rq();
 
@@ -2331,7 +2334,7 @@ void io_schedule(void)
 
 EXPORT_SYMBOL(io_schedule);
 
-long io_schedule_timeout(long timeout)
+__sched long io_schedule_timeout(long timeout)
 {
 	struct runqueue *rq = this_rq();
 	long ret;
@@ -2881,7 +2884,7 @@ EXPORT_SYMBOL(__might_sleep);
  *
  * Called inside preempt_disable().
  */
-void __preempt_spin_lock(spinlock_t *lock)
+__sched void __preempt_spin_lock(spinlock_t *lock)
 {
 	if (preempt_count() > 1) {
 		_raw_spin_lock(lock);
@@ -2897,7 +2900,7 @@ void __preempt_spin_lock(spinlock_t *loc
 
 EXPORT_SYMBOL(__preempt_spin_lock);
 
-void __preempt_write_lock(rwlock_t *lock)
+__sched void __preempt_write_lock(rwlock_t *lock)
 {
 	if (preempt_count() > 1) {
 		_raw_write_lock(lock);
diff -prauN linux-2.6.0-test9-bk22/kernel/timer.c wchan-2.6.0-test9-bk22-1/kernel/timer.c
--- linux-2.6.0-test9-bk22/kernel/timer.c	2003-11-17 22:51:24.000000000 -0800
+++ wchan-2.6.0-test9-bk22-1/kernel/timer.c	2003-11-17 23:01:42.000000000 -0800
@@ -1000,7 +1000,7 @@ static void process_timeout(unsigned lon
  *
  * In all cases the return value is guaranteed to be non-negative.
  */
-signed long schedule_timeout(signed long timeout)
+__sched signed long schedule_timeout(signed long timeout)
 {
 	struct timer_list timer;
 	unsigned long expire;
@@ -1060,7 +1060,7 @@ asmlinkage long sys_gettid(void)
 	return current->pid;
 }
 
-static long nanosleep_restart(struct restart_block *restart)
+static __sched long nanosleep_restart(struct restart_block *restart)
 {
 	unsigned long expire = restart->arg0, now = jiffies;
 	struct timespec *rmtp = (struct timespec *) restart->arg1;

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: use ELF sections for get_wchan()
  2003-11-18  7:44 use ELF sections for get_wchan() William Lee Irwin III
@ 2003-11-18  8:43 ` Russell King
  2003-11-18  8:45   ` William Lee Irwin III
  2003-11-20 20:28 ` Anton Blanchard
  1 sibling, 1 reply; 10+ messages in thread
From: Russell King @ 2003-11-18  8:43 UTC (permalink / raw)
  To: William Lee Irwin III, linux-kernel

A couple of comments on the patch:

> diff -prauN linux-2.6.0-test9-bk22/arch/arm/boot/compressed/vmlinux.lds.in wchan-2.6.0-test9-bk22-1/arch/arm/boot/compressed/vmlinux.lds.in
> --- linux-2.6.0-test9-bk22/arch/arm/boot/compressed/vmlinux.lds.in	2003-10-25 11:43:32.000000000 -0700
> +++ wchan-2.6.0-test9-bk22-1/arch/arm/boot/compressed/vmlinux.lds.in	2003-11-17 23:14:03.000000000 -0800

You don't need to add to this file - this linker script takes the binary
kernel image and puts the necessary decompressor magic around it.

> diff -prauN linux-2.6.0-test9-bk22/arch/arm26/boot/compressed/vmlinux.lds.in wchan-2.6.0-test9-bk22-1/arch/arm26/boot/compressed/vmlinux.lds.in
> --- linux-2.6.0-test9-bk22/arch/arm26/boot/compressed/vmlinux.lds.in	2003-10-25 11:42:57.000000000 -0700
> +++ wchan-2.6.0-test9-bk22-1/arch/arm26/boot/compressed/vmlinux.lds.in	2003-11-17 23:09:47.000000000 -0800

Same again.

-- 
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:  2.6 PCMCIA      - http://pcmcia.arm.linux.org.uk/
                 2.6 Serial core

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: use ELF sections for get_wchan()
  2003-11-18  8:43 ` Russell King
@ 2003-11-18  8:45   ` William Lee Irwin III
  2003-11-18  8:50     ` William Lee Irwin III
  0 siblings, 1 reply; 10+ messages in thread
From: William Lee Irwin III @ 2003-11-18  8:45 UTC (permalink / raw)
  To: linux-kernel

>> diff -prauN linux-2.6.0-test9-bk22/arch/arm/boot/compressed/vmlinux.lds.in wchan-2.6.0-test9-bk22-1/arch/arm/boot/compressed/vmlinux.lds.in
> > --- linux-2.6.0-test9-bk22/arch/arm/boot/compressed/vmlinux.lds.in	2003-10-25 11:43:32.000000000 -0700
> > +++ wchan-2.6.0-test9-bk22-1/arch/arm/boot/compressed/vmlinux.lds.in	2003-11-17 23:14:03.000000000 -0800

On Tue, Nov 18, 2003 at 08:43:36AM +0000, Russell King wrote:
> You don't need to add to this file - this linker script takes the binary
> kernel image and puts the necessary decompressor magic around it.

Aha, thanks. I'll follow up with an amended patch (for both instances).


-- wli

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: use ELF sections for get_wchan()
  2003-11-18  8:45   ` William Lee Irwin III
@ 2003-11-18  8:50     ` William Lee Irwin III
  2003-11-19  3:13       ` William Lee Irwin III
  0 siblings, 1 reply; 10+ messages in thread
From: William Lee Irwin III @ 2003-11-18  8:50 UTC (permalink / raw)
  To: linux-kernel

On Tue, Nov 18, 2003 at 08:43:36AM +0000, Russell King wrote:
>> You don't need to add to this file - this linker script takes the binary
>> kernel image and puts the necessary decompressor magic around it.

On Tue, Nov 18, 2003 at 12:45:29AM -0800, William Lee Irwin III wrote:
> Aha, thanks. I'll follow up with an amended patch (for both instances).

And here it is. I also added a small tweak for the #if 0'd v850 code
(which assumed a 2.4 stack layout; v850's using off-stack task_t's now).


-- wli


diff -prauN linux-2.6.0-test9-bk22/arch/alpha/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/alpha/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/alpha/kernel/process.c	2003-10-25 11:44:37.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/alpha/kernel/process.c	2003-11-17 23:20:01.000000000 -0800
@@ -513,11 +513,6 @@ thread_saved_pc(task_t *t)
 /*
  * 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)
 {
@@ -536,7 +531,8 @@ get_wchan(struct task_struct *p)
 	 */
 
 	pc = thread_saved_pc(p);
-	if (pc >= first_sched && pc < last_sched) {
+	if (pc >= scheduling_functions_start_here &&
+			pc < scheduling_functions_end_here) {
 		schedule_frame = ((unsigned long *)p->thread_info->pcb.ksp)[6];
 		return ((unsigned long *)schedule_frame)[12];
 	}
diff -prauN linux-2.6.0-test9-bk22/arch/alpha/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/alpha/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/alpha/kernel/vmlinux.lds.S	2003-10-25 11:43:42.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/alpha/kernel/vmlinux.lds.S	2003-11-17 23:12:42.000000000 -0800
@@ -17,6 +17,9 @@ SECTIONS
   _text = .;					/* Text and read-only data */
   .text : { 
 	*(.text) 
+	__scheduling_functions_start_here = .;
+	*(.text.sched)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
   } :kernel
diff -prauN linux-2.6.0-test9-bk22/arch/arm/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/arm/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/arm/kernel/process.c	2003-10-25 11:44:41.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/arm/kernel/process.c	2003-11-17 23:20:24.000000000 -0800
@@ -415,11 +415,6 @@ pid_t kernel_thread(int (*fn)(void *), v
 /*
  * 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)
 {
 	unsigned long fp, lr;
@@ -434,7 +429,8 @@ unsigned long get_wchan(struct task_stru
 		if (fp < stack_page || fp > 4092+stack_page)
 			return 0;
 		lr = pc_pointer (((unsigned long *)fp)[-1]);
-		if (lr < first_sched || lr > last_sched)
+		if (lr < scheduling_functions_start_here ||
+				lr > scheduling_functions_end_here)
 			return lr;
 		fp = *(unsigned long *) (fp - 12);
 	} while (count ++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/arm/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/arm/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/arm/kernel/vmlinux.lds.S	2003-10-25 11:43:22.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/arm/kernel/vmlinux.lds.S	2003-11-17 23:13:36.000000000 -0800
@@ -73,6 +73,9 @@ SECTIONS
 	.text : {			/* Real text segment		*/
 		_text = .;		/* Text and read-only data	*/
 			*(.text)
+			__scheduling_functions_start_here = .;
+			*(.text.sched)
+			__scheduling_functions_end_here = .;
 			*(.fixup)
 			*(.gnu.warning)
 			*(.rodata)
diff -prauN linux-2.6.0-test9-bk22/arch/arm26/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/arm26/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/arm26/kernel/process.c	2003-10-25 11:44:39.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/arm26/kernel/process.c	2003-11-17 23:20:47.000000000 -0800
@@ -400,11 +400,6 @@ pid_t kernel_thread(int (*fn)(void *), v
 /*
  * 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)
 {
 	unsigned long fp, lr;
@@ -419,7 +414,8 @@ unsigned long get_wchan(struct task_stru
 		if (fp < stack_page || fp > 4092+stack_page)
 			return 0;
 		lr = pc_pointer (((unsigned long *)fp)[-1]);
-		if (lr < first_sched || lr > last_sched)
+		if (lr < scheduling_functions_start_here ||
+				lr > scheduling_functions_end_here)
 			return lr;
 		fp = *(unsigned long *) (fp - 12);
 	} while (count ++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/arm26/kernel/vmlinux-arm26-xip.lds.in wchan-2.6.0-test9-bk22-1/arch/arm26/kernel/vmlinux-arm26-xip.lds.in
--- linux-2.6.0-test9-bk22/arch/arm26/kernel/vmlinux-arm26-xip.lds.in	2003-10-25 11:44:34.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/arm26/kernel/vmlinux-arm26-xip.lds.in	2003-11-17 23:11:07.000000000 -0800
@@ -66,6 +66,9 @@ SECTIONS
 	.text : {			/* Real text segment		*/
 		_text = .;		/* Text and read-only data	*/
 			*(.text)
+			__scheduling_functions_start_here = .;
+			*(.text.sched)
+			__scheduling_functions_end_here = .;
 			*(.fixup)
 			*(.gnu.warning)
 			*(.rodata)
diff -prauN linux-2.6.0-test9-bk22/arch/arm26/kernel/vmlinux-arm26.lds.in wchan-2.6.0-test9-bk22-1/arch/arm26/kernel/vmlinux-arm26.lds.in
--- linux-2.6.0-test9-bk22/arch/arm26/kernel/vmlinux-arm26.lds.in	2003-10-25 11:42:56.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/arm26/kernel/vmlinux-arm26.lds.in	2003-11-17 23:10:18.000000000 -0800
@@ -67,6 +67,9 @@ SECTIONS
 	.text : {			/* Real text segment		*/
 		_text = .;		/* Text and read-only data	*/
 			*(.text)
+			__scheduling_functions_start_here = .;
+			*(.text.sched)
+			__scheduling_functions_end_here = .;
 			*(.fixup)
 			*(.gnu.warning)
 			*(.rodata)
diff -prauN linux-2.6.0-test9-bk22/arch/cris/arch-v10/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/cris/arch-v10/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/cris/arch-v10/vmlinux.lds.S	2003-10-25 11:43:29.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/cris/arch-v10/vmlinux.lds.S	2003-11-17 23:08:52.000000000 -0800
@@ -25,6 +25,9 @@ SECTIONS
 	__stext = .;
 	.text : {
 		*(.text)
+		__scheduling_functions_start_here = .;
+		*(.text.sched)
+		__scheduling_functions_end_here = .;
 		*(.fixup)
 		*(.text.__*)
 	}
diff -prauN linux-2.6.0-test9-bk22/arch/h8300/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/h8300/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/h8300/kernel/process.c	2003-10-25 11:42:43.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/h8300/kernel/process.c	2003-11-17 23:21:15.000000000 -0800
@@ -264,11 +264,6 @@ out:
 /*
  * 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 thread_saved_pc(struct task_struct *tsk)
 {
 	return ((struct pt_regs *)tsk->thread.esp0)->pc;
@@ -289,8 +284,8 @@ unsigned long get_wchan(struct task_stru
 		    fp >= 8184+stack_page)
 			return 0;
 		pc = ((unsigned long *)fp)[1];
-		/* FIXME: This depends on the order of these functions. */
-		if (pc < first_sched || pc >= last_sched)
+		if (pc < scheduling_functions_start_here ||
+				pc >= scheduling_functions_end_here)
 			return pc;
 		fp = *(unsigned long *) fp;
 	} while (count++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/h8300/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/h8300/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/h8300/kernel/vmlinux.lds.S	2003-10-25 11:43:54.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/h8300/kernel/vmlinux.lds.S	2003-11-17 23:17:49.000000000 -0800
@@ -82,6 +82,9 @@ SECTIONS
 #endif
 	__stext = . ;
         	*(.text)
+	__scheduling_functions_start_here = .;
+		*(.text.sched)
+	__scheduling_functions_end_here = .;
 	. = ALIGN(0x4) ;
 		*(.exit.text)
 		*(.text.*)
diff -prauN linux-2.6.0-test9-bk22/arch/i386/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/i386/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/i386/kernel/process.c	2003-10-25 11:42:40.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/i386/kernel/process.c	2003-11-17 23:03:54.000000000 -0800
@@ -631,11 +631,6 @@ out:
 /*
  * 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)
 {
 	unsigned long ebp, esp, eip;
@@ -653,14 +648,13 @@ unsigned long get_wchan(struct task_stru
 		if (ebp < stack_page || ebp > 8184+stack_page)
 			return 0;
 		eip = *(unsigned long *) (ebp+4);
-		if (eip < first_sched || eip >= last_sched)
+		if (eip < scheduling_functions_start_here ||
+				eip >= scheduling_functions_end_here)
 			return eip;
 		ebp = *(unsigned long *) ebp;
 	} while (count++ < 16);
 	return 0;
 }
-#undef last_sched
-#undef first_sched
 
 /*
  * sys_alloc_thread_area: get a yet unused TLS descriptor index.
diff -prauN linux-2.6.0-test9-bk22/arch/i386/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/i386/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/i386/kernel/vmlinux.lds.S	2003-10-25 11:43:05.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/i386/kernel/vmlinux.lds.S	2003-11-17 23:01:42.000000000 -0800
@@ -15,6 +15,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.text.sched)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x9090
diff -prauN linux-2.6.0-test9-bk22/arch/ia64/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/ia64/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/ia64/kernel/process.c	2003-10-25 11:43:35.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/ia64/kernel/process.c	2003-11-17 23:31:04.000000000 -0800
@@ -638,11 +638,6 @@ get_wchan (struct task_struct *p)
 	/*
 	 * 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)
-
 	/*
 	 * Note: p may not be a blocked task (it could be current or
 	 * another process running on some other CPU.  Rather than
@@ -656,12 +651,11 @@ get_wchan (struct task_struct *p)
 		if (unw_unwind(&info) < 0)
 			return 0;
 		unw_get_ip(&info, &ip);
-		if (ip < first_sched || ip >= last_sched)
+		if (ip < scheduling_functions_start_here ||
+				ip >= scheduling_functions_end_here)
 			return ip;
 	} while (count++ < 16);
 	return 0;
-#	undef first_sched
-#	undef last_sched
 }
 
 void
diff -prauN linux-2.6.0-test9-bk22/arch/ia64/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/ia64/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/ia64/kernel/vmlinux.lds.S	2003-10-25 11:44:35.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/ia64/kernel/vmlinux.lds.S	2003-11-17 23:12:13.000000000 -0800
@@ -35,6 +35,9 @@ SECTIONS
     {
 	*(.text.ivt)
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.text.sched)
+	__scheduling_functions_end_here = .;
 	*(.gnu.linkonce.t*)
     }
   .text2 : AT(ADDR(.text2) - LOAD_OFFSET)
diff -prauN linux-2.6.0-test9-bk22/arch/m68k/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/m68k/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/m68k/kernel/process.c	2003-10-25 11:45:04.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/m68k/kernel/process.c	2003-11-17 23:22:49.000000000 -0800
@@ -65,12 +65,10 @@ asmlinkage void ret_from_fork(void);
  */
 unsigned long thread_saved_pc(struct task_struct *tsk)
 {
-	extern void scheduling_functions_start_here(void);
-	extern void scheduling_functions_end_here(void);
 	struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
 	/* Check whether the thread is blocked in resume() */
-	if (sw->retpc > (unsigned long)scheduling_functions_start_here &&
-	    sw->retpc < (unsigned long)scheduling_functions_end_here)
+	if (sw->retpc > scheduling_functions_start_here &&
+	    sw->retpc < scheduling_functions_end_here)
 		return ((unsigned long *)sw->a6)[1];
 	else
 		return sw->retpc;
@@ -387,11 +385,6 @@ out:
 /*
  * 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)
 {
 	unsigned long fp, pc;
@@ -407,8 +400,8 @@ unsigned long get_wchan(struct task_stru
 		    fp >= 8184+stack_page)
 			return 0;
 		pc = ((unsigned long *)fp)[1];
-		/* FIXME: This depends on the order of these functions. */
-		if (pc < first_sched || pc >= last_sched)
+		if (pc < scheduling_functions_start_here ||
+				pc >= scheduling_functions_end_here)
 			return pc;
 		fp = *(unsigned long *) fp;
 	} while (count++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/m68k/kernel/vmlinux-std.lds wchan-2.6.0-test9-bk22-1/arch/m68k/kernel/vmlinux-std.lds
--- linux-2.6.0-test9-bk22/arch/m68k/kernel/vmlinux-std.lds	2003-10-25 11:44:39.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/m68k/kernel/vmlinux-std.lds	2003-11-17 23:11:46.000000000 -0800
@@ -12,6 +12,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.text.sched)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x4e75
diff -prauN linux-2.6.0-test9-bk22/arch/m68k/kernel/vmlinux-sun3.lds wchan-2.6.0-test9-bk22-1/arch/m68k/kernel/vmlinux-sun3.lds
--- linux-2.6.0-test9-bk22/arch/m68k/kernel/vmlinux-sun3.lds	2003-10-25 11:42:41.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/m68k/kernel/vmlinux-sun3.lds	2003-11-17 23:11:27.000000000 -0800
@@ -13,6 +13,9 @@ SECTIONS
   .text : {
 	*(.head)
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.text.sched)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x4e75
diff -prauN linux-2.6.0-test9-bk22/arch/m68knommu/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/m68knommu/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/m68knommu/kernel/process.c	2003-10-25 11:43:07.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/m68knommu/kernel/process.c	2003-11-17 23:23:27.000000000 -0800
@@ -406,11 +406,6 @@ out:
 /*
  * 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)
 {
 	unsigned long fp, pc;
@@ -426,8 +421,8 @@ unsigned long get_wchan(struct task_stru
 		    fp >= 8184+stack_page)
 			return 0;
 		pc = ((unsigned long *)fp)[1];
-		/* FIXME: This depends on the order of these functions. */
-		if (pc < first_sched || pc >= last_sched)
+		if (pc < scheduling_functions_start_here ||
+				pc >= scheduling_functions_end_here)
 			return pc;
 		fp = *(unsigned long *) fp;
 	} while (count++ < 16);
@@ -439,13 +434,11 @@ unsigned long get_wchan(struct task_stru
  */
 unsigned long thread_saved_pc(struct task_struct *tsk)
 {
-	extern void scheduling_functions_start_here(void);
-	extern void scheduling_functions_end_here(void);
 	struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
 
 	/* Check whether the thread is blocked in resume() */
-	if (sw->retpc > (unsigned long)scheduling_functions_start_here &&
-	    sw->retpc < (unsigned long)scheduling_functions_end_here)
+	if (sw->retpc > scheduling_functions_start_here &&
+	    sw->retpc < scheduling_functions_end_here)
 		return ((unsigned long *)sw->a6)[1];
 	else
 		return sw->retpc;
diff -prauN linux-2.6.0-test9-bk22/arch/m68knommu/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/m68knommu/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/m68knommu/kernel/vmlinux.lds.S	2003-10-25 11:43:29.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/m68knommu/kernel/vmlinux.lds.S	2003-11-17 23:05:24.000000000 -0800
@@ -191,6 +191,9 @@ SECTIONS {
 	.text : {
 		_stext = . ;
         	*(.text)
+		__scheduling_functions_start_here = .;
+		*(.text.sched)
+		__scheduling_functions_end_here = .;
         	*(.text.lock)
 
 		. = ALIGN(16);          /* Exception table              */
diff -prauN linux-2.6.0-test9-bk22/arch/mips/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/mips/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/mips/kernel/process.c	2003-10-25 11:43:29.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/mips/kernel/process.c	2003-11-17 23:31:29.000000000 -0800
@@ -276,11 +276,6 @@ unsigned long thread_saved_pc(struct tas
 /*
  * 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)
-
 /* get_wchan - a maintenance nightmare^W^Wpain in the ass ...  */
 unsigned long get_wchan(struct task_struct *p)
 {
@@ -292,7 +287,8 @@ unsigned long get_wchan(struct task_stru
 	if (!mips_frame_info_initialized)
 		return 0;
 	pc = thread_saved_pc(p);
-	if (pc < first_sched || pc >= last_sched)
+	if (pc < scheduling_functions_start_here ||
+			pc >= scheduling_functions_end_here)
 		goto out;
 
 	if (pc >= (unsigned long) sleep_on_timeout)
@@ -326,7 +322,8 @@ schedule_timeout_caller:
 	 */
 	pc    = ((unsigned long *)frame)[schedule_timeout_frame.pc_offset];
 
-	if (pc >= first_sched && pc < last_sched) {
+	if (pc >= scheduling_functions_start_here &&
+			pc < scheduling_functions_end_here) {
 		/* schedule_timeout called by [interruptible_]sleep_on_timeout */
 		frame = ((unsigned long *)frame)[schedule_timeout_frame.frame_offset];
 		pc    = ((unsigned long *)frame)[sleep_on_timeout_frame.pc_offset];
diff -prauN linux-2.6.0-test9-bk22/arch/mips/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/mips/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/mips/kernel/vmlinux.lds.S	2003-10-25 11:43:21.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/mips/kernel/vmlinux.lds.S	2003-11-17 23:08:18.000000000 -0800
@@ -27,6 +27,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.text.sched)
+    __scheduling_functions_end_here = .;
     *(.fixup)
     *(.gnu.warning)
   } =0
diff -prauN linux-2.6.0-test9-bk22/arch/parisc/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/parisc/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/parisc/kernel/vmlinux.lds.S	2003-10-25 11:43:05.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/parisc/kernel/vmlinux.lds.S	2003-11-17 23:14:31.000000000 -0800
@@ -24,6 +24,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text BLOCK(16) : {
 	*(.text*)
+	__scheduling_functions_start_here = .;
+	*(.text.sched)
+	__scheduling_functions_end_here =.;
 	*(.PARISC.unwind)
 	*(.fixup)
 	*(.lock.text)		/* out-of-line lock text */
diff -prauN linux-2.6.0-test9-bk22/arch/ppc/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/ppc/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/ppc/kernel/process.c	2003-10-25 11:43:35.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/ppc/kernel/process.c	2003-11-17 23:25:35.000000000 -0800
@@ -650,11 +650,6 @@ void __init ll_puts(const char *s)
 /*
  * 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)
 {
 	unsigned long ip, sp;
@@ -669,7 +664,8 @@ unsigned long get_wchan(struct task_stru
 			return 0;
 		if (count > 0) {
 			ip = *(unsigned long *)(sp + 4);
-			if (ip < first_sched || ip >= last_sched)
+			if (ip < scheduling_functions_start_here ||
+					ip >= scheduling_functions_end_here)
 				return ip;
 		}
 	} while (count++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/ppc/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/ppc/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/ppc/kernel/vmlinux.lds.S	2003-11-17 22:51:23.000000000 -0800
+++ wchan-2.6.0-test9-bk22-1/arch/ppc/kernel/vmlinux.lds.S	2003-11-17 23:07:08.000000000 -0800
@@ -31,6 +31,9 @@ SECTIONS
   .text      :
   {
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.text.sched)
+    __scheduling_functions_end_here = .;
     *(.fixup)
     *(.got1)
     __got2_start = .;
diff -prauN linux-2.6.0-test9-bk22/arch/ppc64/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/ppc64/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/ppc64/kernel/process.c	2003-10-25 11:43:54.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/ppc64/kernel/process.c	2003-11-17 23:26:08.000000000 -0800
@@ -369,11 +369,6 @@ out:
 /*
  * 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)
 {
 	unsigned long ip, sp;
@@ -393,7 +388,8 @@ unsigned long get_wchan(struct task_stru
 			 * XXX we mask the upper 32 bits until procps
 			 * gets fixed.
 			 */
-			if (ip < first_sched || ip >= last_sched)
+			if (ip < scheduling_functions_start_here ||
+					ip >= scheduling_functions_end_here)
 				return (ip & 0xFFFFFFFF);
 		}
 	} while (count++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/ppc64/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/ppc64/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/ppc64/kernel/vmlinux.lds.S	2003-10-25 11:44:15.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/ppc64/kernel/vmlinux.lds.S	2003-11-17 23:13:13.000000000 -0800
@@ -33,6 +33,9 @@ SECTIONS
   .text      :
   {
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.text.sched)
+    __scheduling_functions_end_here = .;
     *(.fixup)
     *(.got1)
   }
diff -prauN linux-2.6.0-test9-bk22/arch/s390/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/s390/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/s390/kernel/process.c	2003-10-25 11:44:17.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/s390/kernel/process.c	2003-11-17 23:26:43.000000000 -0800
@@ -371,11 +371,6 @@ void dump_thread(struct pt_regs * regs, 
 /*
  * 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)
 {
 	unsigned long r14, r15, bc;
@@ -398,12 +393,10 @@ unsigned long get_wchan(struct task_stru
 #else
 		r14 = *(unsigned long *) (bc+112);
 #endif
-		if (r14 < first_sched || r14 >= last_sched)
+		if (r14 < scheduling_functions_start_here ||
+				r14 >= scheduling_functions_end_here)
 			return r14;
 		bc = (*(unsigned long *) bc) & PSW_ADDR_INSN;
 	} while (count++ < 16);
 	return 0;
 }
-#undef last_sched
-#undef first_sched
-
diff -prauN linux-2.6.0-test9-bk22/arch/s390/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/s390/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/s390/kernel/vmlinux.lds.S	2003-10-25 11:43:23.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/s390/kernel/vmlinux.lds.S	2003-11-17 23:18:44.000000000 -0800
@@ -23,6 +23,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.text.sched)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x0700
diff -prauN linux-2.6.0-test9-bk22/arch/sh/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/sh/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/sh/kernel/process.c	2003-10-25 11:44:08.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/sh/kernel/process.c	2003-11-17 23:28:29.000000000 -0800
@@ -375,11 +375,6 @@ out:
 /*
  * 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)
 {
 	unsigned long schedule_frame;
diff -prauN linux-2.6.0-test9-bk22/arch/sh/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/sh/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/sh/kernel/vmlinux.lds.S	2003-10-25 11:43:49.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/sh/kernel/vmlinux.lds.S	2003-11-17 23:09:23.000000000 -0800
@@ -22,6 +22,9 @@ SECTIONS
 	} = 0
   .text : {
 	*(.text)
+	__scheduling_functions_start_here =.;
+	*(.text.sched)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x0009
diff -prauN linux-2.6.0-test9-bk22/arch/sparc/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/sparc/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/sparc/kernel/process.c	2003-10-25 11:43:00.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/sparc/kernel/process.c	2003-11-17 23:29:13.000000000 -0800
@@ -692,9 +692,6 @@ pid_t kernel_thread(int (*fn)(void *), v
 	return retval;
 }
 
-extern void scheduling_functions_start_here(void);
-extern void scheduling_functions_end_here(void);
-
 unsigned long get_wchan(struct task_struct *task)
 {
 	unsigned long pc, fp, bias = 0;
@@ -715,8 +712,8 @@ unsigned long get_wchan(struct task_stru
 			break;
 		rw = (struct reg_window *) fp;
 		pc = rw->ins[7];
-		if (pc < ((unsigned long) scheduling_functions_start_here) ||
-                    pc >= ((unsigned long) scheduling_functions_end_here)) {
+		if (pc < scheduling_functions_start_here ||
+                    pc >= scheduling_functions_end_here) {
 			ret = pc;
 			goto out;
 		}
diff -prauN linux-2.6.0-test9-bk22/arch/sparc/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/sparc/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/sparc/kernel/vmlinux.lds.S	2003-10-25 11:42:53.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/sparc/kernel/vmlinux.lds.S	2003-11-17 23:06:33.000000000 -0800
@@ -12,6 +12,9 @@ SECTIONS
   .text 0xf0004000 :
   {
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.text.sched)
+    __scheduling_functions_end_here = .;
     *(.gnu.warning)
   } =0
   _etext = .;
diff -prauN linux-2.6.0-test9-bk22/arch/sparc64/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/sparc64/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/sparc64/kernel/process.c	2003-10-25 11:43:30.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/sparc64/kernel/process.c	2003-11-17 23:29:28.000000000 -0800
@@ -824,9 +824,6 @@ out:
 	return error;
 }
 
-extern void scheduling_functions_start_here(void);
-extern void scheduling_functions_end_here(void);
-
 unsigned long get_wchan(struct task_struct *task)
 {
 	unsigned long pc, fp, bias = 0;
@@ -850,8 +847,8 @@ unsigned long get_wchan(struct task_stru
 			break;
 		rw = (struct reg_window *) fp;
 		pc = rw->ins[7];
-		if (pc < ((unsigned long) scheduling_functions_start_here) ||
-		    pc >= ((unsigned long) scheduling_functions_end_here)) {
+		if (pc < scheduling_functions_start_here ||
+		    pc >= scheduling_functions_end_here) {
 			ret = pc;
 			goto out;
 		}
diff -prauN linux-2.6.0-test9-bk22/arch/sparc64/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/sparc64/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/sparc64/kernel/vmlinux.lds.S	2003-10-25 11:44:36.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/sparc64/kernel/vmlinux.lds.S	2003-11-17 23:06:07.000000000 -0800
@@ -15,6 +15,9 @@ SECTIONS
   .text 0x0000000000404000 :
   {
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.text.sched)
+    __scheduling_functions_end_here = .;
     *(.gnu.warning)
   } =0
   _etext = .;
diff -prauN linux-2.6.0-test9-bk22/arch/v850/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/v850/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/v850/kernel/process.c	2003-10-25 11:43:02.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/v850/kernel/process.c	2003-11-18 00:47:03.000000000 -0800
@@ -203,11 +203,6 @@ int sys_execve (char *name, char **argv,
 /*
  * 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 0  /* Barf.  Figure out the stack-layout later.  XXX  */
@@ -221,15 +216,16 @@ unsigned long get_wchan (struct task_str
 
 	/* This quite disgusting function walks up the stack, following
 	   saved return address, until it something that's out of bounds
-	   (as defined by `first_sched' and `last_sched').  It then
-	   returns the last PC that was in-bounds.  */
+	   (as defined by `scheduling_functions_start_here' and
+	   `scheduling_functions_end_here').  It then returns the last
+	   PC that was in-bounds.  */
 	do {
-		if (fp < stack_page + sizeof (struct task_struct) ||
-		    fp >= 8184+stack_page)
+		if (fp < stack_page + sizeof(struct thread_info) ||
+		    fp >= THREAD_SIZE + stack_page - 8)
 			return 0;
 		pc = ((unsigned long *)fp)[1];
-		/* FIXME: This depends on the order of these functions. */
-		if (pc < first_sched || pc >= last_sched)
+		if (pc < scheduling_functions_start_here ||
+				pc >= scheduling_functions_end_here)
 			return pc;
 		fp = *(unsigned long *) fp;
 	} while (count++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/v850/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/v850/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/v850/kernel/vmlinux.lds.S	2003-10-25 11:43:58.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/v850/kernel/vmlinux.lds.S	2003-11-17 23:18:13.000000000 -0800
@@ -64,6 +64,9 @@
 #define TEXT_CONTENTS							      \
 		__stext = . ;						      \
         	*(.text)						      \
+		__scheduling_functions_start_here = .;
+		*(.text.sched)
+		__scheduling_functions_end_here = .;
 			*(.exit.text)	/* 2.5 convention */		      \
 			*(.text.exit)	/* 2.4 convention */		      \
 			*(.text.lock)					      \
diff -prauN linux-2.6.0-test9-bk22/arch/x86_64/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/x86_64/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/x86_64/kernel/process.c	2003-10-25 11:43:49.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/x86_64/kernel/process.c	2003-11-17 23:30:38.000000000 -0800
@@ -528,11 +528,6 @@ asmlinkage long sys_vfork(struct pt_regs
 /*
  * 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)
 {
 	u64 fp,rip;
@@ -547,14 +542,13 @@ unsigned long get_wchan(struct task_stru
 		if (fp < (unsigned long)p || fp > (unsigned long)p+THREAD_SIZE)
 			return 0; 
 		rip = *(u64 *)(fp+8); 
-		if (rip < first_sched || rip >= last_sched)
+		if (rip < scheduling_functions_start_here ||
+				rip >= scheduling_functions_end_here)
 			return rip; 
 		fp = *(u64 *)fp; 
 	} while (count++ < 16); 
 	return 0;
 }
-#undef last_sched
-#undef first_sched
 
 long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
 { 
diff -prauN linux-2.6.0-test9-bk22/arch/x86_64/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/x86_64/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/x86_64/kernel/vmlinux.lds.S	2003-10-25 11:42:51.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/x86_64/kernel/vmlinux.lds.S	2003-11-17 23:14:54.000000000 -0800
@@ -14,6 +14,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.text.sched)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x9090
diff -prauN linux-2.6.0-test9-bk22/include/linux/init.h wchan-2.6.0-test9-bk22-1/include/linux/init.h
--- linux-2.6.0-test9-bk22/include/linux/init.h	2003-10-25 11:42:50.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/include/linux/init.h	2003-11-17 23:01:42.000000000 -0800
@@ -45,6 +45,8 @@
 #define __exitdata	__attribute__ ((__section__(".exit.data")))
 #define __exit_call	__attribute_used__ __attribute__ ((__section__ (".exitcall.exit")))
 
+#define __sched		__attribute__((__section__(".text.sched")))
+
 #ifdef MODULE
 #define __exit		__attribute__ ((__section__(".exit.text")))
 #else
diff -prauN linux-2.6.0-test9-bk22/include/linux/sched.h wchan-2.6.0-test9-bk22-1/include/linux/sched.h
--- linux-2.6.0-test9-bk22/include/linux/sched.h	2003-11-17 22:51:24.000000000 -0800
+++ wchan-2.6.0-test9-bk22-1/include/linux/sched.h	2003-11-17 23:01:42.000000000 -0800
@@ -169,6 +169,8 @@ extern void update_one_process(struct ta
 			       unsigned long system, int cpu);
 extern void scheduler_tick(int user_tick, int system);
 extern unsigned long cache_decay_ticks;
+extern const unsigned long scheduling_functions_start_here;
+extern const unsigned long scheduling_functions_end_here;
 
 
 #define	MAX_SCHEDULE_TIMEOUT	LONG_MAX
diff -prauN linux-2.6.0-test9-bk22/kernel/sched.c wchan-2.6.0-test9-bk22-1/kernel/sched.c
--- linux-2.6.0-test9-bk22/kernel/sched.c	2003-11-17 22:51:24.000000000 -0800
+++ wchan-2.6.0-test9-bk22-1/kernel/sched.c	2003-11-17 23:01:42.000000000 -0800
@@ -221,6 +221,13 @@ static DEFINE_PER_CPU(struct runqueue, r
 #define task_rq(p)		cpu_rq(task_cpu(p))
 #define cpu_curr(cpu)		(cpu_rq(cpu)->curr)
 
+extern unsigned long __scheduling_functions_start_here;
+extern unsigned long __scheduling_functions_end_here;
+const unsigned long scheduling_functions_start_here =
+			(unsigned long)&__scheduling_functions_start_here;
+const unsigned long scheduling_functions_end_here =
+			(unsigned long)&__scheduling_functions_end_here;
+
 /*
  * Default context-switch locking:
  */
@@ -1463,12 +1470,10 @@ out:
 	rebalance_tick(rq, 0);
 }
 
-void scheduling_functions_start_here(void) { }
-
 /*
  * schedule() is the main scheduler function.
  */
-asmlinkage void schedule(void)
+asmlinkage __sched void schedule(void)
 {
 	task_t *prev, *next;
 	runqueue_t *rq;
@@ -1611,7 +1616,7 @@ EXPORT_SYMBOL(schedule);
  * off of preempt_enable.  Kernel preemptions off return from interrupt
  * occur there and call schedule directly.
  */
-asmlinkage void preempt_schedule(void)
+asmlinkage __sched void preempt_schedule(void)
 {
 	struct thread_info *ti = current_thread_info();
 
@@ -1636,7 +1641,7 @@ need_resched:
 EXPORT_SYMBOL(preempt_schedule);
 #endif /* CONFIG_PREEMPT */
 
-int default_wake_function(wait_queue_t *curr, unsigned mode, int sync)
+__sched int default_wake_function(wait_queue_t *curr, unsigned mode, int sync)
 {
 	task_t *p = curr->task;
 	return try_to_wake_up(p, mode, sync);
@@ -1653,7 +1658,7 @@ EXPORT_SYMBOL(default_wake_function);
  * started to run but is not in state TASK_RUNNING.  try_to_wake_up() returns
  * zero in this (rare) case, and we handle it by continuing to scan the queue.
  */
-static void __wake_up_common(wait_queue_head_t *q, unsigned int mode, int nr_exclusive, int sync)
+static __sched void __wake_up_common(wait_queue_head_t *q, unsigned int mode, int nr_exclusive, int sync)
 {
 	struct list_head *tmp, *next;
 
@@ -1675,7 +1680,7 @@ static void __wake_up_common(wait_queue_
  * @mode: which threads
  * @nr_exclusive: how many wake-one or wake-many threads to wake up
  */
-void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
+__sched void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
 {
 	unsigned long flags;
 
@@ -1707,7 +1712,7 @@ void __wake_up_locked(wait_queue_head_t 
  *
  * On UP it can prevent extra preemption.
  */
-void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
+__sched void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
 {
 	unsigned long flags;
 
@@ -1724,7 +1729,7 @@ void __wake_up_sync(wait_queue_head_t *q
 
 EXPORT_SYMBOL_GPL(__wake_up_sync);	/* For internal use only */
 
-void complete(struct completion *x)
+__sched void complete(struct completion *x)
 {
 	unsigned long flags;
 
@@ -1736,7 +1741,7 @@ void complete(struct completion *x)
 
 EXPORT_SYMBOL(complete);
 
-void complete_all(struct completion *x)
+__sched void complete_all(struct completion *x)
 {
 	unsigned long flags;
 
@@ -1746,7 +1751,7 @@ void complete_all(struct completion *x)
 	spin_unlock_irqrestore(&x->wait.lock, flags);
 }
 
-void wait_for_completion(struct completion *x)
+__sched void wait_for_completion(struct completion *x)
 {
 	might_sleep();
 	spin_lock_irq(&x->wait.lock);
@@ -1784,7 +1789,7 @@ EXPORT_SYMBOL(wait_for_completion);
 	__remove_wait_queue(q, &wait);				\
 	spin_unlock_irqrestore(&q->lock, flags);
 
-void interruptible_sleep_on(wait_queue_head_t *q)
+__sched void interruptible_sleep_on(wait_queue_head_t *q)
 {
 	SLEEP_ON_VAR
 
@@ -1797,7 +1802,7 @@ void interruptible_sleep_on(wait_queue_h
 
 EXPORT_SYMBOL(interruptible_sleep_on);
 
-long interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
+__sched long interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
 	SLEEP_ON_VAR
 
@@ -1812,7 +1817,7 @@ long interruptible_sleep_on_timeout(wait
 
 EXPORT_SYMBOL(interruptible_sleep_on_timeout);
 
-void sleep_on(wait_queue_head_t *q)
+__sched void sleep_on(wait_queue_head_t *q)
 {
 	SLEEP_ON_VAR
 
@@ -1825,7 +1830,7 @@ void sleep_on(wait_queue_head_t *q)
 
 EXPORT_SYMBOL(sleep_on);
 
-long sleep_on_timeout(wait_queue_head_t *q, long timeout)
+__sched long sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
 	SLEEP_ON_VAR
 
@@ -1840,8 +1845,6 @@ long sleep_on_timeout(wait_queue_head_t 
 
 EXPORT_SYMBOL(sleep_on_timeout);
 
-void scheduling_functions_end_here(void) { }
-
 void set_user_nice(task_t *p, long nice)
 {
 	unsigned long flags;
@@ -2291,7 +2294,7 @@ asmlinkage long sys_sched_yield(void)
 	return 0;
 }
 
-void __cond_resched(void)
+__sched void __cond_resched(void)
 {
 	set_current_state(TASK_RUNNING);
 	schedule();
@@ -2305,7 +2308,7 @@ EXPORT_SYMBOL(__cond_resched);
  * this is a shortcut for kernel-space yielding - it marks the
  * thread runnable and calls sys_sched_yield().
  */
-void yield(void)
+__sched void yield(void)
 {
 	set_current_state(TASK_RUNNING);
 	sys_sched_yield();
@@ -2320,7 +2323,7 @@ EXPORT_SYMBOL(yield);
  * But don't do that if it is a deliberate, throttling IO wait (this task
  * has set its backing_dev_info: the queue against which it should throttle)
  */
-void io_schedule(void)
+__sched void io_schedule(void)
 {
 	struct runqueue *rq = this_rq();
 
@@ -2331,7 +2334,7 @@ void io_schedule(void)
 
 EXPORT_SYMBOL(io_schedule);
 
-long io_schedule_timeout(long timeout)
+__sched long io_schedule_timeout(long timeout)
 {
 	struct runqueue *rq = this_rq();
 	long ret;
@@ -2881,7 +2884,7 @@ EXPORT_SYMBOL(__might_sleep);
  *
  * Called inside preempt_disable().
  */
-void __preempt_spin_lock(spinlock_t *lock)
+__sched void __preempt_spin_lock(spinlock_t *lock)
 {
 	if (preempt_count() > 1) {
 		_raw_spin_lock(lock);
@@ -2897,7 +2900,7 @@ void __preempt_spin_lock(spinlock_t *loc
 
 EXPORT_SYMBOL(__preempt_spin_lock);
 
-void __preempt_write_lock(rwlock_t *lock)
+__sched void __preempt_write_lock(rwlock_t *lock)
 {
 	if (preempt_count() > 1) {
 		_raw_write_lock(lock);
diff -prauN linux-2.6.0-test9-bk22/kernel/timer.c wchan-2.6.0-test9-bk22-1/kernel/timer.c
--- linux-2.6.0-test9-bk22/kernel/timer.c	2003-11-17 22:51:24.000000000 -0800
+++ wchan-2.6.0-test9-bk22-1/kernel/timer.c	2003-11-17 23:01:42.000000000 -0800
@@ -1000,7 +1000,7 @@ static void process_timeout(unsigned lon
  *
  * In all cases the return value is guaranteed to be non-negative.
  */
-signed long schedule_timeout(signed long timeout)
+__sched signed long schedule_timeout(signed long timeout)
 {
 	struct timer_list timer;
 	unsigned long expire;
@@ -1060,7 +1060,7 @@ asmlinkage long sys_gettid(void)
 	return current->pid;
 }
 
-static long nanosleep_restart(struct restart_block *restart)
+static __sched long nanosleep_restart(struct restart_block *restart)
 {
 	unsigned long expire = restart->arg0, now = jiffies;
 	struct timespec *rmtp = (struct timespec *) restart->arg1;

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: use ELF sections for get_wchan()
  2003-11-18  8:50     ` William Lee Irwin III
@ 2003-11-19  3:13       ` William Lee Irwin III
  2003-11-19  5:53         ` Sam Ravnborg
  0 siblings, 1 reply; 10+ messages in thread
From: William Lee Irwin III @ 2003-11-19  3:13 UTC (permalink / raw)
  To: linux-kernel

On Tue, Nov 18, 2003 at 12:45:29AM -0800, William Lee Irwin III wrote:
>> Aha, thanks. I'll follow up with an amended patch (for both instances).

On Tue, Nov 18, 2003 at 12:50:22AM -0800, William Lee Irwin III wrote:
> And here it is. I also added a small tweak for the #if 0'd v850 code
> (which assumed a 2.4 stack layout; v850's using off-stack task_t's now).

willy said I should use .sched.text instead of .text.sched; this fixes
it up to do that.


-- wli



diff -prauN linux-2.6.0-test9-bk22/arch/alpha/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/alpha/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/alpha/kernel/process.c	2003-10-25 11:44:37.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/alpha/kernel/process.c	2003-11-17 23:20:01.000000000 -0800
@@ -513,11 +513,6 @@ thread_saved_pc(task_t *t)
 /*
  * 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)
 {
@@ -536,7 +531,8 @@ get_wchan(struct task_struct *p)
 	 */
 
 	pc = thread_saved_pc(p);
-	if (pc >= first_sched && pc < last_sched) {
+	if (pc >= scheduling_functions_start_here &&
+			pc < scheduling_functions_end_here) {
 		schedule_frame = ((unsigned long *)p->thread_info->pcb.ksp)[6];
 		return ((unsigned long *)schedule_frame)[12];
 	}
diff -prauN linux-2.6.0-test9-bk22/arch/alpha/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/alpha/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/alpha/kernel/vmlinux.lds.S	2003-10-25 11:43:42.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/alpha/kernel/vmlinux.lds.S	2003-11-18 19:07:05.000000000 -0800
@@ -17,6 +17,9 @@ SECTIONS
   _text = .;					/* Text and read-only data */
   .text : { 
 	*(.text) 
+	__scheduling_functions_start_here = .;
+	*(.sched.text)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
   } :kernel
diff -prauN linux-2.6.0-test9-bk22/arch/arm/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/arm/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/arm/kernel/process.c	2003-10-25 11:44:41.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/arm/kernel/process.c	2003-11-17 23:20:24.000000000 -0800
@@ -415,11 +415,6 @@ pid_t kernel_thread(int (*fn)(void *), v
 /*
  * 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)
 {
 	unsigned long fp, lr;
@@ -434,7 +429,8 @@ unsigned long get_wchan(struct task_stru
 		if (fp < stack_page || fp > 4092+stack_page)
 			return 0;
 		lr = pc_pointer (((unsigned long *)fp)[-1]);
-		if (lr < first_sched || lr > last_sched)
+		if (lr < scheduling_functions_start_here ||
+				lr > scheduling_functions_end_here)
 			return lr;
 		fp = *(unsigned long *) (fp - 12);
 	} while (count ++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/arm/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/arm/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/arm/kernel/vmlinux.lds.S	2003-10-25 11:43:22.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/arm/kernel/vmlinux.lds.S	2003-11-18 19:07:12.000000000 -0800
@@ -73,6 +73,9 @@ SECTIONS
 	.text : {			/* Real text segment		*/
 		_text = .;		/* Text and read-only data	*/
 			*(.text)
+			__scheduling_functions_start_here = .;
+			*(.sched.text)
+			__scheduling_functions_end_here = .;
 			*(.fixup)
 			*(.gnu.warning)
 			*(.rodata)
diff -prauN linux-2.6.0-test9-bk22/arch/arm26/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/arm26/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/arm26/kernel/process.c	2003-10-25 11:44:39.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/arm26/kernel/process.c	2003-11-17 23:20:47.000000000 -0800
@@ -400,11 +400,6 @@ pid_t kernel_thread(int (*fn)(void *), v
 /*
  * 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)
 {
 	unsigned long fp, lr;
@@ -419,7 +414,8 @@ unsigned long get_wchan(struct task_stru
 		if (fp < stack_page || fp > 4092+stack_page)
 			return 0;
 		lr = pc_pointer (((unsigned long *)fp)[-1]);
-		if (lr < first_sched || lr > last_sched)
+		if (lr < scheduling_functions_start_here ||
+				lr > scheduling_functions_end_here)
 			return lr;
 		fp = *(unsigned long *) (fp - 12);
 	} while (count ++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/arm26/kernel/vmlinux-arm26-xip.lds.in wchan-2.6.0-test9-bk22-1/arch/arm26/kernel/vmlinux-arm26-xip.lds.in
--- linux-2.6.0-test9-bk22/arch/arm26/kernel/vmlinux-arm26-xip.lds.in	2003-10-25 11:44:34.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/arm26/kernel/vmlinux-arm26-xip.lds.in	2003-11-18 19:06:51.000000000 -0800
@@ -66,6 +66,9 @@ SECTIONS
 	.text : {			/* Real text segment		*/
 		_text = .;		/* Text and read-only data	*/
 			*(.text)
+			__scheduling_functions_start_here = .;
+			*(.sched.text)
+			__scheduling_functions_end_here = .;
 			*(.fixup)
 			*(.gnu.warning)
 			*(.rodata)
diff -prauN linux-2.6.0-test9-bk22/arch/arm26/kernel/vmlinux-arm26.lds.in wchan-2.6.0-test9-bk22-1/arch/arm26/kernel/vmlinux-arm26.lds.in
--- linux-2.6.0-test9-bk22/arch/arm26/kernel/vmlinux-arm26.lds.in	2003-10-25 11:42:56.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/arm26/kernel/vmlinux-arm26.lds.in	2003-11-18 19:06:47.000000000 -0800
@@ -67,6 +67,9 @@ SECTIONS
 	.text : {			/* Real text segment		*/
 		_text = .;		/* Text and read-only data	*/
 			*(.text)
+			__scheduling_functions_start_here = .;
+			*(.sched.text)
+			__scheduling_functions_end_here = .;
 			*(.fixup)
 			*(.gnu.warning)
 			*(.rodata)
diff -prauN linux-2.6.0-test9-bk22/arch/cris/arch-v10/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/cris/arch-v10/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/cris/arch-v10/vmlinux.lds.S	2003-10-25 11:43:29.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/cris/arch-v10/vmlinux.lds.S	2003-11-18 19:06:39.000000000 -0800
@@ -25,6 +25,9 @@ SECTIONS
 	__stext = .;
 	.text : {
 		*(.text)
+		__scheduling_functions_start_here = .;
+		*(.sched.text)
+		__scheduling_functions_end_here = .;
 		*(.fixup)
 		*(.text.__*)
 	}
diff -prauN linux-2.6.0-test9-bk22/arch/h8300/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/h8300/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/h8300/kernel/process.c	2003-10-25 11:42:43.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/h8300/kernel/process.c	2003-11-17 23:21:15.000000000 -0800
@@ -264,11 +264,6 @@ out:
 /*
  * 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 thread_saved_pc(struct task_struct *tsk)
 {
 	return ((struct pt_regs *)tsk->thread.esp0)->pc;
@@ -289,8 +284,8 @@ unsigned long get_wchan(struct task_stru
 		    fp >= 8184+stack_page)
 			return 0;
 		pc = ((unsigned long *)fp)[1];
-		/* FIXME: This depends on the order of these functions. */
-		if (pc < first_sched || pc >= last_sched)
+		if (pc < scheduling_functions_start_here ||
+				pc >= scheduling_functions_end_here)
 			return pc;
 		fp = *(unsigned long *) fp;
 	} while (count++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/h8300/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/h8300/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/h8300/kernel/vmlinux.lds.S	2003-10-25 11:43:54.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/h8300/kernel/vmlinux.lds.S	2003-11-18 19:07:21.000000000 -0800
@@ -82,6 +82,9 @@ SECTIONS
 #endif
 	__stext = . ;
         	*(.text)
+	__scheduling_functions_start_here = .;
+		*(.sched.text)
+	__scheduling_functions_end_here = .;
 	. = ALIGN(0x4) ;
 		*(.exit.text)
 		*(.text.*)
diff -prauN linux-2.6.0-test9-bk22/arch/i386/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/i386/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/i386/kernel/process.c	2003-10-25 11:42:40.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/i386/kernel/process.c	2003-11-17 23:03:54.000000000 -0800
@@ -631,11 +631,6 @@ out:
 /*
  * 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)
 {
 	unsigned long ebp, esp, eip;
@@ -653,14 +648,13 @@ unsigned long get_wchan(struct task_stru
 		if (ebp < stack_page || ebp > 8184+stack_page)
 			return 0;
 		eip = *(unsigned long *) (ebp+4);
-		if (eip < first_sched || eip >= last_sched)
+		if (eip < scheduling_functions_start_here ||
+				eip >= scheduling_functions_end_here)
 			return eip;
 		ebp = *(unsigned long *) ebp;
 	} while (count++ < 16);
 	return 0;
 }
-#undef last_sched
-#undef first_sched
 
 /*
  * sys_alloc_thread_area: get a yet unused TLS descriptor index.
diff -prauN linux-2.6.0-test9-bk22/arch/i386/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/i386/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/i386/kernel/vmlinux.lds.S	2003-10-25 11:43:05.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/i386/kernel/vmlinux.lds.S	2003-11-18 19:05:54.000000000 -0800
@@ -15,6 +15,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.sched.text)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x9090
diff -prauN linux-2.6.0-test9-bk22/arch/ia64/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/ia64/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/ia64/kernel/process.c	2003-10-25 11:43:35.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/ia64/kernel/process.c	2003-11-17 23:31:04.000000000 -0800
@@ -638,11 +638,6 @@ get_wchan (struct task_struct *p)
 	/*
 	 * 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)
-
 	/*
 	 * Note: p may not be a blocked task (it could be current or
 	 * another process running on some other CPU.  Rather than
@@ -656,12 +651,11 @@ get_wchan (struct task_struct *p)
 		if (unw_unwind(&info) < 0)
 			return 0;
 		unw_get_ip(&info, &ip);
-		if (ip < first_sched || ip >= last_sched)
+		if (ip < scheduling_functions_start_here ||
+				ip >= scheduling_functions_end_here)
 			return ip;
 	} while (count++ < 16);
 	return 0;
-#	undef first_sched
-#	undef last_sched
 }
 
 void
diff -prauN linux-2.6.0-test9-bk22/arch/ia64/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/ia64/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/ia64/kernel/vmlinux.lds.S	2003-10-25 11:44:35.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/ia64/kernel/vmlinux.lds.S	2003-11-18 19:07:02.000000000 -0800
@@ -35,6 +35,9 @@ SECTIONS
     {
 	*(.text.ivt)
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.sched.text)
+	__scheduling_functions_end_here = .;
 	*(.gnu.linkonce.t*)
     }
   .text2 : AT(ADDR(.text2) - LOAD_OFFSET)
diff -prauN linux-2.6.0-test9-bk22/arch/m68k/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/m68k/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/m68k/kernel/process.c	2003-10-25 11:45:04.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/m68k/kernel/process.c	2003-11-17 23:22:49.000000000 -0800
@@ -65,12 +65,10 @@ asmlinkage void ret_from_fork(void);
  */
 unsigned long thread_saved_pc(struct task_struct *tsk)
 {
-	extern void scheduling_functions_start_here(void);
-	extern void scheduling_functions_end_here(void);
 	struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
 	/* Check whether the thread is blocked in resume() */
-	if (sw->retpc > (unsigned long)scheduling_functions_start_here &&
-	    sw->retpc < (unsigned long)scheduling_functions_end_here)
+	if (sw->retpc > scheduling_functions_start_here &&
+	    sw->retpc < scheduling_functions_end_here)
 		return ((unsigned long *)sw->a6)[1];
 	else
 		return sw->retpc;
@@ -387,11 +385,6 @@ out:
 /*
  * 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)
 {
 	unsigned long fp, pc;
@@ -407,8 +400,8 @@ unsigned long get_wchan(struct task_stru
 		    fp >= 8184+stack_page)
 			return 0;
 		pc = ((unsigned long *)fp)[1];
-		/* FIXME: This depends on the order of these functions. */
-		if (pc < first_sched || pc >= last_sched)
+		if (pc < scheduling_functions_start_here ||
+				pc >= scheduling_functions_end_here)
 			return pc;
 		fp = *(unsigned long *) fp;
 	} while (count++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/m68k/kernel/vmlinux-std.lds wchan-2.6.0-test9-bk22-1/arch/m68k/kernel/vmlinux-std.lds
--- linux-2.6.0-test9-bk22/arch/m68k/kernel/vmlinux-std.lds	2003-10-25 11:44:39.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/m68k/kernel/vmlinux-std.lds	2003-11-18 19:06:58.000000000 -0800
@@ -12,6 +12,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.sched.text)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x4e75
diff -prauN linux-2.6.0-test9-bk22/arch/m68k/kernel/vmlinux-sun3.lds wchan-2.6.0-test9-bk22-1/arch/m68k/kernel/vmlinux-sun3.lds
--- linux-2.6.0-test9-bk22/arch/m68k/kernel/vmlinux-sun3.lds	2003-10-25 11:42:41.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/m68k/kernel/vmlinux-sun3.lds	2003-11-18 19:06:54.000000000 -0800
@@ -13,6 +13,9 @@ SECTIONS
   .text : {
 	*(.head)
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.sched.text)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x4e75
diff -prauN linux-2.6.0-test9-bk22/arch/m68knommu/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/m68knommu/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/m68knommu/kernel/process.c	2003-10-25 11:43:07.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/m68knommu/kernel/process.c	2003-11-17 23:23:27.000000000 -0800
@@ -406,11 +406,6 @@ out:
 /*
  * 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)
 {
 	unsigned long fp, pc;
@@ -426,8 +421,8 @@ unsigned long get_wchan(struct task_stru
 		    fp >= 8184+stack_page)
 			return 0;
 		pc = ((unsigned long *)fp)[1];
-		/* FIXME: This depends on the order of these functions. */
-		if (pc < first_sched || pc >= last_sched)
+		if (pc < scheduling_functions_start_here ||
+				pc >= scheduling_functions_end_here)
 			return pc;
 		fp = *(unsigned long *) fp;
 	} while (count++ < 16);
@@ -439,13 +434,11 @@ unsigned long get_wchan(struct task_stru
  */
 unsigned long thread_saved_pc(struct task_struct *tsk)
 {
-	extern void scheduling_functions_start_here(void);
-	extern void scheduling_functions_end_here(void);
 	struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
 
 	/* Check whether the thread is blocked in resume() */
-	if (sw->retpc > (unsigned long)scheduling_functions_start_here &&
-	    sw->retpc < (unsigned long)scheduling_functions_end_here)
+	if (sw->retpc > scheduling_functions_start_here &&
+	    sw->retpc < scheduling_functions_end_here)
 		return ((unsigned long *)sw->a6)[1];
 	else
 		return sw->retpc;
diff -prauN linux-2.6.0-test9-bk22/arch/m68knommu/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/m68knommu/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/m68knommu/kernel/vmlinux.lds.S	2003-10-25 11:43:29.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/m68knommu/kernel/vmlinux.lds.S	2003-11-18 19:06:18.000000000 -0800
@@ -191,6 +191,9 @@ SECTIONS {
 	.text : {
 		_stext = . ;
         	*(.text)
+		__scheduling_functions_start_here = .;
+		*(.sched.text)
+		__scheduling_functions_end_here = .;
         	*(.text.lock)
 
 		. = ALIGN(16);          /* Exception table              */
diff -prauN linux-2.6.0-test9-bk22/arch/mips/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/mips/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/mips/kernel/process.c	2003-10-25 11:43:29.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/mips/kernel/process.c	2003-11-17 23:31:29.000000000 -0800
@@ -276,11 +276,6 @@ unsigned long thread_saved_pc(struct tas
 /*
  * 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)
-
 /* get_wchan - a maintenance nightmare^W^Wpain in the ass ...  */
 unsigned long get_wchan(struct task_struct *p)
 {
@@ -292,7 +287,8 @@ unsigned long get_wchan(struct task_stru
 	if (!mips_frame_info_initialized)
 		return 0;
 	pc = thread_saved_pc(p);
-	if (pc < first_sched || pc >= last_sched)
+	if (pc < scheduling_functions_start_here ||
+			pc >= scheduling_functions_end_here)
 		goto out;
 
 	if (pc >= (unsigned long) sleep_on_timeout)
@@ -326,7 +322,8 @@ schedule_timeout_caller:
 	 */
 	pc    = ((unsigned long *)frame)[schedule_timeout_frame.pc_offset];
 
-	if (pc >= first_sched && pc < last_sched) {
+	if (pc >= scheduling_functions_start_here &&
+			pc < scheduling_functions_end_here) {
 		/* schedule_timeout called by [interruptible_]sleep_on_timeout */
 		frame = ((unsigned long *)frame)[schedule_timeout_frame.frame_offset];
 		pc    = ((unsigned long *)frame)[sleep_on_timeout_frame.pc_offset];
diff -prauN linux-2.6.0-test9-bk22/arch/mips/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/mips/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/mips/kernel/vmlinux.lds.S	2003-10-25 11:43:21.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/mips/kernel/vmlinux.lds.S	2003-11-18 19:06:35.000000000 -0800
@@ -27,6 +27,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.sched.text)
+    __scheduling_functions_end_here = .;
     *(.fixup)
     *(.gnu.warning)
   } =0
diff -prauN linux-2.6.0-test9-bk22/arch/parisc/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/parisc/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/parisc/kernel/vmlinux.lds.S	2003-10-25 11:43:05.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/parisc/kernel/vmlinux.lds.S	2003-11-18 19:07:15.000000000 -0800
@@ -24,6 +24,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text BLOCK(16) : {
 	*(.text*)
+	__scheduling_functions_start_here = .;
+	*(.sched.text)
+	__scheduling_functions_end_here =.;
 	*(.PARISC.unwind)
 	*(.fixup)
 	*(.lock.text)		/* out-of-line lock text */
diff -prauN linux-2.6.0-test9-bk22/arch/ppc/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/ppc/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/ppc/kernel/process.c	2003-10-25 11:43:35.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/ppc/kernel/process.c	2003-11-17 23:25:35.000000000 -0800
@@ -650,11 +650,6 @@ void __init ll_puts(const char *s)
 /*
  * 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)
 {
 	unsigned long ip, sp;
@@ -669,7 +664,8 @@ unsigned long get_wchan(struct task_stru
 			return 0;
 		if (count > 0) {
 			ip = *(unsigned long *)(sp + 4);
-			if (ip < first_sched || ip >= last_sched)
+			if (ip < scheduling_functions_start_here ||
+					ip >= scheduling_functions_end_here)
 				return ip;
 		}
 	} while (count++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/ppc/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/ppc/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/ppc/kernel/vmlinux.lds.S	2003-11-17 22:51:23.000000000 -0800
+++ wchan-2.6.0-test9-bk22-1/arch/ppc/kernel/vmlinux.lds.S	2003-11-18 19:06:32.000000000 -0800
@@ -31,6 +31,9 @@ SECTIONS
   .text      :
   {
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.sched.text)
+    __scheduling_functions_end_here = .;
     *(.fixup)
     *(.got1)
     __got2_start = .;
diff -prauN linux-2.6.0-test9-bk22/arch/ppc64/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/ppc64/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/ppc64/kernel/process.c	2003-10-25 11:43:54.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/ppc64/kernel/process.c	2003-11-17 23:26:08.000000000 -0800
@@ -369,11 +369,6 @@ out:
 /*
  * 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)
 {
 	unsigned long ip, sp;
@@ -393,7 +388,8 @@ unsigned long get_wchan(struct task_stru
 			 * XXX we mask the upper 32 bits until procps
 			 * gets fixed.
 			 */
-			if (ip < first_sched || ip >= last_sched)
+			if (ip < scheduling_functions_start_here ||
+					ip >= scheduling_functions_end_here)
 				return (ip & 0xFFFFFFFF);
 		}
 	} while (count++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/ppc64/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/ppc64/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/ppc64/kernel/vmlinux.lds.S	2003-10-25 11:44:15.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/ppc64/kernel/vmlinux.lds.S	2003-11-18 19:07:08.000000000 -0800
@@ -33,6 +33,9 @@ SECTIONS
   .text      :
   {
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.sched.text)
+    __scheduling_functions_end_here = .;
     *(.fixup)
     *(.got1)
   }
diff -prauN linux-2.6.0-test9-bk22/arch/s390/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/s390/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/s390/kernel/process.c	2003-10-25 11:44:17.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/s390/kernel/process.c	2003-11-17 23:26:43.000000000 -0800
@@ -371,11 +371,6 @@ void dump_thread(struct pt_regs * regs, 
 /*
  * 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)
 {
 	unsigned long r14, r15, bc;
@@ -398,12 +393,10 @@ unsigned long get_wchan(struct task_stru
 #else
 		r14 = *(unsigned long *) (bc+112);
 #endif
-		if (r14 < first_sched || r14 >= last_sched)
+		if (r14 < scheduling_functions_start_here ||
+				r14 >= scheduling_functions_end_here)
 			return r14;
 		bc = (*(unsigned long *) bc) & PSW_ADDR_INSN;
 	} while (count++ < 16);
 	return 0;
 }
-#undef last_sched
-#undef first_sched
-
diff -prauN linux-2.6.0-test9-bk22/arch/s390/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/s390/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/s390/kernel/vmlinux.lds.S	2003-10-25 11:43:23.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/s390/kernel/vmlinux.lds.S	2003-11-18 19:07:33.000000000 -0800
@@ -23,6 +23,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.sched.text)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x0700
diff -prauN linux-2.6.0-test9-bk22/arch/sh/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/sh/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/sh/kernel/process.c	2003-10-25 11:44:08.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/sh/kernel/process.c	2003-11-17 23:28:29.000000000 -0800
@@ -375,11 +375,6 @@ out:
 /*
  * 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)
 {
 	unsigned long schedule_frame;
diff -prauN linux-2.6.0-test9-bk22/arch/sh/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/sh/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/sh/kernel/vmlinux.lds.S	2003-10-25 11:43:49.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/sh/kernel/vmlinux.lds.S	2003-11-18 19:06:43.000000000 -0800
@@ -22,6 +22,9 @@ SECTIONS
 	} = 0
   .text : {
 	*(.text)
+	__scheduling_functions_start_here =.;
+	*(.sched.text)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x0009
diff -prauN linux-2.6.0-test9-bk22/arch/sparc/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/sparc/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/sparc/kernel/process.c	2003-10-25 11:43:00.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/sparc/kernel/process.c	2003-11-17 23:29:13.000000000 -0800
@@ -692,9 +692,6 @@ pid_t kernel_thread(int (*fn)(void *), v
 	return retval;
 }
 
-extern void scheduling_functions_start_here(void);
-extern void scheduling_functions_end_here(void);
-
 unsigned long get_wchan(struct task_struct *task)
 {
 	unsigned long pc, fp, bias = 0;
@@ -715,8 +712,8 @@ unsigned long get_wchan(struct task_stru
 			break;
 		rw = (struct reg_window *) fp;
 		pc = rw->ins[7];
-		if (pc < ((unsigned long) scheduling_functions_start_here) ||
-                    pc >= ((unsigned long) scheduling_functions_end_here)) {
+		if (pc < scheduling_functions_start_here ||
+                    pc >= scheduling_functions_end_here) {
 			ret = pc;
 			goto out;
 		}
diff -prauN linux-2.6.0-test9-bk22/arch/sparc/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/sparc/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/sparc/kernel/vmlinux.lds.S	2003-10-25 11:42:53.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/sparc/kernel/vmlinux.lds.S	2003-11-18 19:06:28.000000000 -0800
@@ -12,6 +12,9 @@ SECTIONS
   .text 0xf0004000 :
   {
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.sched.text)
+    __scheduling_functions_end_here = .;
     *(.gnu.warning)
   } =0
   _etext = .;
diff -prauN linux-2.6.0-test9-bk22/arch/sparc64/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/sparc64/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/sparc64/kernel/process.c	2003-10-25 11:43:30.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/sparc64/kernel/process.c	2003-11-17 23:29:28.000000000 -0800
@@ -824,9 +824,6 @@ out:
 	return error;
 }
 
-extern void scheduling_functions_start_here(void);
-extern void scheduling_functions_end_here(void);
-
 unsigned long get_wchan(struct task_struct *task)
 {
 	unsigned long pc, fp, bias = 0;
@@ -850,8 +847,8 @@ unsigned long get_wchan(struct task_stru
 			break;
 		rw = (struct reg_window *) fp;
 		pc = rw->ins[7];
-		if (pc < ((unsigned long) scheduling_functions_start_here) ||
-		    pc >= ((unsigned long) scheduling_functions_end_here)) {
+		if (pc < scheduling_functions_start_here ||
+		    pc >= scheduling_functions_end_here) {
 			ret = pc;
 			goto out;
 		}
diff -prauN linux-2.6.0-test9-bk22/arch/sparc64/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/sparc64/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/sparc64/kernel/vmlinux.lds.S	2003-10-25 11:44:36.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/sparc64/kernel/vmlinux.lds.S	2003-11-18 19:06:23.000000000 -0800
@@ -15,6 +15,9 @@ SECTIONS
   .text 0x0000000000404000 :
   {
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.sched.text)
+    __scheduling_functions_end_here = .;
     *(.gnu.warning)
   } =0
   _etext = .;
diff -prauN linux-2.6.0-test9-bk22/arch/v850/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/v850/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/v850/kernel/process.c	2003-10-25 11:43:02.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/v850/kernel/process.c	2003-11-18 00:47:03.000000000 -0800
@@ -203,11 +203,6 @@ int sys_execve (char *name, char **argv,
 /*
  * 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 0  /* Barf.  Figure out the stack-layout later.  XXX  */
@@ -221,15 +216,16 @@ unsigned long get_wchan (struct task_str
 
 	/* This quite disgusting function walks up the stack, following
 	   saved return address, until it something that's out of bounds
-	   (as defined by `first_sched' and `last_sched').  It then
-	   returns the last PC that was in-bounds.  */
+	   (as defined by `scheduling_functions_start_here' and
+	   `scheduling_functions_end_here').  It then returns the last
+	   PC that was in-bounds.  */
 	do {
-		if (fp < stack_page + sizeof (struct task_struct) ||
-		    fp >= 8184+stack_page)
+		if (fp < stack_page + sizeof(struct thread_info) ||
+		    fp >= THREAD_SIZE + stack_page - 8)
 			return 0;
 		pc = ((unsigned long *)fp)[1];
-		/* FIXME: This depends on the order of these functions. */
-		if (pc < first_sched || pc >= last_sched)
+		if (pc < scheduling_functions_start_here ||
+				pc >= scheduling_functions_end_here)
 			return pc;
 		fp = *(unsigned long *) fp;
 	} while (count++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/v850/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/v850/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/v850/kernel/vmlinux.lds.S	2003-10-25 11:43:58.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/v850/kernel/vmlinux.lds.S	2003-11-18 19:07:25.000000000 -0800
@@ -64,6 +64,9 @@
 #define TEXT_CONTENTS							      \
 		__stext = . ;						      \
         	*(.text)						      \
+		__scheduling_functions_start_here = .;
+		*(.sched.text)
+		__scheduling_functions_end_here = .;
 			*(.exit.text)	/* 2.5 convention */		      \
 			*(.text.exit)	/* 2.4 convention */		      \
 			*(.text.lock)					      \
diff -prauN linux-2.6.0-test9-bk22/arch/x86_64/kernel/process.c wchan-2.6.0-test9-bk22-1/arch/x86_64/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/x86_64/kernel/process.c	2003-10-25 11:43:49.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/x86_64/kernel/process.c	2003-11-17 23:30:38.000000000 -0800
@@ -528,11 +528,6 @@ asmlinkage long sys_vfork(struct pt_regs
 /*
  * 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)
 {
 	u64 fp,rip;
@@ -547,14 +542,13 @@ unsigned long get_wchan(struct task_stru
 		if (fp < (unsigned long)p || fp > (unsigned long)p+THREAD_SIZE)
 			return 0; 
 		rip = *(u64 *)(fp+8); 
-		if (rip < first_sched || rip >= last_sched)
+		if (rip < scheduling_functions_start_here ||
+				rip >= scheduling_functions_end_here)
 			return rip; 
 		fp = *(u64 *)fp; 
 	} while (count++ < 16); 
 	return 0;
 }
-#undef last_sched
-#undef first_sched
 
 long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
 { 
diff -prauN linux-2.6.0-test9-bk22/arch/x86_64/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-1/arch/x86_64/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/x86_64/kernel/vmlinux.lds.S	2003-10-25 11:42:51.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/arch/x86_64/kernel/vmlinux.lds.S	2003-11-18 19:07:18.000000000 -0800
@@ -14,6 +14,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.sched.text)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x9090
diff -prauN linux-2.6.0-test9-bk22/include/linux/init.h wchan-2.6.0-test9-bk22-1/include/linux/init.h
--- linux-2.6.0-test9-bk22/include/linux/init.h	2003-10-25 11:42:50.000000000 -0700
+++ wchan-2.6.0-test9-bk22-1/include/linux/init.h	2003-11-18 19:05:04.000000000 -0800
@@ -45,6 +45,8 @@
 #define __exitdata	__attribute__ ((__section__(".exit.data")))
 #define __exit_call	__attribute_used__ __attribute__ ((__section__ (".exitcall.exit")))
 
+#define __sched		__attribute__((__section__(".sched.text")))
+
 #ifdef MODULE
 #define __exit		__attribute__ ((__section__(".exit.text")))
 #else
diff -prauN linux-2.6.0-test9-bk22/include/linux/sched.h wchan-2.6.0-test9-bk22-1/include/linux/sched.h
--- linux-2.6.0-test9-bk22/include/linux/sched.h	2003-11-17 22:51:24.000000000 -0800
+++ wchan-2.6.0-test9-bk22-1/include/linux/sched.h	2003-11-17 23:01:42.000000000 -0800
@@ -169,6 +169,8 @@ extern void update_one_process(struct ta
 			       unsigned long system, int cpu);
 extern void scheduler_tick(int user_tick, int system);
 extern unsigned long cache_decay_ticks;
+extern const unsigned long scheduling_functions_start_here;
+extern const unsigned long scheduling_functions_end_here;
 
 
 #define	MAX_SCHEDULE_TIMEOUT	LONG_MAX
diff -prauN linux-2.6.0-test9-bk22/kernel/sched.c wchan-2.6.0-test9-bk22-1/kernel/sched.c
--- linux-2.6.0-test9-bk22/kernel/sched.c	2003-11-17 22:51:24.000000000 -0800
+++ wchan-2.6.0-test9-bk22-1/kernel/sched.c	2003-11-17 23:01:42.000000000 -0800
@@ -221,6 +221,13 @@ static DEFINE_PER_CPU(struct runqueue, r
 #define task_rq(p)		cpu_rq(task_cpu(p))
 #define cpu_curr(cpu)		(cpu_rq(cpu)->curr)
 
+extern unsigned long __scheduling_functions_start_here;
+extern unsigned long __scheduling_functions_end_here;
+const unsigned long scheduling_functions_start_here =
+			(unsigned long)&__scheduling_functions_start_here;
+const unsigned long scheduling_functions_end_here =
+			(unsigned long)&__scheduling_functions_end_here;
+
 /*
  * Default context-switch locking:
  */
@@ -1463,12 +1470,10 @@ out:
 	rebalance_tick(rq, 0);
 }
 
-void scheduling_functions_start_here(void) { }
-
 /*
  * schedule() is the main scheduler function.
  */
-asmlinkage void schedule(void)
+asmlinkage __sched void schedule(void)
 {
 	task_t *prev, *next;
 	runqueue_t *rq;
@@ -1611,7 +1616,7 @@ EXPORT_SYMBOL(schedule);
  * off of preempt_enable.  Kernel preemptions off return from interrupt
  * occur there and call schedule directly.
  */
-asmlinkage void preempt_schedule(void)
+asmlinkage __sched void preempt_schedule(void)
 {
 	struct thread_info *ti = current_thread_info();
 
@@ -1636,7 +1641,7 @@ need_resched:
 EXPORT_SYMBOL(preempt_schedule);
 #endif /* CONFIG_PREEMPT */
 
-int default_wake_function(wait_queue_t *curr, unsigned mode, int sync)
+__sched int default_wake_function(wait_queue_t *curr, unsigned mode, int sync)
 {
 	task_t *p = curr->task;
 	return try_to_wake_up(p, mode, sync);
@@ -1653,7 +1658,7 @@ EXPORT_SYMBOL(default_wake_function);
  * started to run but is not in state TASK_RUNNING.  try_to_wake_up() returns
  * zero in this (rare) case, and we handle it by continuing to scan the queue.
  */
-static void __wake_up_common(wait_queue_head_t *q, unsigned int mode, int nr_exclusive, int sync)
+static __sched void __wake_up_common(wait_queue_head_t *q, unsigned int mode, int nr_exclusive, int sync)
 {
 	struct list_head *tmp, *next;
 
@@ -1675,7 +1680,7 @@ static void __wake_up_common(wait_queue_
  * @mode: which threads
  * @nr_exclusive: how many wake-one or wake-many threads to wake up
  */
-void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
+__sched void __wake_up(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
 {
 	unsigned long flags;
 
@@ -1707,7 +1712,7 @@ void __wake_up_locked(wait_queue_head_t 
  *
  * On UP it can prevent extra preemption.
  */
-void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
+__sched void __wake_up_sync(wait_queue_head_t *q, unsigned int mode, int nr_exclusive)
 {
 	unsigned long flags;
 
@@ -1724,7 +1729,7 @@ void __wake_up_sync(wait_queue_head_t *q
 
 EXPORT_SYMBOL_GPL(__wake_up_sync);	/* For internal use only */
 
-void complete(struct completion *x)
+__sched void complete(struct completion *x)
 {
 	unsigned long flags;
 
@@ -1736,7 +1741,7 @@ void complete(struct completion *x)
 
 EXPORT_SYMBOL(complete);
 
-void complete_all(struct completion *x)
+__sched void complete_all(struct completion *x)
 {
 	unsigned long flags;
 
@@ -1746,7 +1751,7 @@ void complete_all(struct completion *x)
 	spin_unlock_irqrestore(&x->wait.lock, flags);
 }
 
-void wait_for_completion(struct completion *x)
+__sched void wait_for_completion(struct completion *x)
 {
 	might_sleep();
 	spin_lock_irq(&x->wait.lock);
@@ -1784,7 +1789,7 @@ EXPORT_SYMBOL(wait_for_completion);
 	__remove_wait_queue(q, &wait);				\
 	spin_unlock_irqrestore(&q->lock, flags);
 
-void interruptible_sleep_on(wait_queue_head_t *q)
+__sched void interruptible_sleep_on(wait_queue_head_t *q)
 {
 	SLEEP_ON_VAR
 
@@ -1797,7 +1802,7 @@ void interruptible_sleep_on(wait_queue_h
 
 EXPORT_SYMBOL(interruptible_sleep_on);
 
-long interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
+__sched long interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
 	SLEEP_ON_VAR
 
@@ -1812,7 +1817,7 @@ long interruptible_sleep_on_timeout(wait
 
 EXPORT_SYMBOL(interruptible_sleep_on_timeout);
 
-void sleep_on(wait_queue_head_t *q)
+__sched void sleep_on(wait_queue_head_t *q)
 {
 	SLEEP_ON_VAR
 
@@ -1825,7 +1830,7 @@ void sleep_on(wait_queue_head_t *q)
 
 EXPORT_SYMBOL(sleep_on);
 
-long sleep_on_timeout(wait_queue_head_t *q, long timeout)
+__sched long sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
 	SLEEP_ON_VAR
 
@@ -1840,8 +1845,6 @@ long sleep_on_timeout(wait_queue_head_t 
 
 EXPORT_SYMBOL(sleep_on_timeout);
 
-void scheduling_functions_end_here(void) { }
-
 void set_user_nice(task_t *p, long nice)
 {
 	unsigned long flags;
@@ -2291,7 +2294,7 @@ asmlinkage long sys_sched_yield(void)
 	return 0;
 }
 
-void __cond_resched(void)
+__sched void __cond_resched(void)
 {
 	set_current_state(TASK_RUNNING);
 	schedule();
@@ -2305,7 +2308,7 @@ EXPORT_SYMBOL(__cond_resched);
  * this is a shortcut for kernel-space yielding - it marks the
  * thread runnable and calls sys_sched_yield().
  */
-void yield(void)
+__sched void yield(void)
 {
 	set_current_state(TASK_RUNNING);
 	sys_sched_yield();
@@ -2320,7 +2323,7 @@ EXPORT_SYMBOL(yield);
  * But don't do that if it is a deliberate, throttling IO wait (this task
  * has set its backing_dev_info: the queue against which it should throttle)
  */
-void io_schedule(void)
+__sched void io_schedule(void)
 {
 	struct runqueue *rq = this_rq();
 
@@ -2331,7 +2334,7 @@ void io_schedule(void)
 
 EXPORT_SYMBOL(io_schedule);
 
-long io_schedule_timeout(long timeout)
+__sched long io_schedule_timeout(long timeout)
 {
 	struct runqueue *rq = this_rq();
 	long ret;
@@ -2881,7 +2884,7 @@ EXPORT_SYMBOL(__might_sleep);
  *
  * Called inside preempt_disable().
  */
-void __preempt_spin_lock(spinlock_t *lock)
+__sched void __preempt_spin_lock(spinlock_t *lock)
 {
 	if (preempt_count() > 1) {
 		_raw_spin_lock(lock);
@@ -2897,7 +2900,7 @@ void __preempt_spin_lock(spinlock_t *loc
 
 EXPORT_SYMBOL(__preempt_spin_lock);
 
-void __preempt_write_lock(rwlock_t *lock)
+__sched void __preempt_write_lock(rwlock_t *lock)
 {
 	if (preempt_count() > 1) {
 		_raw_write_lock(lock);
diff -prauN linux-2.6.0-test9-bk22/kernel/timer.c wchan-2.6.0-test9-bk22-1/kernel/timer.c
--- linux-2.6.0-test9-bk22/kernel/timer.c	2003-11-17 22:51:24.000000000 -0800
+++ wchan-2.6.0-test9-bk22-1/kernel/timer.c	2003-11-17 23:01:42.000000000 -0800
@@ -1000,7 +1000,7 @@ static void process_timeout(unsigned lon
  *
  * In all cases the return value is guaranteed to be non-negative.
  */
-signed long schedule_timeout(signed long timeout)
+__sched signed long schedule_timeout(signed long timeout)
 {
 	struct timer_list timer;
 	unsigned long expire;
@@ -1060,7 +1060,7 @@ asmlinkage long sys_gettid(void)
 	return current->pid;
 }
 
-static long nanosleep_restart(struct restart_block *restart)
+static __sched long nanosleep_restart(struct restart_block *restart)
 {
 	unsigned long expire = restart->arg0, now = jiffies;
 	struct timespec *rmtp = (struct timespec *) restart->arg1;

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: use ELF sections for get_wchan()
  2003-11-19  3:13       ` William Lee Irwin III
@ 2003-11-19  5:53         ` Sam Ravnborg
  2003-11-19  6:19           ` William Lee Irwin III
  0 siblings, 1 reply; 10+ messages in thread
From: Sam Ravnborg @ 2003-11-19  5:53 UTC (permalink / raw)
  To: William Lee Irwin III, linux-kernel

On Tue, Nov 18, 2003 at 07:13:37PM -0800, William Lee Irwin III wrote:
> willy said I should use .sched.text instead of .text.sched; this fixes
> it up to do that.

Hi wli,
how about utilising asm-generic/vmlinux.h.S now that you are touching so
many .lds files?
Something like the attached could be used?

That will simplify and consolidate the the .lds files, but full
flexibility remains.

I noticed that there were small diferences between the individual
architectures, but specifying only content of the section should allow
it to be used all over.

	Sam


===== include/asm-generic/vmlinux.lds.h 1.8 vs edited =====
--- 1.8/include/asm-generic/vmlinux.lds.h	Thu Jun 12 02:40:10 2003
+++ edited/include/asm-generic/vmlinux.lds.h	Wed Nov 19 06:48:40 2003
@@ -45,6 +45,15 @@
 		*(__ksymtab_strings)					\
 	}
 
+#define TEXT_CONTENT							\
+		_stext = .;						\
+		*(.text)						\
+		__schduling_functions_start_here = .;			\
+		*(.sched.text)						\
+		__scheduling_functions_end_here = .;			\
+		*(.fixup)						\
+		*(.gnu.warning)						
+
 #define SECURITY_INIT							\
 	.security_initcall.init : {					\
 		__security_initcall_start = .;				\

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: use ELF sections for get_wchan()
  2003-11-19  5:53         ` Sam Ravnborg
@ 2003-11-19  6:19           ` William Lee Irwin III
  0 siblings, 0 replies; 10+ messages in thread
From: William Lee Irwin III @ 2003-11-19  6:19 UTC (permalink / raw)
  To: linux-kernel

On Tue, Nov 18, 2003 at 07:13:37PM -0800, William Lee Irwin III wrote:
>> willy said I should use .sched.text instead of .text.sched; this fixes
>> it up to do that.

On Wed, Nov 19, 2003 at 06:53:32AM +0100, Sam Ravnborg wrote:
> Hi wli,
> how about utilising asm-generic/vmlinux.h.S now that you are touching so
> many .lds files?
> Something like the attached could be used?
> That will simplify and consolidate the the .lds files, but full
> flexibility remains.
> I noticed that there were small diferences between the individual
> architectures, but specifying only content of the section should allow
> it to be used all over.

This doesn't quite cover all cases, though I agree in principle. It
would probably be okay to rearrange the sections, but I'm vaguely
queasy about it turning into a cleanup.


-- wli

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: use ELF sections for get_wchan()
  2003-11-18  7:44 use ELF sections for get_wchan() William Lee Irwin III
  2003-11-18  8:43 ` Russell King
@ 2003-11-20 20:28 ` Anton Blanchard
  2003-11-20 20:50   ` William Lee Irwin III
  1 sibling, 1 reply; 10+ messages in thread
From: Anton Blanchard @ 2003-11-20 20:28 UTC (permalink / raw)
  To: William Lee Irwin III, linux-kernel


Hi,

> I noticed a bunch of "FIXME: this depends on the order of these
> functions" comments in/around wchan calculations.
> 
> So I decided I'd remove the dependency on the order of the functions by
> dumping them all into an ELF section with clear delimiters.

I like it. At the moment wchan is next to useless because everything
ends up in down* or something similar.

Anton

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: use ELF sections for get_wchan()
  2003-11-20 20:28 ` Anton Blanchard
@ 2003-11-20 20:50   ` William Lee Irwin III
  2003-11-20 22:55     ` William Lee Irwin III
  0 siblings, 1 reply; 10+ messages in thread
From: William Lee Irwin III @ 2003-11-20 20:50 UTC (permalink / raw)
  To: Anton Blanchard; +Cc: linux-kernel

At some point in the past, I wrote:
>> I noticed a bunch of "FIXME: this depends on the order of these
>> functions" comments in/around wchan calculations.
>> So I decided I'd remove the dependency on the order of the functions by
>> dumping them all into an ELF section with clear delimiters.

On Fri, Nov 21, 2003 at 07:28:15AM +1100, Anton Blanchard wrote:
> I like it. At the moment wchan is next to useless because everything
> ends up in down* or something similar.

down_*() aren't covered by this yet; I'll do a sweep for that and repost.


-- wli

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: use ELF sections for get_wchan()
  2003-11-20 20:50   ` William Lee Irwin III
@ 2003-11-20 22:55     ` William Lee Irwin III
  0 siblings, 0 replies; 10+ messages in thread
From: William Lee Irwin III @ 2003-11-20 22:55 UTC (permalink / raw)
  To: Anton Blanchard, linux-kernel

At some point in the past, I wrote:
>>> I noticed a bunch of "FIXME: this depends on the order of these
>>> functions" comments in/around wchan calculations.
>>> So I decided I'd remove the dependency on the order of the functions by
>>> dumping them all into an ELF section with clear delimiters.

On Fri, Nov 21, 2003 at 07:28:15AM +1100, Anton Blanchard wrote:
>> I like it. At the moment wchan is next to useless because everything
>> ends up in down* or something similar.

On Thu, Nov 20, 2003 at 12:50:15PM -0800, William Lee Irwin III wrote:
> down_*() aren't covered by this yet; I'll do a sweep for that and repost.

Okay, here is the updated patch:


diff -prauN linux-2.6.0-test9-bk22/arch/alpha/kernel/process.c wchan-2.6.0-test9-bk22-2/arch/alpha/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/alpha/kernel/process.c	2003-10-25 11:44:37.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/alpha/kernel/process.c	2003-11-17 23:20:01.000000000 -0800
@@ -513,11 +513,6 @@ thread_saved_pc(task_t *t)
 /*
  * 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)
 {
@@ -536,7 +531,8 @@ get_wchan(struct task_struct *p)
 	 */
 
 	pc = thread_saved_pc(p);
-	if (pc >= first_sched && pc < last_sched) {
+	if (pc >= scheduling_functions_start_here &&
+			pc < scheduling_functions_end_here) {
 		schedule_frame = ((unsigned long *)p->thread_info->pcb.ksp)[6];
 		return ((unsigned long *)schedule_frame)[12];
 	}
diff -prauN linux-2.6.0-test9-bk22/arch/alpha/kernel/semaphore.c wchan-2.6.0-test9-bk22-2/arch/alpha/kernel/semaphore.c
--- linux-2.6.0-test9-bk22/arch/alpha/kernel/semaphore.c	2003-10-25 11:43:41.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/alpha/kernel/semaphore.c	2003-11-20 14:13:28.000000000 -0800
@@ -7,6 +7,7 @@
 
 #include <linux/errno.h>
 #include <linux/sched.h>
+#include <linux/init.h>
 
 /*
  * Semaphores are implemented using a two-way counter:
@@ -52,7 +53,7 @@
  * Either form may be used in conjunction with "up()".
  */
 
-void
+__sched void
 __down_failed(struct semaphore *sem)
 {
 	DECLARE_WAITQUEUE(wait, current);
@@ -103,7 +104,7 @@ __down_failed(struct semaphore *sem)
 #endif
 }
 
-int
+__sched int
 __down_failed_interruptible(struct semaphore *sem)
 {
 	DECLARE_WAITQUEUE(wait, current);
@@ -201,7 +202,7 @@ __up_wakeup(struct semaphore *sem)
 	wake_up(&sem->wait);
 }
 
-void
+__sched void
 down(struct semaphore *sem)
 {
 #if WAITQUEUE_DEBUG
@@ -215,7 +216,7 @@ down(struct semaphore *sem)
 	__down(sem);
 }
 
-int
+__sched int
 down_interruptible(struct semaphore *sem)
 {
 #if WAITQUEUE_DEBUG
diff -prauN linux-2.6.0-test9-bk22/arch/alpha/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-2/arch/alpha/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/alpha/kernel/vmlinux.lds.S	2003-10-25 11:43:42.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/alpha/kernel/vmlinux.lds.S	2003-11-18 19:07:05.000000000 -0800
@@ -17,6 +17,9 @@ SECTIONS
   _text = .;					/* Text and read-only data */
   .text : { 
 	*(.text) 
+	__scheduling_functions_start_here = .;
+	*(.sched.text)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
   } :kernel
diff -prauN linux-2.6.0-test9-bk22/arch/arm/kernel/process.c wchan-2.6.0-test9-bk22-2/arch/arm/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/arm/kernel/process.c	2003-10-25 11:44:41.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/arm/kernel/process.c	2003-11-17 23:20:24.000000000 -0800
@@ -415,11 +415,6 @@ pid_t kernel_thread(int (*fn)(void *), v
 /*
  * 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)
 {
 	unsigned long fp, lr;
@@ -434,7 +429,8 @@ unsigned long get_wchan(struct task_stru
 		if (fp < stack_page || fp > 4092+stack_page)
 			return 0;
 		lr = pc_pointer (((unsigned long *)fp)[-1]);
-		if (lr < first_sched || lr > last_sched)
+		if (lr < scheduling_functions_start_here ||
+				lr > scheduling_functions_end_here)
 			return lr;
 		fp = *(unsigned long *) (fp - 12);
 	} while (count ++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/arm/kernel/semaphore.c wchan-2.6.0-test9-bk22-2/arch/arm/kernel/semaphore.c
--- linux-2.6.0-test9-bk22/arch/arm/kernel/semaphore.c	2003-10-25 11:43:29.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/arm/kernel/semaphore.c	2003-11-20 14:13:35.000000000 -0800
@@ -13,6 +13,7 @@
  */
 #include <linux/sched.h>
 #include <linux/errno.h>
+#include <linux/init.h>
 
 #include <asm/semaphore.h>
 
@@ -54,7 +55,7 @@ void __up(struct semaphore *sem)
 
 static spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED;
 
-void __down(struct semaphore * sem)
+__sched void __down(struct semaphore * sem)
 {
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
@@ -87,7 +88,7 @@ void __down(struct semaphore * sem)
 	wake_up(&sem->wait);
 }
 
-int __down_interruptible(struct semaphore * sem)
+__sched int __down_interruptible(struct semaphore * sem)
 {
 	int retval = 0;
 	struct task_struct *tsk = current;
@@ -176,7 +177,8 @@ int __down_trylock(struct semaphore * se
  * registers (r0 to r3 and lr), but not ip, as we use it as a return
  * value in some cases..
  */
-asm("	.align	5				\n\
+asm("	.section .sched.text			\n\
+	.align	5				\n\
 	.globl	__down_failed			\n\
 __down_failed:					\n\
 	stmfd	sp!, {r0 - r3, lr}		\n\
diff -prauN linux-2.6.0-test9-bk22/arch/arm/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-2/arch/arm/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/arm/kernel/vmlinux.lds.S	2003-10-25 11:43:22.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/arm/kernel/vmlinux.lds.S	2003-11-18 19:07:12.000000000 -0800
@@ -73,6 +73,9 @@ SECTIONS
 	.text : {			/* Real text segment		*/
 		_text = .;		/* Text and read-only data	*/
 			*(.text)
+			__scheduling_functions_start_here = .;
+			*(.sched.text)
+			__scheduling_functions_end_here = .;
 			*(.fixup)
 			*(.gnu.warning)
 			*(.rodata)
diff -prauN linux-2.6.0-test9-bk22/arch/arm26/kernel/process.c wchan-2.6.0-test9-bk22-2/arch/arm26/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/arm26/kernel/process.c	2003-10-25 11:44:39.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/arm26/kernel/process.c	2003-11-17 23:20:47.000000000 -0800
@@ -400,11 +400,6 @@ pid_t kernel_thread(int (*fn)(void *), v
 /*
  * 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)
 {
 	unsigned long fp, lr;
@@ -419,7 +414,8 @@ unsigned long get_wchan(struct task_stru
 		if (fp < stack_page || fp > 4092+stack_page)
 			return 0;
 		lr = pc_pointer (((unsigned long *)fp)[-1]);
-		if (lr < first_sched || lr > last_sched)
+		if (lr < scheduling_functions_start_here ||
+				lr > scheduling_functions_end_here)
 			return lr;
 		fp = *(unsigned long *) (fp - 12);
 	} while (count ++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/arm26/kernel/semaphore.c wchan-2.6.0-test9-bk22-2/arch/arm26/kernel/semaphore.c
--- linux-2.6.0-test9-bk22/arch/arm26/kernel/semaphore.c	2003-10-25 11:43:15.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/arm26/kernel/semaphore.c	2003-11-20 14:13:43.000000000 -0800
@@ -15,6 +15,7 @@
 #include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
+#include <linux/init.h>
 
 #include <asm/semaphore.h>
 
@@ -56,7 +57,7 @@ void __up(struct semaphore *sem)
 
 static spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED;
 
-void __down(struct semaphore * sem)
+__sched void __down(struct semaphore * sem)
 {
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
@@ -89,7 +90,7 @@ void __down(struct semaphore * sem)
 	wake_up(&sem->wait);
 }
 
-int __down_interruptible(struct semaphore * sem)
+__sched int __down_interruptible(struct semaphore * sem)
 {
 	int retval = 0;
 	struct task_struct *tsk = current;
@@ -178,7 +179,8 @@ int __down_trylock(struct semaphore * se
  * registers (r0 to r3 and lr), but not ip, as we use it as a return
  * value in some cases..
  */
-asm("	.align	5				\n\
+asm("	.section .sched.text			\n\
+	.align	5				\n\
 	.globl	__down_failed			\n\
 __down_failed:					\n\
 	stmfd	sp!, {r0 - r3, lr}		\n\
diff -prauN linux-2.6.0-test9-bk22/arch/arm26/kernel/vmlinux-arm26-xip.lds.in wchan-2.6.0-test9-bk22-2/arch/arm26/kernel/vmlinux-arm26-xip.lds.in
--- linux-2.6.0-test9-bk22/arch/arm26/kernel/vmlinux-arm26-xip.lds.in	2003-10-25 11:44:34.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/arm26/kernel/vmlinux-arm26-xip.lds.in	2003-11-18 19:06:51.000000000 -0800
@@ -66,6 +66,9 @@ SECTIONS
 	.text : {			/* Real text segment		*/
 		_text = .;		/* Text and read-only data	*/
 			*(.text)
+			__scheduling_functions_start_here = .;
+			*(.sched.text)
+			__scheduling_functions_end_here = .;
 			*(.fixup)
 			*(.gnu.warning)
 			*(.rodata)
diff -prauN linux-2.6.0-test9-bk22/arch/arm26/kernel/vmlinux-arm26.lds.in wchan-2.6.0-test9-bk22-2/arch/arm26/kernel/vmlinux-arm26.lds.in
--- linux-2.6.0-test9-bk22/arch/arm26/kernel/vmlinux-arm26.lds.in	2003-10-25 11:42:56.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/arm26/kernel/vmlinux-arm26.lds.in	2003-11-18 19:06:47.000000000 -0800
@@ -67,6 +67,9 @@ SECTIONS
 	.text : {			/* Real text segment		*/
 		_text = .;		/* Text and read-only data	*/
 			*(.text)
+			__scheduling_functions_start_here = .;
+			*(.sched.text)
+			__scheduling_functions_end_here = .;
 			*(.fixup)
 			*(.gnu.warning)
 			*(.rodata)
diff -prauN linux-2.6.0-test9-bk22/arch/cris/arch-v10/vmlinux.lds.S wchan-2.6.0-test9-bk22-2/arch/cris/arch-v10/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/cris/arch-v10/vmlinux.lds.S	2003-10-25 11:43:29.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/cris/arch-v10/vmlinux.lds.S	2003-11-18 19:06:39.000000000 -0800
@@ -25,6 +25,9 @@ SECTIONS
 	__stext = .;
 	.text : {
 		*(.text)
+		__scheduling_functions_start_here = .;
+		*(.sched.text)
+		__scheduling_functions_end_here = .;
 		*(.fixup)
 		*(.text.__*)
 	}
diff -prauN linux-2.6.0-test9-bk22/arch/cris/kernel/semaphore.c wchan-2.6.0-test9-bk22-2/arch/cris/kernel/semaphore.c
--- linux-2.6.0-test9-bk22/arch/cris/kernel/semaphore.c	2003-10-25 11:43:21.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/cris/kernel/semaphore.c	2003-11-20 14:13:57.000000000 -0800
@@ -4,6 +4,7 @@
  */
 
 #include <linux/sched.h>
+#include <linux/init.h>
 #include <asm/semaphore-helper.h>
 
 /*
@@ -94,7 +95,7 @@ void __up(struct semaphore *sem)
 	tsk->state = TASK_RUNNING;		\
 	remove_wait_queue(&sem->wait, &wait);
 
-void __down(struct semaphore * sem)
+__sched void __down(struct semaphore * sem)
 {
 	DOWN_VAR
 	DOWN_HEAD(TASK_UNINTERRUPTIBLE)
@@ -104,7 +105,7 @@ void __down(struct semaphore * sem)
 	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
 }
 
-int __down_interruptible(struct semaphore * sem)
+__sched int __down_interruptible(struct semaphore * sem)
 {
 	int ret = 0;
 	DOWN_VAR
diff -prauN linux-2.6.0-test9-bk22/arch/h8300/kernel/process.c wchan-2.6.0-test9-bk22-2/arch/h8300/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/h8300/kernel/process.c	2003-10-25 11:42:43.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/h8300/kernel/process.c	2003-11-17 23:21:15.000000000 -0800
@@ -264,11 +264,6 @@ out:
 /*
  * 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 thread_saved_pc(struct task_struct *tsk)
 {
 	return ((struct pt_regs *)tsk->thread.esp0)->pc;
@@ -289,8 +284,8 @@ unsigned long get_wchan(struct task_stru
 		    fp >= 8184+stack_page)
 			return 0;
 		pc = ((unsigned long *)fp)[1];
-		/* FIXME: This depends on the order of these functions. */
-		if (pc < first_sched || pc >= last_sched)
+		if (pc < scheduling_functions_start_here ||
+				pc >= scheduling_functions_end_here)
 			return pc;
 		fp = *(unsigned long *) fp;
 	} while (count++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/h8300/kernel/semaphore.c wchan-2.6.0-test9-bk22-2/arch/h8300/kernel/semaphore.c
--- linux-2.6.0-test9-bk22/arch/h8300/kernel/semaphore.c	2003-10-25 11:43:51.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/h8300/kernel/semaphore.c	2003-11-20 14:14:11.000000000 -0800
@@ -5,6 +5,7 @@
 
 #include <linux/config.h>
 #include <linux/sched.h>
+#include <linux/init.h>
 #include <asm/semaphore-helper.h>
 
 #ifndef CONFIG_RMW_INSNS
@@ -95,7 +96,7 @@ void __up(struct semaphore *sem)
 	current->state = TASK_RUNNING;		\
 	remove_wait_queue(&sem->wait, &wait);
 
-void __down(struct semaphore * sem)
+__sched void __down(struct semaphore * sem)
 {
 	DECLARE_WAITQUEUE(wait, current);
 
@@ -106,7 +107,7 @@ void __down(struct semaphore * sem)
 	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
 }
 
-int __down_interruptible(struct semaphore * sem)
+__sched int __down_interruptible(struct semaphore * sem)
 {
 	DECLARE_WAITQUEUE(wait, current);
 	int ret = 0;
diff -prauN linux-2.6.0-test9-bk22/arch/h8300/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-2/arch/h8300/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/h8300/kernel/vmlinux.lds.S	2003-10-25 11:43:54.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/h8300/kernel/vmlinux.lds.S	2003-11-18 19:07:21.000000000 -0800
@@ -82,6 +82,9 @@ SECTIONS
 #endif
 	__stext = . ;
         	*(.text)
+	__scheduling_functions_start_here = .;
+		*(.sched.text)
+	__scheduling_functions_end_here = .;
 	. = ALIGN(0x4) ;
 		*(.exit.text)
 		*(.text.*)
diff -prauN linux-2.6.0-test9-bk22/arch/i386/kernel/process.c wchan-2.6.0-test9-bk22-2/arch/i386/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/i386/kernel/process.c	2003-10-25 11:42:40.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/i386/kernel/process.c	2003-11-17 23:03:54.000000000 -0800
@@ -631,11 +631,6 @@ out:
 /*
  * 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)
 {
 	unsigned long ebp, esp, eip;
@@ -653,14 +648,13 @@ unsigned long get_wchan(struct task_stru
 		if (ebp < stack_page || ebp > 8184+stack_page)
 			return 0;
 		eip = *(unsigned long *) (ebp+4);
-		if (eip < first_sched || eip >= last_sched)
+		if (eip < scheduling_functions_start_here ||
+				eip >= scheduling_functions_end_here)
 			return eip;
 		ebp = *(unsigned long *) ebp;
 	} while (count++ < 16);
 	return 0;
 }
-#undef last_sched
-#undef first_sched
 
 /*
  * sys_alloc_thread_area: get a yet unused TLS descriptor index.
diff -prauN linux-2.6.0-test9-bk22/arch/i386/kernel/semaphore.c wchan-2.6.0-test9-bk22-2/arch/i386/kernel/semaphore.c
--- linux-2.6.0-test9-bk22/arch/i386/kernel/semaphore.c	2003-10-25 11:43:30.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/i386/kernel/semaphore.c	2003-11-20 14:24:24.000000000 -0800
@@ -15,6 +15,7 @@
 #include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/err.h>
+#include <linux/init.h>
 #include <asm/semaphore.h>
 
 /*
@@ -53,7 +54,7 @@ void __up(struct semaphore *sem)
 	wake_up(&sem->wait);
 }
 
-void __down(struct semaphore * sem)
+__sched void __down(struct semaphore * sem)
 {
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
@@ -90,7 +91,7 @@ void __down(struct semaphore * sem)
 	tsk->state = TASK_RUNNING;
 }
 
-int __down_interruptible(struct semaphore * sem)
+__sched int __down_interruptible(struct semaphore * sem)
 {
 	int retval = 0;
 	struct task_struct *tsk = current;
@@ -187,7 +188,7 @@ int __down_trylock(struct semaphore * se
  * value..
  */
 asm(
-".text\n"
+".section .sched.text\n"
 ".align 4\n"
 ".globl __down_failed\n"
 "__down_failed:\n\t"
@@ -210,7 +211,7 @@ asm(
 );
 
 asm(
-".text\n"
+".section .sched.text\n"
 ".align 4\n"
 ".globl __down_failed_interruptible\n"
 "__down_failed_interruptible:\n\t"
@@ -231,7 +232,7 @@ asm(
 );
 
 asm(
-".text\n"
+".section .sched.text\n"
 ".align 4\n"
 ".globl __down_failed_trylock\n"
 "__down_failed_trylock:\n\t"
@@ -252,7 +253,7 @@ asm(
 );
 
 asm(
-".text\n"
+".section .sched.text\n"
 ".align 4\n"
 ".globl __up_wakeup\n"
 "__up_wakeup:\n\t"
@@ -271,7 +272,7 @@ asm(
  */
 #if defined(CONFIG_SMP)
 asm(
-".text\n"
+".section .sched.text\n"
 ".align	4\n"
 ".globl	__write_lock_failed\n"
 "__write_lock_failed:\n\t"
@@ -285,7 +286,7 @@ asm(
 );
 
 asm(
-".text\n"
+".section .sched.text\n"
 ".align	4\n"
 ".globl	__read_lock_failed\n"
 "__read_lock_failed:\n\t"
diff -prauN linux-2.6.0-test9-bk22/arch/i386/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-2/arch/i386/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/i386/kernel/vmlinux.lds.S	2003-10-25 11:43:05.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/i386/kernel/vmlinux.lds.S	2003-11-18 19:05:54.000000000 -0800
@@ -15,6 +15,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.sched.text)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x9090
diff -prauN linux-2.6.0-test9-bk22/arch/ia64/kernel/process.c wchan-2.6.0-test9-bk22-2/arch/ia64/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/ia64/kernel/process.c	2003-10-25 11:43:35.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/ia64/kernel/process.c	2003-11-17 23:31:04.000000000 -0800
@@ -638,11 +638,6 @@ get_wchan (struct task_struct *p)
 	/*
 	 * 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)
-
 	/*
 	 * Note: p may not be a blocked task (it could be current or
 	 * another process running on some other CPU.  Rather than
@@ -656,12 +651,11 @@ get_wchan (struct task_struct *p)
 		if (unw_unwind(&info) < 0)
 			return 0;
 		unw_get_ip(&info, &ip);
-		if (ip < first_sched || ip >= last_sched)
+		if (ip < scheduling_functions_start_here ||
+				ip >= scheduling_functions_end_here)
 			return ip;
 	} while (count++ < 16);
 	return 0;
-#	undef first_sched
-#	undef last_sched
 }
 
 void
diff -prauN linux-2.6.0-test9-bk22/arch/ia64/kernel/semaphore.c wchan-2.6.0-test9-bk22-2/arch/ia64/kernel/semaphore.c
--- linux-2.6.0-test9-bk22/arch/ia64/kernel/semaphore.c	2003-10-25 11:43:30.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/ia64/kernel/semaphore.c	2003-11-20 14:15:14.000000000 -0800
@@ -24,6 +24,7 @@
  * <asm/semaphore.h> where we want to avoid any extra jumps and calls.
  */
 #include <linux/sched.h>
+#include <linux/init.h>
 
 #include <asm/errno.h>
 #include <asm/semaphore.h>
@@ -44,7 +45,7 @@ __up (struct semaphore *sem)
 	wake_up(&sem->wait);
 }
 
-void
+__sched void
 __down (struct semaphore *sem)
 {
 	struct task_struct *tsk = current;
@@ -82,7 +83,7 @@ __down (struct semaphore *sem)
 	tsk->state = TASK_RUNNING;
 }
 
-int
+__sched int
 __down_interruptible (struct semaphore * sem)
 {
 	int retval = 0;
diff -prauN linux-2.6.0-test9-bk22/arch/ia64/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-2/arch/ia64/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/ia64/kernel/vmlinux.lds.S	2003-10-25 11:44:35.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/ia64/kernel/vmlinux.lds.S	2003-11-18 19:07:02.000000000 -0800
@@ -35,6 +35,9 @@ SECTIONS
     {
 	*(.text.ivt)
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.sched.text)
+	__scheduling_functions_end_here = .;
 	*(.gnu.linkonce.t*)
     }
   .text2 : AT(ADDR(.text2) - LOAD_OFFSET)
diff -prauN linux-2.6.0-test9-bk22/arch/m68k/kernel/process.c wchan-2.6.0-test9-bk22-2/arch/m68k/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/m68k/kernel/process.c	2003-10-25 11:45:04.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/m68k/kernel/process.c	2003-11-17 23:22:49.000000000 -0800
@@ -65,12 +65,10 @@ asmlinkage void ret_from_fork(void);
  */
 unsigned long thread_saved_pc(struct task_struct *tsk)
 {
-	extern void scheduling_functions_start_here(void);
-	extern void scheduling_functions_end_here(void);
 	struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
 	/* Check whether the thread is blocked in resume() */
-	if (sw->retpc > (unsigned long)scheduling_functions_start_here &&
-	    sw->retpc < (unsigned long)scheduling_functions_end_here)
+	if (sw->retpc > scheduling_functions_start_here &&
+	    sw->retpc < scheduling_functions_end_here)
 		return ((unsigned long *)sw->a6)[1];
 	else
 		return sw->retpc;
@@ -387,11 +385,6 @@ out:
 /*
  * 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)
 {
 	unsigned long fp, pc;
@@ -407,8 +400,8 @@ unsigned long get_wchan(struct task_stru
 		    fp >= 8184+stack_page)
 			return 0;
 		pc = ((unsigned long *)fp)[1];
-		/* FIXME: This depends on the order of these functions. */
-		if (pc < first_sched || pc >= last_sched)
+		if (pc < scheduling_functions_start_here ||
+				pc >= scheduling_functions_end_here)
 			return pc;
 		fp = *(unsigned long *) fp;
 	} while (count++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/m68k/kernel/semaphore.c wchan-2.6.0-test9-bk22-2/arch/m68k/kernel/semaphore.c
--- linux-2.6.0-test9-bk22/arch/m68k/kernel/semaphore.c	2003-10-25 11:44:08.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/m68k/kernel/semaphore.c	2003-11-20 14:16:04.000000000 -0800
@@ -5,6 +5,7 @@
 
 #include <linux/config.h>
 #include <linux/sched.h>
+#include <linux/init.h>
 #include <asm/semaphore-helper.h>
 
 #ifndef CONFIG_RMW_INSNS
@@ -95,7 +96,7 @@ void __up(struct semaphore *sem)
 	current->state = TASK_RUNNING;		\
 	remove_wait_queue(&sem->wait, &wait);
 
-void __down(struct semaphore * sem)
+__sched void __down(struct semaphore * sem)
 {
 	DECLARE_WAITQUEUE(wait, current);
 
@@ -106,7 +107,7 @@ void __down(struct semaphore * sem)
 	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
 }
 
-int __down_interruptible(struct semaphore * sem)
+__sched int __down_interruptible(struct semaphore * sem)
 {
 	DECLARE_WAITQUEUE(wait, current);
 	int ret = 0;
diff -prauN linux-2.6.0-test9-bk22/arch/m68k/kernel/vmlinux-std.lds wchan-2.6.0-test9-bk22-2/arch/m68k/kernel/vmlinux-std.lds
--- linux-2.6.0-test9-bk22/arch/m68k/kernel/vmlinux-std.lds	2003-10-25 11:44:39.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/m68k/kernel/vmlinux-std.lds	2003-11-18 19:06:58.000000000 -0800
@@ -12,6 +12,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.sched.text)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x4e75
diff -prauN linux-2.6.0-test9-bk22/arch/m68k/kernel/vmlinux-sun3.lds wchan-2.6.0-test9-bk22-2/arch/m68k/kernel/vmlinux-sun3.lds
--- linux-2.6.0-test9-bk22/arch/m68k/kernel/vmlinux-sun3.lds	2003-10-25 11:42:41.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/m68k/kernel/vmlinux-sun3.lds	2003-11-18 19:06:54.000000000 -0800
@@ -13,6 +13,9 @@ SECTIONS
   .text : {
 	*(.head)
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.sched.text)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x4e75
diff -prauN linux-2.6.0-test9-bk22/arch/m68knommu/kernel/process.c wchan-2.6.0-test9-bk22-2/arch/m68knommu/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/m68knommu/kernel/process.c	2003-10-25 11:43:07.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/m68knommu/kernel/process.c	2003-11-17 23:23:27.000000000 -0800
@@ -406,11 +406,6 @@ out:
 /*
  * 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)
 {
 	unsigned long fp, pc;
@@ -426,8 +421,8 @@ unsigned long get_wchan(struct task_stru
 		    fp >= 8184+stack_page)
 			return 0;
 		pc = ((unsigned long *)fp)[1];
-		/* FIXME: This depends on the order of these functions. */
-		if (pc < first_sched || pc >= last_sched)
+		if (pc < scheduling_functions_start_here ||
+				pc >= scheduling_functions_end_here)
 			return pc;
 		fp = *(unsigned long *) fp;
 	} while (count++ < 16);
@@ -439,13 +434,11 @@ unsigned long get_wchan(struct task_stru
  */
 unsigned long thread_saved_pc(struct task_struct *tsk)
 {
-	extern void scheduling_functions_start_here(void);
-	extern void scheduling_functions_end_here(void);
 	struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
 
 	/* Check whether the thread is blocked in resume() */
-	if (sw->retpc > (unsigned long)scheduling_functions_start_here &&
-	    sw->retpc < (unsigned long)scheduling_functions_end_here)
+	if (sw->retpc > scheduling_functions_start_here &&
+	    sw->retpc < scheduling_functions_end_here)
 		return ((unsigned long *)sw->a6)[1];
 	else
 		return sw->retpc;
diff -prauN linux-2.6.0-test9-bk22/arch/m68knommu/kernel/semaphore.c wchan-2.6.0-test9-bk22-2/arch/m68knommu/kernel/semaphore.c
--- linux-2.6.0-test9-bk22/arch/m68knommu/kernel/semaphore.c	2003-10-25 11:45:05.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/m68knommu/kernel/semaphore.c	2003-11-20 14:21:25.000000000 -0800
@@ -6,6 +6,7 @@
 #include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/err.h>
+#include <linux/init.h>
 #include <asm/semaphore-helper.h>
 
 #ifndef CONFIG_RMW_INSNS
@@ -96,7 +97,7 @@ void __up(struct semaphore *sem)
 	current->state = TASK_RUNNING;		\
 	remove_wait_queue(&sem->wait, &wait);
 
-void __down(struct semaphore * sem)
+__sched void __down(struct semaphore * sem)
 {
 	DECLARE_WAITQUEUE(wait, current);
 
@@ -107,7 +108,7 @@ void __down(struct semaphore * sem)
 	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
 }
 
-int __down_interruptible(struct semaphore * sem)
+__sched int __down_interruptible(struct semaphore * sem)
 {
 	DECLARE_WAITQUEUE(wait, current);
 	int ret = 0;
diff -prauN linux-2.6.0-test9-bk22/arch/m68knommu/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-2/arch/m68knommu/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/m68knommu/kernel/vmlinux.lds.S	2003-10-25 11:43:29.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/m68knommu/kernel/vmlinux.lds.S	2003-11-18 19:06:18.000000000 -0800
@@ -191,6 +191,9 @@ SECTIONS {
 	.text : {
 		_stext = . ;
         	*(.text)
+		__scheduling_functions_start_here = .;
+		*(.sched.text)
+		__scheduling_functions_end_here = .;
         	*(.text.lock)
 
 		. = ALIGN(16);          /* Exception table              */
diff -prauN linux-2.6.0-test9-bk22/arch/mips/kernel/process.c wchan-2.6.0-test9-bk22-2/arch/mips/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/mips/kernel/process.c	2003-10-25 11:43:29.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/mips/kernel/process.c	2003-11-17 23:31:29.000000000 -0800
@@ -276,11 +276,6 @@ unsigned long thread_saved_pc(struct tas
 /*
  * 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)
-
 /* get_wchan - a maintenance nightmare^W^Wpain in the ass ...  */
 unsigned long get_wchan(struct task_struct *p)
 {
@@ -292,7 +287,8 @@ unsigned long get_wchan(struct task_stru
 	if (!mips_frame_info_initialized)
 		return 0;
 	pc = thread_saved_pc(p);
-	if (pc < first_sched || pc >= last_sched)
+	if (pc < scheduling_functions_start_here ||
+			pc >= scheduling_functions_end_here)
 		goto out;
 
 	if (pc >= (unsigned long) sleep_on_timeout)
@@ -326,7 +322,8 @@ schedule_timeout_caller:
 	 */
 	pc    = ((unsigned long *)frame)[schedule_timeout_frame.pc_offset];
 
-	if (pc >= first_sched && pc < last_sched) {
+	if (pc >= scheduling_functions_start_here &&
+			pc < scheduling_functions_end_here) {
 		/* schedule_timeout called by [interruptible_]sleep_on_timeout */
 		frame = ((unsigned long *)frame)[schedule_timeout_frame.frame_offset];
 		pc    = ((unsigned long *)frame)[sleep_on_timeout_frame.pc_offset];
diff -prauN linux-2.6.0-test9-bk22/arch/mips/kernel/semaphore.c wchan-2.6.0-test9-bk22-2/arch/mips/kernel/semaphore.c
--- linux-2.6.0-test9-bk22/arch/mips/kernel/semaphore.c	2003-10-25 11:43:59.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/mips/kernel/semaphore.c	2003-11-20 14:16:42.000000000 -0800
@@ -4,6 +4,7 @@
  */
 
 #include <linux/sched.h>
+#include <linux/init.h>
 #include <asm/semaphore-helper.h>
 
 /*
@@ -94,7 +95,7 @@ void __up(struct semaphore *sem)
 	tsk->state = TASK_RUNNING;		\
 	remove_wait_queue(&sem->wait, &wait);
 
-void __down(struct semaphore * sem)
+__sched void __down(struct semaphore * sem)
 {
 	DOWN_VAR
 	DOWN_HEAD(TASK_UNINTERRUPTIBLE)
@@ -104,7 +105,7 @@ void __down(struct semaphore * sem)
 	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
 }
 
-int __down_interruptible(struct semaphore * sem)
+__sched int __down_interruptible(struct semaphore * sem)
 {
 	int ret = 0;
 	DOWN_VAR
diff -prauN linux-2.6.0-test9-bk22/arch/mips/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-2/arch/mips/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/mips/kernel/vmlinux.lds.S	2003-10-25 11:43:21.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/mips/kernel/vmlinux.lds.S	2003-11-18 19:06:35.000000000 -0800
@@ -27,6 +27,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.sched.text)
+    __scheduling_functions_end_here = .;
     *(.fixup)
     *(.gnu.warning)
   } =0
diff -prauN linux-2.6.0-test9-bk22/arch/parisc/kernel/semaphore.c wchan-2.6.0-test9-bk22-2/arch/parisc/kernel/semaphore.c
--- linux-2.6.0-test9-bk22/arch/parisc/kernel/semaphore.c	2003-10-25 11:44:13.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/parisc/kernel/semaphore.c	2003-11-20 14:17:07.000000000 -0800
@@ -5,6 +5,7 @@
 #include <linux/sched.h>
 #include <linux/spinlock.h>
 #include <linux/errno.h>
+#include <linux/init.h>
 
 /*
  * Semaphores are complex as we wish to avoid using two variables.
@@ -58,7 +59,7 @@ void __up(struct semaphore *sem)
 	sem->count += (sem->count < 0) ? 1 : - 1;
 	
 
-void __down(struct semaphore * sem)
+__sched void __down(struct semaphore * sem)
 {
 	DOWN_HEAD
 
@@ -74,7 +75,7 @@ void __down(struct semaphore * sem)
 	UPDATE_COUNT
 }
 
-int __down_interruptible(struct semaphore * sem)
+__sched int __down_interruptible(struct semaphore * sem)
 {
 	DOWN_HEAD
 
diff -prauN linux-2.6.0-test9-bk22/arch/parisc/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-2/arch/parisc/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/parisc/kernel/vmlinux.lds.S	2003-10-25 11:43:05.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/parisc/kernel/vmlinux.lds.S	2003-11-18 19:07:15.000000000 -0800
@@ -24,6 +24,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text BLOCK(16) : {
 	*(.text*)
+	__scheduling_functions_start_here = .;
+	*(.sched.text)
+	__scheduling_functions_end_here =.;
 	*(.PARISC.unwind)
 	*(.fixup)
 	*(.lock.text)		/* out-of-line lock text */
diff -prauN linux-2.6.0-test9-bk22/arch/ppc/kernel/process.c wchan-2.6.0-test9-bk22-2/arch/ppc/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/ppc/kernel/process.c	2003-10-25 11:43:35.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/ppc/kernel/process.c	2003-11-17 23:25:35.000000000 -0800
@@ -650,11 +650,6 @@ void __init ll_puts(const char *s)
 /*
  * 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)
 {
 	unsigned long ip, sp;
@@ -669,7 +664,8 @@ unsigned long get_wchan(struct task_stru
 			return 0;
 		if (count > 0) {
 			ip = *(unsigned long *)(sp + 4);
-			if (ip < first_sched || ip >= last_sched)
+			if (ip < scheduling_functions_start_here ||
+					ip >= scheduling_functions_end_here)
 				return ip;
 		}
 	} while (count++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/ppc/kernel/semaphore.c wchan-2.6.0-test9-bk22-2/arch/ppc/kernel/semaphore.c
--- linux-2.6.0-test9-bk22/arch/ppc/kernel/semaphore.c	2003-10-25 11:44:26.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/ppc/kernel/semaphore.c	2003-11-20 14:17:32.000000000 -0800
@@ -15,6 +15,7 @@
  */
 
 #include <linux/sched.h>
+#include <linux/init.h>
 #include <asm/atomic.h>
 #include <asm/semaphore.h>
 #include <asm/errno.h>
@@ -69,7 +70,7 @@ void __up(struct semaphore *sem)
  * Thus it is only when we decrement count from some value > 0
  * that we have actually got the semaphore.
  */
-void __down(struct semaphore *sem)
+__sched void __down(struct semaphore *sem)
 {
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
@@ -99,7 +100,7 @@ void __down(struct semaphore *sem)
 	wake_up(&sem->wait);
 }
 
-int __down_interruptible(struct semaphore * sem)
+__sched int __down_interruptible(struct semaphore * sem)
 {
 	int retval = 0;
 	struct task_struct *tsk = current;
diff -prauN linux-2.6.0-test9-bk22/arch/ppc/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-2/arch/ppc/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/ppc/kernel/vmlinux.lds.S	2003-11-17 22:51:23.000000000 -0800
+++ wchan-2.6.0-test9-bk22-2/arch/ppc/kernel/vmlinux.lds.S	2003-11-18 19:06:32.000000000 -0800
@@ -31,6 +31,9 @@ SECTIONS
   .text      :
   {
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.sched.text)
+    __scheduling_functions_end_here = .;
     *(.fixup)
     *(.got1)
     __got2_start = .;
diff -prauN linux-2.6.0-test9-bk22/arch/ppc64/kernel/process.c wchan-2.6.0-test9-bk22-2/arch/ppc64/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/ppc64/kernel/process.c	2003-10-25 11:43:54.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/ppc64/kernel/process.c	2003-11-17 23:26:08.000000000 -0800
@@ -369,11 +369,6 @@ out:
 /*
  * 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)
 {
 	unsigned long ip, sp;
@@ -393,7 +388,8 @@ unsigned long get_wchan(struct task_stru
 			 * XXX we mask the upper 32 bits until procps
 			 * gets fixed.
 			 */
-			if (ip < first_sched || ip >= last_sched)
+			if (ip < scheduling_functions_start_here ||
+					ip >= scheduling_functions_end_here)
 				return (ip & 0xFFFFFFFF);
 		}
 	} while (count++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/ppc64/kernel/semaphore.c wchan-2.6.0-test9-bk22-2/arch/ppc64/kernel/semaphore.c
--- linux-2.6.0-test9-bk22/arch/ppc64/kernel/semaphore.c	2003-10-25 11:42:54.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/ppc64/kernel/semaphore.c	2003-11-20 14:17:59.000000000 -0800
@@ -17,6 +17,7 @@
  */
 
 #include <linux/sched.h>
+#include <linux/init.h>
 #include <asm/atomic.h>
 #include <asm/semaphore.h>
 #include <asm/errno.h>
@@ -70,7 +71,7 @@ void __up(struct semaphore *sem)
  * Thus it is only when we decrement count from some value > 0
  * that we have actually got the semaphore.
  */
-void __down(struct semaphore *sem)
+__sched void __down(struct semaphore *sem)
 {
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
@@ -99,7 +100,7 @@ void __down(struct semaphore *sem)
 	wake_up(&sem->wait);
 }
 
-int __down_interruptible(struct semaphore * sem)
+__sched int __down_interruptible(struct semaphore * sem)
 {
 	int retval = 0;
 	struct task_struct *tsk = current;
diff -prauN linux-2.6.0-test9-bk22/arch/ppc64/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-2/arch/ppc64/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/ppc64/kernel/vmlinux.lds.S	2003-10-25 11:44:15.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/ppc64/kernel/vmlinux.lds.S	2003-11-18 19:07:08.000000000 -0800
@@ -33,6 +33,9 @@ SECTIONS
   .text      :
   {
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.sched.text)
+    __scheduling_functions_end_here = .;
     *(.fixup)
     *(.got1)
   }
diff -prauN linux-2.6.0-test9-bk22/arch/s390/kernel/process.c wchan-2.6.0-test9-bk22-2/arch/s390/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/s390/kernel/process.c	2003-10-25 11:44:17.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/s390/kernel/process.c	2003-11-17 23:26:43.000000000 -0800
@@ -371,11 +371,6 @@ void dump_thread(struct pt_regs * regs, 
 /*
  * 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)
 {
 	unsigned long r14, r15, bc;
@@ -398,12 +393,10 @@ unsigned long get_wchan(struct task_stru
 #else
 		r14 = *(unsigned long *) (bc+112);
 #endif
-		if (r14 < first_sched || r14 >= last_sched)
+		if (r14 < scheduling_functions_start_here ||
+				r14 >= scheduling_functions_end_here)
 			return r14;
 		bc = (*(unsigned long *) bc) & PSW_ADDR_INSN;
 	} while (count++ < 16);
 	return 0;
 }
-#undef last_sched
-#undef first_sched
-
diff -prauN linux-2.6.0-test9-bk22/arch/s390/kernel/semaphore.c wchan-2.6.0-test9-bk22-2/arch/s390/kernel/semaphore.c
--- linux-2.6.0-test9-bk22/arch/s390/kernel/semaphore.c	2003-10-25 11:44:42.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/s390/kernel/semaphore.c	2003-11-20 14:18:16.000000000 -0800
@@ -11,6 +11,7 @@
  */
 #include <linux/sched.h>
 #include <linux/errno.h>
+#include <linux/init.h>
 
 #include <asm/semaphore.h>
 
@@ -59,7 +60,7 @@ void __up(struct semaphore *sem)
  *   count > 0: decrement count, wake up queue and exit.
  *   count <= 0: set count to -1, go to sleep.
  */
-void __down(struct semaphore * sem)
+__sched void __down(struct semaphore * sem)
 {
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
@@ -81,7 +82,7 @@ void __down(struct semaphore * sem)
  *   count > 0: wake up queue and exit.
  *   count <= 0: set count to 0, wake up queue and exit.
  */
-int __down_interruptible(struct semaphore * sem)
+__sched int __down_interruptible(struct semaphore * sem)
 {
 	int retval = 0;
 	struct task_struct *tsk = current;
diff -prauN linux-2.6.0-test9-bk22/arch/s390/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-2/arch/s390/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/s390/kernel/vmlinux.lds.S	2003-10-25 11:43:23.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/s390/kernel/vmlinux.lds.S	2003-11-18 19:07:33.000000000 -0800
@@ -23,6 +23,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.sched.text)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x0700
diff -prauN linux-2.6.0-test9-bk22/arch/sh/kernel/process.c wchan-2.6.0-test9-bk22-2/arch/sh/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/sh/kernel/process.c	2003-10-25 11:44:08.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/sh/kernel/process.c	2003-11-17 23:28:29.000000000 -0800
@@ -375,11 +375,6 @@ out:
 /*
  * 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)
 {
 	unsigned long schedule_frame;
diff -prauN linux-2.6.0-test9-bk22/arch/sh/kernel/semaphore.c wchan-2.6.0-test9-bk22-2/arch/sh/kernel/semaphore.c
--- linux-2.6.0-test9-bk22/arch/sh/kernel/semaphore.c	2003-10-25 11:44:28.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/sh/kernel/semaphore.c	2003-11-20 14:18:36.000000000 -0800
@@ -10,6 +10,7 @@
 #include <linux/errno.h>
 #include <linux/sched.h>
 #include <linux/wait.h>
+#include <linux/init.h>
 #include <asm/semaphore.h>
 #include <asm/semaphore-helper.h>
 
@@ -103,7 +104,7 @@ void __up(struct semaphore *sem)
 	tsk->state = TASK_RUNNING;		\
 	remove_wait_queue(&sem->wait, &wait);
 
-void __down(struct semaphore * sem)
+__sched void __down(struct semaphore * sem)
 {
 	DOWN_VAR
 	DOWN_HEAD(TASK_UNINTERRUPTIBLE)
@@ -113,7 +114,7 @@ void __down(struct semaphore * sem)
 	DOWN_TAIL(TASK_UNINTERRUPTIBLE)
 }
 
-int __down_interruptible(struct semaphore * sem)
+__sched int __down_interruptible(struct semaphore * sem)
 {
 	int ret = 0;
 	DOWN_VAR
diff -prauN linux-2.6.0-test9-bk22/arch/sh/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-2/arch/sh/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/sh/kernel/vmlinux.lds.S	2003-10-25 11:43:49.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/sh/kernel/vmlinux.lds.S	2003-11-18 19:06:43.000000000 -0800
@@ -22,6 +22,9 @@ SECTIONS
 	} = 0
   .text : {
 	*(.text)
+	__scheduling_functions_start_here =.;
+	*(.sched.text)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x0009
diff -prauN linux-2.6.0-test9-bk22/arch/sparc/kernel/process.c wchan-2.6.0-test9-bk22-2/arch/sparc/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/sparc/kernel/process.c	2003-10-25 11:43:00.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/sparc/kernel/process.c	2003-11-17 23:29:13.000000000 -0800
@@ -692,9 +692,6 @@ pid_t kernel_thread(int (*fn)(void *), v
 	return retval;
 }
 
-extern void scheduling_functions_start_here(void);
-extern void scheduling_functions_end_here(void);
-
 unsigned long get_wchan(struct task_struct *task)
 {
 	unsigned long pc, fp, bias = 0;
@@ -715,8 +712,8 @@ unsigned long get_wchan(struct task_stru
 			break;
 		rw = (struct reg_window *) fp;
 		pc = rw->ins[7];
-		if (pc < ((unsigned long) scheduling_functions_start_here) ||
-                    pc >= ((unsigned long) scheduling_functions_end_here)) {
+		if (pc < scheduling_functions_start_here ||
+                    pc >= scheduling_functions_end_here) {
 			ret = pc;
 			goto out;
 		}
diff -prauN linux-2.6.0-test9-bk22/arch/sparc/kernel/semaphore.c wchan-2.6.0-test9-bk22-2/arch/sparc/kernel/semaphore.c
--- linux-2.6.0-test9-bk22/arch/sparc/kernel/semaphore.c	2003-10-25 11:44:48.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/sparc/kernel/semaphore.c	2003-11-20 14:18:58.000000000 -0800
@@ -4,6 +4,7 @@
 
 #include <linux/sched.h>
 #include <linux/errno.h>
+#include <linux/init.h>
 
 #include <asm/semaphore.h>
 
@@ -45,7 +46,7 @@ void __up(struct semaphore *sem)
 
 static spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED;
 
-void __down(struct semaphore * sem)
+__sched void __down(struct semaphore * sem)
 {
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
@@ -78,7 +79,7 @@ void __down(struct semaphore * sem)
 	wake_up(&sem->wait);
 }
 
-int __down_interruptible(struct semaphore * sem)
+__sched int __down_interruptible(struct semaphore * sem)
 {
 	int retval = 0;
 	struct task_struct *tsk = current;
diff -prauN linux-2.6.0-test9-bk22/arch/sparc/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-2/arch/sparc/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/sparc/kernel/vmlinux.lds.S	2003-10-25 11:42:53.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/sparc/kernel/vmlinux.lds.S	2003-11-18 19:06:28.000000000 -0800
@@ -12,6 +12,9 @@ SECTIONS
   .text 0xf0004000 :
   {
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.sched.text)
+    __scheduling_functions_end_here = .;
     *(.gnu.warning)
   } =0
   _etext = .;
diff -prauN linux-2.6.0-test9-bk22/arch/sparc/lib/rwsem.S wchan-2.6.0-test9-bk22-2/arch/sparc/lib/rwsem.S
--- linux-2.6.0-test9-bk22/arch/sparc/lib/rwsem.S	2003-10-25 11:44:00.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/sparc/lib/rwsem.S	2003-11-20 14:41:16.000000000 -0800
@@ -8,7 +8,7 @@
 #include <asm/ptrace.h>
 #include <asm/psr.h>
 
-	.text
+	.section .sched.text
 	.align	4
 
 	.globl		___down_read
@@ -113,6 +113,7 @@ ___down_write:
 	ba		2b
 	 restore	%l5, %g0, %g5
 
+	.text
 	.globl		___up_read
 ___up_read:
 	rd		%psr, %g3
diff -prauN linux-2.6.0-test9-bk22/arch/sparc64/kernel/process.c wchan-2.6.0-test9-bk22-2/arch/sparc64/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/sparc64/kernel/process.c	2003-10-25 11:43:30.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/sparc64/kernel/process.c	2003-11-17 23:29:28.000000000 -0800
@@ -824,9 +824,6 @@ out:
 	return error;
 }
 
-extern void scheduling_functions_start_here(void);
-extern void scheduling_functions_end_here(void);
-
 unsigned long get_wchan(struct task_struct *task)
 {
 	unsigned long pc, fp, bias = 0;
@@ -850,8 +847,8 @@ unsigned long get_wchan(struct task_stru
 			break;
 		rw = (struct reg_window *) fp;
 		pc = rw->ins[7];
-		if (pc < ((unsigned long) scheduling_functions_start_here) ||
-		    pc >= ((unsigned long) scheduling_functions_end_here)) {
+		if (pc < scheduling_functions_start_here ||
+		    pc >= scheduling_functions_end_here) {
 			ret = pc;
 			goto out;
 		}
diff -prauN linux-2.6.0-test9-bk22/arch/sparc64/kernel/semaphore.c wchan-2.6.0-test9-bk22-2/arch/sparc64/kernel/semaphore.c
--- linux-2.6.0-test9-bk22/arch/sparc64/kernel/semaphore.c	2003-10-25 11:44:28.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/sparc64/kernel/semaphore.c	2003-11-20 14:22:01.000000000 -0800
@@ -8,6 +8,7 @@
 
 #include <linux/sched.h>
 #include <linux/errno.h>
+#include <linux/init.h>
 
 /*
  * Atomically update sem->count.
@@ -90,7 +91,7 @@ void up(struct semaphore *sem)
 	: "g5", "g7", "memory", "cc");
 }
 
-static void __down(struct semaphore * sem)
+static __sched void __down(struct semaphore * sem)
 {
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
@@ -108,7 +109,7 @@ static void __down(struct semaphore * se
 	wake_up(&sem->wait);
 }
 
-void down(struct semaphore *sem)
+__sched void down(struct semaphore *sem)
 {
 	might_sleep();
 	/* This atomically does:
@@ -192,7 +193,7 @@ int down_trylock(struct semaphore *sem)
 	return ret;
 }
 
-static int __down_interruptible(struct semaphore * sem)
+static __sched int __down_interruptible(struct semaphore * sem)
 {
 	int retval = 0;
 	struct task_struct *tsk = current;
@@ -216,7 +217,7 @@ static int __down_interruptible(struct s
 	return retval;
 }
 
-int down_interruptible(struct semaphore *sem)
+__sched int down_interruptible(struct semaphore *sem)
 {
 	int ret = 0;
 	
diff -prauN linux-2.6.0-test9-bk22/arch/sparc64/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-2/arch/sparc64/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/sparc64/kernel/vmlinux.lds.S	2003-10-25 11:44:36.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/sparc64/kernel/vmlinux.lds.S	2003-11-18 19:06:23.000000000 -0800
@@ -15,6 +15,9 @@ SECTIONS
   .text 0x0000000000404000 :
   {
     *(.text)
+    __scheduling_functions_start_here = .;
+    *(.sched.text)
+    __scheduling_functions_end_here = .;
     *(.gnu.warning)
   } =0
   _etext = .;
diff -prauN linux-2.6.0-test9-bk22/arch/sparc64/lib/rwsem.c wchan-2.6.0-test9-bk22-2/arch/sparc64/lib/rwsem.c
--- linux-2.6.0-test9-bk22/arch/sparc64/lib/rwsem.c	2003-10-25 11:42:43.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/sparc64/lib/rwsem.c	2003-11-20 14:40:21.000000000 -0800
@@ -6,6 +6,7 @@
 
 #include <linux/kernel.h>
 #include <linux/rwsem.h>
+#include <linux/init.h>
 #include <linux/module.h>
 
 extern struct rw_semaphore *FASTCALL(rwsem_down_read_failed(struct rw_semaphore *sem));
@@ -13,7 +14,7 @@ extern struct rw_semaphore *FASTCALL(rws
 extern struct rw_semaphore *FASTCALL(rwsem_wake(struct rw_semaphore *));
 extern struct rw_semaphore *FASTCALL(rwsem_downgrade_wake(struct rw_semaphore *));
 
-void __down_read(struct rw_semaphore *sem)
+__sched void __down_read(struct rw_semaphore *sem)
 {
 	__asm__ __volatile__(
 		"! beginning __down_read\n"
@@ -72,7 +73,7 @@ int __down_read_trylock(struct rw_semaph
 }
 EXPORT_SYMBOL(__down_read_trylock);
 
-void __down_write(struct rw_semaphore *sem)
+__sched void __down_write(struct rw_semaphore *sem)
 {
 	__asm__ __volatile__(
 		"! beginning __down_write\n\t"
diff -prauN linux-2.6.0-test9-bk22/arch/v850/kernel/process.c wchan-2.6.0-test9-bk22-2/arch/v850/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/v850/kernel/process.c	2003-10-25 11:43:02.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/v850/kernel/process.c	2003-11-18 00:47:03.000000000 -0800
@@ -203,11 +203,6 @@ int sys_execve (char *name, char **argv,
 /*
  * 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 0  /* Barf.  Figure out the stack-layout later.  XXX  */
@@ -221,15 +216,16 @@ unsigned long get_wchan (struct task_str
 
 	/* This quite disgusting function walks up the stack, following
 	   saved return address, until it something that's out of bounds
-	   (as defined by `first_sched' and `last_sched').  It then
-	   returns the last PC that was in-bounds.  */
+	   (as defined by `scheduling_functions_start_here' and
+	   `scheduling_functions_end_here').  It then returns the last
+	   PC that was in-bounds.  */
 	do {
-		if (fp < stack_page + sizeof (struct task_struct) ||
-		    fp >= 8184+stack_page)
+		if (fp < stack_page + sizeof(struct thread_info) ||
+		    fp >= THREAD_SIZE + stack_page - 8)
 			return 0;
 		pc = ((unsigned long *)fp)[1];
-		/* FIXME: This depends on the order of these functions. */
-		if (pc < first_sched || pc >= last_sched)
+		if (pc < scheduling_functions_start_here ||
+				pc >= scheduling_functions_end_here)
 			return pc;
 		fp = *(unsigned long *) fp;
 	} while (count++ < 16);
diff -prauN linux-2.6.0-test9-bk22/arch/v850/kernel/semaphore.c wchan-2.6.0-test9-bk22-2/arch/v850/kernel/semaphore.c
--- linux-2.6.0-test9-bk22/arch/v850/kernel/semaphore.c	2003-10-25 11:44:28.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/v850/kernel/semaphore.c	2003-11-20 14:19:57.000000000 -0800
@@ -15,6 +15,7 @@
 
 #include <linux/errno.h>
 #include <linux/sched.h>
+#include <linux/init.h>
 
 #include <asm/semaphore.h>
 
@@ -56,7 +57,7 @@ void __up(struct semaphore *sem)
 
 static spinlock_t semaphore_lock = SPIN_LOCK_UNLOCKED;
 
-void __down(struct semaphore * sem)
+__sched void __down(struct semaphore * sem)
 {
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
@@ -89,7 +90,7 @@ void __down(struct semaphore * sem)
 	wake_up(&sem->wait);
 }
 
-int __down_interruptible(struct semaphore * sem)
+__sched int __down_interruptible(struct semaphore * sem)
 {
 	int retval = 0;
 	struct task_struct *tsk = current;
diff -prauN linux-2.6.0-test9-bk22/arch/v850/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-2/arch/v850/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/v850/kernel/vmlinux.lds.S	2003-10-25 11:43:58.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/v850/kernel/vmlinux.lds.S	2003-11-18 19:07:25.000000000 -0800
@@ -64,6 +64,9 @@
 #define TEXT_CONTENTS							      \
 		__stext = . ;						      \
         	*(.text)						      \
+		__scheduling_functions_start_here = .;
+		*(.sched.text)
+		__scheduling_functions_end_here = .;
 			*(.exit.text)	/* 2.5 convention */		      \
 			*(.text.exit)	/* 2.4 convention */		      \
 			*(.text.lock)					      \
diff -prauN linux-2.6.0-test9-bk22/arch/x86_64/kernel/process.c wchan-2.6.0-test9-bk22-2/arch/x86_64/kernel/process.c
--- linux-2.6.0-test9-bk22/arch/x86_64/kernel/process.c	2003-10-25 11:43:49.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/x86_64/kernel/process.c	2003-11-17 23:30:38.000000000 -0800
@@ -528,11 +528,6 @@ asmlinkage long sys_vfork(struct pt_regs
 /*
  * 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)
 {
 	u64 fp,rip;
@@ -547,14 +542,13 @@ unsigned long get_wchan(struct task_stru
 		if (fp < (unsigned long)p || fp > (unsigned long)p+THREAD_SIZE)
 			return 0; 
 		rip = *(u64 *)(fp+8); 
-		if (rip < first_sched || rip >= last_sched)
+		if (rip < scheduling_functions_start_here ||
+				rip >= scheduling_functions_end_here)
 			return rip; 
 		fp = *(u64 *)fp; 
 	} while (count++ < 16); 
 	return 0;
 }
-#undef last_sched
-#undef first_sched
 
 long do_arch_prctl(struct task_struct *task, int code, unsigned long addr)
 { 
diff -prauN linux-2.6.0-test9-bk22/arch/x86_64/kernel/semaphore.c wchan-2.6.0-test9-bk22-2/arch/x86_64/kernel/semaphore.c
--- linux-2.6.0-test9-bk22/arch/x86_64/kernel/semaphore.c	2003-10-25 11:45:07.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/x86_64/kernel/semaphore.c	2003-11-20 14:20:17.000000000 -0800
@@ -14,6 +14,7 @@
  */
 #include <linux/config.h>
 #include <linux/sched.h>
+#include <linux/init.h>
 #include <asm/errno.h>
 
 #include <asm/semaphore.h>
@@ -54,7 +55,7 @@ void __up(struct semaphore *sem)
 	wake_up(&sem->wait);
 }
 
-void __down(struct semaphore * sem)
+__sched void __down(struct semaphore * sem)
 {
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
@@ -91,7 +92,7 @@ void __down(struct semaphore * sem)
 	tsk->state = TASK_RUNNING;
 }
 
-int __down_interruptible(struct semaphore * sem)
+__sched int __down_interruptible(struct semaphore * sem)
 {
 	int retval = 0;
 	struct task_struct *tsk = current;
diff -prauN linux-2.6.0-test9-bk22/arch/x86_64/kernel/vmlinux.lds.S wchan-2.6.0-test9-bk22-2/arch/x86_64/kernel/vmlinux.lds.S
--- linux-2.6.0-test9-bk22/arch/x86_64/kernel/vmlinux.lds.S	2003-10-25 11:42:51.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/x86_64/kernel/vmlinux.lds.S	2003-11-18 19:07:18.000000000 -0800
@@ -14,6 +14,9 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
+	__scheduling_functions_start_here = .;
+	*(.sched.text)
+	__scheduling_functions_end_here = .;
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x9090
diff -prauN linux-2.6.0-test9-bk22/arch/x86_64/lib/thunk.S wchan-2.6.0-test9-bk22-2/arch/x86_64/lib/thunk.S
--- linux-2.6.0-test9-bk22/arch/x86_64/lib/thunk.S	2003-10-25 11:43:33.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/arch/x86_64/lib/thunk.S	2003-11-20 14:44:51.000000000 -0800
@@ -30,6 +30,7 @@
 	.endm
 	
 
+	.section .sched.text
 #ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM
 	thunk rwsem_down_read_failed_thunk,rwsem_down_read_failed
 	thunk rwsem_down_write_failed_thunk,rwsem_down_write_failed
@@ -53,7 +54,7 @@ restore_norax:	
 
 #ifdef CONFIG_SMP
 /* Support for read/write spinlocks. */
-	
+	.text
 /* rax:	pointer to rwlock_t */	
 ENTRY(__write_lock_failed)
 	lock
diff -prauN linux-2.6.0-test9-bk22/include/linux/init.h wchan-2.6.0-test9-bk22-2/include/linux/init.h
--- linux-2.6.0-test9-bk22/include/linux/init.h	2003-10-25 11:42:50.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/include/linux/init.h	2003-11-18 19:05:04.000000000 -0800
@@ -45,6 +45,8 @@
 #define __exitdata	__attribute__ ((__section__(".exit.data")))
 #define __exit_call	__attribute_used__ __attribute__ ((__section__ (".exitcall.exit")))
 
+#define __sched		__attribute__((__section__(".sched.text")))
+
 #ifdef MODULE
 #define __exit		__attribute__ ((__section__(".exit.text")))
 #else
diff -prauN linux-2.6.0-test9-bk22/include/linux/sched.h wchan-2.6.0-test9-bk22-2/include/linux/sched.h
--- linux-2.6.0-test9-bk22/include/linux/sched.h	2003-11-17 22:51:24.000000000 -0800
+++ wchan-2.6.0-test9-bk22-2/include/linux/sched.h	2003-11-17 23:01:42.000000000 -0800
@@ -169,6 +169,8 @@ extern void update_one_process(struct ta
 			       unsigned long system, int cpu);
 extern void scheduler_tick(int user_tick, int system);
 extern unsigned long cache_decay_ticks;
+extern const unsigned long scheduling_functions_start_here;
+extern const unsigned long scheduling_functions_end_here;
 
 
 #define	MAX_SCHEDULE_TIMEOUT	LONG_MAX
diff -prauN linux-2.6.0-test9-bk22/kernel/sched.c wchan-2.6.0-test9-bk22-2/kernel/sched.c
--- linux-2.6.0-test9-bk22/kernel/sched.c	2003-11-17 22:51:24.000000000 -0800
+++ wchan-2.6.0-test9-bk22-2/kernel/sched.c	2003-11-20 14:06:44.000000000 -0800
@@ -221,6 +221,13 @@ static DEFINE_PER_CPU(struct runqueue, r
 #define task_rq(p)		cpu_rq(task_cpu(p))
 #define cpu_curr(cpu)		(cpu_rq(cpu)->curr)
 
+extern unsigned long __scheduling_functions_start_here;
+extern unsigned long __scheduling_functions_end_here;
+const unsigned long scheduling_functions_start_here =
+			(unsigned long)&__scheduling_functions_start_here;
+const unsigned long scheduling_functions_end_here =
+			(unsigned long)&__scheduling_functions_end_here;
+
 /*
  * Default context-switch locking:
  */
@@ -1463,12 +1470,10 @@ out:
 	rebalance_tick(rq, 0);
 }
 
-void scheduling_functions_start_here(void) { }
-
 /*
  * schedule() is the main scheduler function.
  */
-asmlinkage void schedule(void)
+asmlinkage __sched void schedule(void)
 {
 	task_t *prev, *next;
 	runqueue_t *rq;
@@ -1611,7 +1616,7 @@ EXPORT_SYMBOL(schedule);
  * off of preempt_enable.  Kernel preemptions off return from interrupt
  * occur there and call schedule directly.
  */
-asmlinkage void preempt_schedule(void)
+asmlinkage __sched void preempt_schedule(void)
 {
 	struct thread_info *ti = current_thread_info();
 
@@ -1746,7 +1751,7 @@ void complete_all(struct completion *x)
 	spin_unlock_irqrestore(&x->wait.lock, flags);
 }
 
-void wait_for_completion(struct completion *x)
+__sched void wait_for_completion(struct completion *x)
 {
 	might_sleep();
 	spin_lock_irq(&x->wait.lock);
@@ -1784,7 +1789,7 @@ EXPORT_SYMBOL(wait_for_completion);
 	__remove_wait_queue(q, &wait);				\
 	spin_unlock_irqrestore(&q->lock, flags);
 
-void interruptible_sleep_on(wait_queue_head_t *q)
+__sched void interruptible_sleep_on(wait_queue_head_t *q)
 {
 	SLEEP_ON_VAR
 
@@ -1797,7 +1802,7 @@ void interruptible_sleep_on(wait_queue_h
 
 EXPORT_SYMBOL(interruptible_sleep_on);
 
-long interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
+__sched long interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
 	SLEEP_ON_VAR
 
@@ -1812,7 +1817,7 @@ long interruptible_sleep_on_timeout(wait
 
 EXPORT_SYMBOL(interruptible_sleep_on_timeout);
 
-void sleep_on(wait_queue_head_t *q)
+__sched void sleep_on(wait_queue_head_t *q)
 {
 	SLEEP_ON_VAR
 
@@ -1825,7 +1830,7 @@ void sleep_on(wait_queue_head_t *q)
 
 EXPORT_SYMBOL(sleep_on);
 
-long sleep_on_timeout(wait_queue_head_t *q, long timeout)
+__sched long sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
 	SLEEP_ON_VAR
 
@@ -1840,8 +1845,6 @@ long sleep_on_timeout(wait_queue_head_t 
 
 EXPORT_SYMBOL(sleep_on_timeout);
 
-void scheduling_functions_end_here(void) { }
-
 void set_user_nice(task_t *p, long nice)
 {
 	unsigned long flags;
@@ -2291,7 +2294,7 @@ asmlinkage long sys_sched_yield(void)
 	return 0;
 }
 
-void __cond_resched(void)
+__sched void __cond_resched(void)
 {
 	set_current_state(TASK_RUNNING);
 	schedule();
@@ -2305,7 +2308,7 @@ EXPORT_SYMBOL(__cond_resched);
  * this is a shortcut for kernel-space yielding - it marks the
  * thread runnable and calls sys_sched_yield().
  */
-void yield(void)
+__sched void yield(void)
 {
 	set_current_state(TASK_RUNNING);
 	sys_sched_yield();
@@ -2320,7 +2323,7 @@ EXPORT_SYMBOL(yield);
  * But don't do that if it is a deliberate, throttling IO wait (this task
  * has set its backing_dev_info: the queue against which it should throttle)
  */
-void io_schedule(void)
+__sched void io_schedule(void)
 {
 	struct runqueue *rq = this_rq();
 
@@ -2331,7 +2334,7 @@ void io_schedule(void)
 
 EXPORT_SYMBOL(io_schedule);
 
-long io_schedule_timeout(long timeout)
+__sched long io_schedule_timeout(long timeout)
 {
 	struct runqueue *rq = this_rq();
 	long ret;
@@ -2881,7 +2884,7 @@ EXPORT_SYMBOL(__might_sleep);
  *
  * Called inside preempt_disable().
  */
-void __preempt_spin_lock(spinlock_t *lock)
+__sched void __preempt_spin_lock(spinlock_t *lock)
 {
 	if (preempt_count() > 1) {
 		_raw_spin_lock(lock);
@@ -2897,7 +2900,7 @@ void __preempt_spin_lock(spinlock_t *loc
 
 EXPORT_SYMBOL(__preempt_spin_lock);
 
-void __preempt_write_lock(rwlock_t *lock)
+__sched void __preempt_write_lock(rwlock_t *lock)
 {
 	if (preempt_count() > 1) {
 		_raw_write_lock(lock);
diff -prauN linux-2.6.0-test9-bk22/kernel/timer.c wchan-2.6.0-test9-bk22-2/kernel/timer.c
--- linux-2.6.0-test9-bk22/kernel/timer.c	2003-11-17 22:51:24.000000000 -0800
+++ wchan-2.6.0-test9-bk22-2/kernel/timer.c	2003-11-17 23:01:42.000000000 -0800
@@ -1000,7 +1000,7 @@ static void process_timeout(unsigned lon
  *
  * In all cases the return value is guaranteed to be non-negative.
  */
-signed long schedule_timeout(signed long timeout)
+__sched signed long schedule_timeout(signed long timeout)
 {
 	struct timer_list timer;
 	unsigned long expire;
@@ -1060,7 +1060,7 @@ asmlinkage long sys_gettid(void)
 	return current->pid;
 }
 
-static long nanosleep_restart(struct restart_block *restart)
+static __sched long nanosleep_restart(struct restart_block *restart)
 {
 	unsigned long expire = restart->arg0, now = jiffies;
 	struct timespec *rmtp = (struct timespec *) restart->arg1;
diff -prauN linux-2.6.0-test9-bk22/lib/rwsem.c wchan-2.6.0-test9-bk22-2/lib/rwsem.c
--- linux-2.6.0-test9-bk22/lib/rwsem.c	2003-10-25 11:42:48.000000000 -0700
+++ wchan-2.6.0-test9-bk22-2/lib/rwsem.c	2003-11-20 14:47:13.000000000 -0800
@@ -5,6 +5,7 @@
  */
 #include <linux/rwsem.h>
 #include <linux/sched.h>
+#include <linux/init.h>
 #include <linux/module.h>
 
 struct rwsem_waiter {
@@ -162,7 +163,7 @@ static inline struct rw_semaphore *rwsem
 /*
  * wait for the read lock to be granted
  */
-struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem)
+__sched struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem)
 {
 	struct rwsem_waiter waiter;
 
@@ -178,7 +179,7 @@ struct rw_semaphore *rwsem_down_read_fai
 /*
  * wait for the write lock to be granted
  */
-struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem)
+__sched struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem)
 {
 	struct rwsem_waiter waiter;
 

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2003-11-20 23:00 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-11-18  7:44 use ELF sections for get_wchan() William Lee Irwin III
2003-11-18  8:43 ` Russell King
2003-11-18  8:45   ` William Lee Irwin III
2003-11-18  8:50     ` William Lee Irwin III
2003-11-19  3:13       ` William Lee Irwin III
2003-11-19  5:53         ` Sam Ravnborg
2003-11-19  6:19           ` William Lee Irwin III
2003-11-20 20:28 ` Anton Blanchard
2003-11-20 20:50   ` William Lee Irwin III
2003-11-20 22:55     ` William Lee Irwin III

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox