
From: William Lee Irwin III <wli@holomorphy.com>

This addresses the issue with get_wchan() that the various functions acting
as scheduling-related primitives are not, in fact, contiguous in the text
segment.  It creates an ELF section for scheduling primitives to be placed
in, and places currently-detected (i.e.  skipped during stack decoding)
scheduling primitives and others like io_schedule() and down(), which are
currently missed by get_wchan() code, into this section also.

The net effects are more reliability of get_wchan()'s results and the new
ability, made use of by this code, to arbitrarily place scheduling
primitives in the source code without disturbing get_wchan()'s accuracy.

Suggestions by Arnd Bergmann and Matthew Wilcox regarding reducing the
invasiveness of the patch were incorporated during prior rounds of review. 
I've at least tried to sweep all arches in this patch.



---

 25-akpm/arch/alpha/kernel/process.c                |    2 -
 25-akpm/arch/alpha/kernel/semaphore.c              |    9 ++---
 25-akpm/arch/alpha/kernel/vmlinux.lds.S            |    1 
 25-akpm/arch/arm/kernel/process.c                  |    2 -
 25-akpm/arch/arm/kernel/semaphore.c                |    8 ++--
 25-akpm/arch/arm/kernel/vmlinux.lds.S              |    1 
 25-akpm/arch/arm26/kernel/process.c                |    2 -
 25-akpm/arch/arm26/kernel/semaphore.c              |    8 ++--
 25-akpm/arch/arm26/kernel/vmlinux-arm26-xip.lds.in |    1 
 25-akpm/arch/arm26/kernel/vmlinux-arm26.lds.in     |    1 
 25-akpm/arch/cris/arch-v10/kernel/process.c        |    3 -
 25-akpm/arch/cris/arch-v10/vmlinux.lds.S           |    1 
 25-akpm/arch/cris/kernel/semaphore.c               |    5 +-
 25-akpm/arch/h8300/kernel/process.c                |    3 -
 25-akpm/arch/h8300/kernel/semaphore.c              |    5 +-
 25-akpm/arch/h8300/kernel/vmlinux.lds.S            |    1 
 25-akpm/arch/i386/kernel/process.c                 |    2 -
 25-akpm/arch/i386/kernel/semaphore.c               |   17 +++++----
 25-akpm/arch/i386/kernel/vmlinux.lds.S             |    1 
 25-akpm/arch/ia64/kernel/process.c                 |    2 -
 25-akpm/arch/ia64/kernel/semaphore.c               |    7 +--
 25-akpm/arch/ia64/kernel/vmlinux.lds.S             |    1 
 25-akpm/arch/m68k/kernel/process.c                 |    5 --
 25-akpm/arch/m68k/kernel/semaphore.c               |    5 +-
 25-akpm/arch/m68k/kernel/vmlinux-std.lds           |    1 
 25-akpm/arch/m68k/kernel/vmlinux-sun3.lds          |    1 
 25-akpm/arch/m68knommu/kernel/process.c            |    5 --
 25-akpm/arch/m68knommu/kernel/semaphore.c          |    5 +-
 25-akpm/arch/m68knommu/kernel/vmlinux.lds.S        |    1 
 25-akpm/arch/mips/kernel/process.c                 |    2 -
 25-akpm/arch/mips/kernel/semaphore.c               |    5 +-
 25-akpm/arch/mips/kernel/vmlinux.lds.S             |    1 
 25-akpm/arch/parisc/kernel/semaphore.c             |    5 +-
 25-akpm/arch/parisc/kernel/vmlinux.lds.S           |    1 
 25-akpm/arch/ppc/kernel/process.c                  |    2 -
 25-akpm/arch/ppc/kernel/semaphore.c                |    5 +-
 25-akpm/arch/ppc/kernel/vmlinux.lds.S              |    1 
 25-akpm/arch/ppc64/kernel/process.c                |    2 -
 25-akpm/arch/ppc64/kernel/semaphore.c              |    5 +-
 25-akpm/arch/ppc64/kernel/vmlinux.lds.S            |    1 
 25-akpm/arch/s390/kernel/process.c                 |    2 -
 25-akpm/arch/s390/kernel/semaphore.c               |    5 +-
 25-akpm/arch/s390/kernel/vmlinux.lds.S             |    1 
 25-akpm/arch/sh/kernel/process.c                   |    4 --
 25-akpm/arch/sh/kernel/semaphore.c                 |    5 +-
 25-akpm/arch/sh/kernel/vmlinux.lds.S               |    1 
 25-akpm/arch/sparc/kernel/process.c                |    4 --
 25-akpm/arch/sparc/kernel/semaphore.c              |    5 +-
 25-akpm/arch/sparc/kernel/vmlinux.lds.S            |    1 
 25-akpm/arch/sparc/lib/rwsem.S                     |    3 +
 25-akpm/arch/sparc64/kernel/process.c              |    4 --
 25-akpm/arch/sparc64/kernel/semaphore.c            |    9 ++---
 25-akpm/arch/sparc64/kernel/vmlinux.lds.S          |    1 
 25-akpm/arch/sparc64/lib/rwsem.c                   |    5 +-
 25-akpm/arch/v850/kernel/process.c                 |    3 -
 25-akpm/arch/v850/kernel/semaphore.c               |    5 +-
 25-akpm/arch/v850/kernel/vmlinux.lds.S             |    1 
 25-akpm/arch/x86_64/kernel/process.c               |    2 -
 25-akpm/arch/x86_64/kernel/semaphore.c             |    5 +-
 25-akpm/arch/x86_64/kernel/vmlinux.lds.S           |    1 
 25-akpm/arch/x86_64/lib/thunk.S                    |    3 +
 25-akpm/include/asm-generic/vmlinux.lds.h          |    5 ++
 25-akpm/include/linux/init.h                       |    2 +
 25-akpm/include/linux/sched.h                      |    2 +
 25-akpm/kernel/sched.c                             |   37 +++++++++++----------
 25-akpm/kernel/timer.c                             |    4 +-
 25-akpm/lib/rwsem.c                                |    5 +-
 67 files changed, 137 insertions(+), 124 deletions(-)

diff -puN arch/alpha/kernel/process.c~wchan-use-ELF-sections arch/alpha/kernel/process.c
--- 25/arch/alpha/kernel/process.c~wchan-use-ELF-sections	2004-04-03 02:59:47.186179552 -0800
+++ 25-akpm/arch/alpha/kernel/process.c	2004-04-03 02:59:47.274166176 -0800
@@ -513,8 +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)
 
diff -puN arch/alpha/kernel/semaphore.c~wchan-use-ELF-sections arch/alpha/kernel/semaphore.c
--- 25/arch/alpha/kernel/semaphore.c~wchan-use-ELF-sections	2004-04-03 02:59:47.187179400 -0800
+++ 25-akpm/arch/alpha/kernel/semaphore.c	2004-04-03 02:59:47.274166176 -0800
@@ -7,6 +7,7 @@
 
 #include <linux/errno.h>
 #include <linux/sched.h>
+#include <linux/init.h>
 
 /*
  * This is basically the PPC semaphore scheme ported to use
@@ -60,7 +61,7 @@ static inline int __sem_update_count(str
  * Either form may be used in conjunction with "up()".
  */
 
-void
+void __sched
 __down_failed(struct semaphore *sem)
 {
 	struct task_struct *tsk = current;
@@ -101,7 +102,7 @@ __down_failed(struct semaphore *sem)
 #endif
 }
 
-int
+int __sched
 __down_failed_interruptible(struct semaphore *sem)
 {
 	struct task_struct *tsk = current;
@@ -159,7 +160,7 @@ __up_wakeup(struct semaphore *sem)
 	wake_up(&sem->wait);
 }
 
-void
+void __sched
 down(struct semaphore *sem)
 {
 #if WAITQUEUE_DEBUG
@@ -173,7 +174,7 @@ down(struct semaphore *sem)
 	__down(sem);
 }
 
-int
+int __sched
 down_interruptible(struct semaphore *sem)
 {
 #if WAITQUEUE_DEBUG
diff -puN arch/alpha/kernel/vmlinux.lds.S~wchan-use-ELF-sections arch/alpha/kernel/vmlinux.lds.S
--- 25/arch/alpha/kernel/vmlinux.lds.S~wchan-use-ELF-sections	2004-04-03 02:59:47.188179248 -0800
+++ 25-akpm/arch/alpha/kernel/vmlinux.lds.S	2004-04-03 02:59:47.275166024 -0800
@@ -17,6 +17,7 @@ SECTIONS
   _text = .;					/* Text and read-only data */
   .text : { 
 	*(.text) 
+	SCHED_TEXT
 	*(.fixup)
 	*(.gnu.warning)
   } :kernel
diff -puN arch/arm26/kernel/process.c~wchan-use-ELF-sections arch/arm26/kernel/process.c
--- 25/arch/arm26/kernel/process.c~wchan-use-ELF-sections	2004-04-03 02:59:47.189179096 -0800
+++ 25-akpm/arch/arm26/kernel/process.c	2004-04-03 02:59:47.275166024 -0800
@@ -400,8 +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)
 
diff -puN arch/arm26/kernel/semaphore.c~wchan-use-ELF-sections arch/arm26/kernel/semaphore.c
--- 25/arch/arm26/kernel/semaphore.c~wchan-use-ELF-sections	2004-04-03 02:59:47.191178792 -0800
+++ 25-akpm/arch/arm26/kernel/semaphore.c	2004-04-03 02:59:47.276165872 -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)
+void __sched __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)
+int __sched __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 -puN arch/arm26/kernel/vmlinux-arm26.lds.in~wchan-use-ELF-sections arch/arm26/kernel/vmlinux-arm26.lds.in
--- 25/arch/arm26/kernel/vmlinux-arm26.lds.in~wchan-use-ELF-sections	2004-04-03 02:59:47.192178640 -0800
+++ 25-akpm/arch/arm26/kernel/vmlinux-arm26.lds.in	2004-04-03 02:59:47.276165872 -0800
@@ -67,6 +67,7 @@ SECTIONS
 	.text : {			/* Real text segment		*/
 		_text = .;		/* Text and read-only data	*/
 			*(.text)
+			SCHED_TEXT
 			*(.fixup)
 			*(.gnu.warning)
 			*(.rodata)
diff -puN arch/arm26/kernel/vmlinux-arm26-xip.lds.in~wchan-use-ELF-sections arch/arm26/kernel/vmlinux-arm26-xip.lds.in
--- 25/arch/arm26/kernel/vmlinux-arm26-xip.lds.in~wchan-use-ELF-sections	2004-04-03 02:59:47.193178488 -0800
+++ 25-akpm/arch/arm26/kernel/vmlinux-arm26-xip.lds.in	2004-04-03 02:59:47.277165720 -0800
@@ -66,6 +66,7 @@ SECTIONS
 	.text : {			/* Real text segment		*/
 		_text = .;		/* Text and read-only data	*/
 			*(.text)
+			SCHED_TEXT
 			*(.fixup)
 			*(.gnu.warning)
 			*(.rodata)
diff -puN arch/arm/kernel/process.c~wchan-use-ELF-sections arch/arm/kernel/process.c
--- 25/arch/arm/kernel/process.c~wchan-use-ELF-sections	2004-04-03 02:59:47.194178336 -0800
+++ 25-akpm/arch/arm/kernel/process.c	2004-04-03 02:59:47.277165720 -0800
@@ -414,8 +414,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)
 
diff -puN arch/arm/kernel/semaphore.c~wchan-use-ELF-sections arch/arm/kernel/semaphore.c
--- 25/arch/arm/kernel/semaphore.c~wchan-use-ELF-sections	2004-04-03 02:59:47.196178032 -0800
+++ 25-akpm/arch/arm/kernel/semaphore.c	2004-04-03 02:59:47.278165568 -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)
+void __sched __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)
+int __sched __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 -puN arch/arm/kernel/vmlinux.lds.S~wchan-use-ELF-sections arch/arm/kernel/vmlinux.lds.S
--- 25/arch/arm/kernel/vmlinux.lds.S~wchan-use-ELF-sections	2004-04-03 02:59:47.197177880 -0800
+++ 25-akpm/arch/arm/kernel/vmlinux.lds.S	2004-04-03 02:59:47.278165568 -0800
@@ -73,6 +73,7 @@ SECTIONS
 	.text : {			/* Real text segment		*/
 		_text = .;		/* Text and read-only data	*/
 			*(.text)
+			SCHED_TEXT
 			*(.fixup)
 			*(.gnu.warning)
 			*(.rodata)
diff -puN arch/cris/arch-v10/kernel/process.c~wchan-use-ELF-sections arch/cris/arch-v10/kernel/process.c
--- 25/arch/cris/arch-v10/kernel/process.c~wchan-use-ELF-sections	2004-04-03 02:59:47.198177728 -0800
+++ 25-akpm/arch/cris/arch-v10/kernel/process.c	2004-04-03 02:59:47.278165568 -0800
@@ -16,6 +16,7 @@
 #include <linux/err.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
+#include <linux/init.h>
 
 #ifdef CONFIG_ETRAX_GPIO
 void etrax_gpio_wake_up_check(void); /* drivers/gpio.c */
@@ -216,8 +217,6 @@ asmlinkage int sys_execve(const char *fn
  * 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)
 
diff -puN arch/cris/arch-v10/vmlinux.lds.S~wchan-use-ELF-sections arch/cris/arch-v10/vmlinux.lds.S
--- 25/arch/cris/arch-v10/vmlinux.lds.S~wchan-use-ELF-sections	2004-04-03 02:59:47.199177576 -0800
+++ 25-akpm/arch/cris/arch-v10/vmlinux.lds.S	2004-04-03 02:59:47.279165416 -0800
@@ -25,6 +25,7 @@ SECTIONS
 	__stext = .;
 	.text : {
 		*(.text)
+		SCHED_TEXT
 		*(.fixup)
 		*(.text.__*)
 	}
diff -puN arch/cris/kernel/semaphore.c~wchan-use-ELF-sections arch/cris/kernel/semaphore.c
--- 25/arch/cris/kernel/semaphore.c~wchan-use-ELF-sections	2004-04-03 02:59:47.200177424 -0800
+++ 25-akpm/arch/cris/kernel/semaphore.c	2004-04-03 02:59:47.279165416 -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)
+void __sched __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)
+int __sched __down_interruptible(struct semaphore * sem)
 {
 	int ret = 0;
 	DOWN_VAR
diff -puN arch/h8300/kernel/process.c~wchan-use-ELF-sections arch/h8300/kernel/process.c
--- 25/arch/h8300/kernel/process.c~wchan-use-ELF-sections	2004-04-03 02:59:47.202177120 -0800
+++ 25-akpm/arch/h8300/kernel/process.c	2004-04-03 02:59:47.280165264 -0800
@@ -264,8 +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)
 
@@ -289,7 +287,6 @@ 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)
 			return pc;
 		fp = *(unsigned long *) fp;
diff -puN arch/h8300/kernel/semaphore.c~wchan-use-ELF-sections arch/h8300/kernel/semaphore.c
--- 25/arch/h8300/kernel/semaphore.c~wchan-use-ELF-sections	2004-04-03 02:59:47.203176968 -0800
+++ 25-akpm/arch/h8300/kernel/semaphore.c	2004-04-03 02:59:47.280165264 -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)
+void __sched __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)
+int __sched __down_interruptible(struct semaphore * sem)
 {
 	DECLARE_WAITQUEUE(wait, current);
 	int ret = 0;
diff -puN arch/h8300/kernel/vmlinux.lds.S~wchan-use-ELF-sections arch/h8300/kernel/vmlinux.lds.S
--- 25/arch/h8300/kernel/vmlinux.lds.S~wchan-use-ELF-sections	2004-04-03 02:59:47.204176816 -0800
+++ 25-akpm/arch/h8300/kernel/vmlinux.lds.S	2004-04-03 02:59:47.280165264 -0800
@@ -82,6 +82,7 @@ SECTIONS
 #endif
 	__stext = . ;
         	*(.text)
+	SCHED_TEXT
 	. = ALIGN(0x4) ;
 		*(.exit.text)
 		*(.text.*)
diff -puN arch/i386/kernel/process.c~wchan-use-ELF-sections arch/i386/kernel/process.c
--- 25/arch/i386/kernel/process.c~wchan-use-ELF-sections	2004-04-03 02:59:47.205176664 -0800
+++ 25-akpm/arch/i386/kernel/process.c	2004-04-03 02:59:47.281165112 -0800
@@ -632,8 +632,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)
 #define top_esp                (THREAD_SIZE - sizeof(unsigned long))
diff -puN arch/i386/kernel/semaphore.c~wchan-use-ELF-sections arch/i386/kernel/semaphore.c
--- 25/arch/i386/kernel/semaphore.c~wchan-use-ELF-sections	2004-04-03 02:59:47.206176512 -0800
+++ 25-akpm/arch/i386/kernel/semaphore.c	2004-04-03 02:59:47.282164960 -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 @@ asmlinkage void __up(struct semaphore *s
 	wake_up(&sem->wait);
 }
 
-asmlinkage void __down(struct semaphore * sem)
+asmlinkage void __sched __down(struct semaphore * sem)
 {
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
@@ -90,7 +91,7 @@ asmlinkage void __down(struct semaphore 
 	tsk->state = TASK_RUNNING;
 }
 
-asmlinkage int __down_interruptible(struct semaphore * sem)
+asmlinkage int __sched __down_interruptible(struct semaphore * sem)
 {
 	int retval = 0;
 	struct task_struct *tsk = current;
@@ -187,7 +188,7 @@ asmlinkage int __down_trylock(struct sem
  * 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 -puN arch/i386/kernel/vmlinux.lds.S~wchan-use-ELF-sections arch/i386/kernel/vmlinux.lds.S
--- 25/arch/i386/kernel/vmlinux.lds.S~wchan-use-ELF-sections	2004-04-03 02:59:47.208176208 -0800
+++ 25-akpm/arch/i386/kernel/vmlinux.lds.S	2004-04-03 02:59:47.282164960 -0800
@@ -16,6 +16,7 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
+	SCHED_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x9090
diff -puN arch/ia64/kernel/process.c~wchan-use-ELF-sections arch/ia64/kernel/process.c
--- 25/arch/ia64/kernel/process.c~wchan-use-ELF-sections	2004-04-03 02:59:47.209176056 -0800
+++ 25-akpm/arch/ia64/kernel/process.c	2004-04-03 02:59:47.283164808 -0800
@@ -660,8 +660,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)
 
diff -puN arch/ia64/kernel/semaphore.c~wchan-use-ELF-sections arch/ia64/kernel/semaphore.c
--- 25/arch/ia64/kernel/semaphore.c~wchan-use-ELF-sections	2004-04-03 02:59:47.210175904 -0800
+++ 25-akpm/arch/ia64/kernel/semaphore.c	2004-04-03 02:59:47.283164808 -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,8 +45,7 @@ __up (struct semaphore *sem)
 	wake_up(&sem->wait);
 }
 
-void
-__down (struct semaphore *sem)
+void __sched __down (struct semaphore *sem)
 {
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
@@ -82,8 +82,7 @@ __down (struct semaphore *sem)
 	tsk->state = TASK_RUNNING;
 }
 
-int
-__down_interruptible (struct semaphore * sem)
+int __sched __down_interruptible (struct semaphore * sem)
 {
 	int retval = 0;
 	struct task_struct *tsk = current;
diff -puN arch/ia64/kernel/vmlinux.lds.S~wchan-use-ELF-sections arch/ia64/kernel/vmlinux.lds.S
--- 25/arch/ia64/kernel/vmlinux.lds.S~wchan-use-ELF-sections	2004-04-03 02:59:47.211175752 -0800
+++ 25-akpm/arch/ia64/kernel/vmlinux.lds.S	2004-04-03 02:59:47.284164656 -0800
@@ -41,6 +41,7 @@ SECTIONS
     {
 	*(.text.ivt)
 	*(.text)
+	SCHED_TEXT
 	*(.gnu.linkonce.t*)
     }
   .text2 : AT(ADDR(.text2) - LOAD_OFFSET)
diff -puN arch/m68k/kernel/process.c~wchan-use-ELF-sections arch/m68k/kernel/process.c
--- 25/arch/m68k/kernel/process.c~wchan-use-ELF-sections	2004-04-03 02:59:47.213175448 -0800
+++ 25-akpm/arch/m68k/kernel/process.c	2004-04-03 02:59:47.284164656 -0800
@@ -65,8 +65,6 @@ 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 &&
@@ -387,8 +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)
 
@@ -407,7 +403,6 @@ 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)
 			return pc;
 		fp = *(unsigned long *) fp;
diff -puN arch/m68k/kernel/semaphore.c~wchan-use-ELF-sections arch/m68k/kernel/semaphore.c
--- 25/arch/m68k/kernel/semaphore.c~wchan-use-ELF-sections	2004-04-03 02:59:47.214175296 -0800
+++ 25-akpm/arch/m68k/kernel/semaphore.c	2004-04-03 02:59:47.285164504 -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)
+void __sched __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)
+int __sched __down_interruptible(struct semaphore * sem)
 {
 	DECLARE_WAITQUEUE(wait, current);
 	int ret = 0;
diff -puN arch/m68k/kernel/vmlinux-std.lds~wchan-use-ELF-sections arch/m68k/kernel/vmlinux-std.lds
--- 25/arch/m68k/kernel/vmlinux-std.lds~wchan-use-ELF-sections	2004-04-03 02:59:47.215175144 -0800
+++ 25-akpm/arch/m68k/kernel/vmlinux-std.lds	2004-04-03 02:59:47.285164504 -0800
@@ -12,6 +12,7 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
+	SCHED_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x4e75
diff -puN arch/m68k/kernel/vmlinux-sun3.lds~wchan-use-ELF-sections arch/m68k/kernel/vmlinux-sun3.lds
--- 25/arch/m68k/kernel/vmlinux-sun3.lds~wchan-use-ELF-sections	2004-04-03 02:59:47.216174992 -0800
+++ 25-akpm/arch/m68k/kernel/vmlinux-sun3.lds	2004-04-03 02:59:47.285164504 -0800
@@ -13,6 +13,7 @@ SECTIONS
   .text : {
 	*(.head)
 	*(.text)
+	SCHED_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x4e75
diff -puN arch/m68knommu/kernel/process.c~wchan-use-ELF-sections arch/m68knommu/kernel/process.c
--- 25/arch/m68knommu/kernel/process.c~wchan-use-ELF-sections	2004-04-03 02:59:47.218174688 -0800
+++ 25-akpm/arch/m68knommu/kernel/process.c	2004-04-03 02:59:47.286164352 -0800
@@ -406,8 +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)
 
@@ -426,7 +424,6 @@ 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)
 			return pc;
 		fp = *(unsigned long *) fp;
@@ -439,8 +436,6 @@ 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() */
diff -puN arch/m68knommu/kernel/semaphore.c~wchan-use-ELF-sections arch/m68knommu/kernel/semaphore.c
--- 25/arch/m68knommu/kernel/semaphore.c~wchan-use-ELF-sections	2004-04-03 02:59:47.219174536 -0800
+++ 25-akpm/arch/m68knommu/kernel/semaphore.c	2004-04-03 02:59:47.286164352 -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)
+void __sched __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)
+int __sched __down_interruptible(struct semaphore * sem)
 {
 	DECLARE_WAITQUEUE(wait, current);
 	int ret = 0;
diff -puN arch/m68knommu/kernel/vmlinux.lds.S~wchan-use-ELF-sections arch/m68knommu/kernel/vmlinux.lds.S
--- 25/arch/m68knommu/kernel/vmlinux.lds.S~wchan-use-ELF-sections	2004-04-03 02:59:47.220174384 -0800
+++ 25-akpm/arch/m68knommu/kernel/vmlinux.lds.S	2004-04-03 02:59:47.287164200 -0800
@@ -191,6 +191,7 @@ SECTIONS {
 	.text : {
 		_stext = . ;
         	*(.text)
+		SCHED_TEXT
         	*(.text.lock)
 
 		. = ALIGN(16);          /* Exception table              */
diff -puN arch/mips/kernel/process.c~wchan-use-ELF-sections arch/mips/kernel/process.c
--- 25/arch/mips/kernel/process.c~wchan-use-ELF-sections	2004-04-03 02:59:47.222174080 -0800
+++ 25-akpm/arch/mips/kernel/process.c	2004-04-03 02:59:47.287164200 -0800
@@ -283,8 +283,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)
 
diff -puN arch/mips/kernel/semaphore.c~wchan-use-ELF-sections arch/mips/kernel/semaphore.c
--- 25/arch/mips/kernel/semaphore.c~wchan-use-ELF-sections	2004-04-03 02:59:47.223173928 -0800
+++ 25-akpm/arch/mips/kernel/semaphore.c	2004-04-03 02:59:47.288164048 -0800
@@ -6,6 +6,7 @@
 #include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/module.h>
+#include <linux/init.h>
 #include <linux/sched.h>
 
 #ifdef CONFIG_CPU_HAS_LLDSCD
@@ -104,7 +105,7 @@ static inline int waking_non_zero(struct
  * Either form may be used in conjunction with "up()".
  */
 
-void __down_failed(struct semaphore * sem)
+void __sched __down_failed(struct semaphore * sem)
 {
 	struct task_struct *tsk = current;
 	wait_queue_t wait;
@@ -227,7 +228,7 @@ static inline int waking_non_zero_interr
 
 #endif /* !CONFIG_CPU_HAS_LLDSCD */
 
-int __down_failed_interruptible(struct semaphore * sem)
+int __sched __down_failed_interruptible(struct semaphore * sem)
 {
 	struct task_struct *tsk = current;
 	wait_queue_t wait;
diff -puN arch/mips/kernel/vmlinux.lds.S~wchan-use-ELF-sections arch/mips/kernel/vmlinux.lds.S
--- 25/arch/mips/kernel/vmlinux.lds.S~wchan-use-ELF-sections	2004-04-03 02:59:47.224173776 -0800
+++ 25-akpm/arch/mips/kernel/vmlinux.lds.S	2004-04-03 02:59:47.288164048 -0800
@@ -28,6 +28,7 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
     *(.text)
+    SCHED_TEXT
     *(.fixup)
     *(.gnu.warning)
   } =0
diff -puN arch/parisc/kernel/semaphore.c~wchan-use-ELF-sections arch/parisc/kernel/semaphore.c
--- 25/arch/parisc/kernel/semaphore.c~wchan-use-ELF-sections	2004-04-03 02:59:47.225173624 -0800
+++ 25-akpm/arch/parisc/kernel/semaphore.c	2004-04-03 02:59:47.289163896 -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)
+void __sched __down(struct semaphore * sem)
 {
 	DOWN_HEAD
 
@@ -74,7 +75,7 @@ void __down(struct semaphore * sem)
 	UPDATE_COUNT
 }
 
-int __down_interruptible(struct semaphore * sem)
+int __sched __down_interruptible(struct semaphore * sem)
 {
 	DOWN_HEAD
 
diff -puN arch/parisc/kernel/vmlinux.lds.S~wchan-use-ELF-sections arch/parisc/kernel/vmlinux.lds.S
--- 25/arch/parisc/kernel/vmlinux.lds.S~wchan-use-ELF-sections	2004-04-03 02:59:47.227173320 -0800
+++ 25-akpm/arch/parisc/kernel/vmlinux.lds.S	2004-04-03 02:59:47.289163896 -0800
@@ -50,6 +50,7 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text ALIGN(16) : {
 	*(.text*)
+	SCHED_TEXT
 	*(.PARISC.unwind)
 	*(.fixup)
 	*(.lock.text)		/* out-of-line lock text */
diff -puN arch/ppc64/kernel/process.c~wchan-use-ELF-sections arch/ppc64/kernel/process.c
--- 25/arch/ppc64/kernel/process.c~wchan-use-ELF-sections	2004-04-03 02:59:47.228173168 -0800
+++ 25-akpm/arch/ppc64/kernel/process.c	2004-04-03 02:59:47.290163744 -0800
@@ -475,8 +475,6 @@ static inline int validate_sp(unsigned l
 /*
  * 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)
 
diff -puN arch/ppc64/kernel/semaphore.c~wchan-use-ELF-sections arch/ppc64/kernel/semaphore.c
--- 25/arch/ppc64/kernel/semaphore.c~wchan-use-ELF-sections	2004-04-03 02:59:47.229173016 -0800
+++ 25-akpm/arch/ppc64/kernel/semaphore.c	2004-04-03 02:59:47.290163744 -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)
+void __sched __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)
+int __sched __down_interruptible(struct semaphore * sem)
 {
 	int retval = 0;
 	struct task_struct *tsk = current;
diff -puN arch/ppc64/kernel/vmlinux.lds.S~wchan-use-ELF-sections arch/ppc64/kernel/vmlinux.lds.S
--- 25/arch/ppc64/kernel/vmlinux.lds.S~wchan-use-ELF-sections	2004-04-03 02:59:47.231172712 -0800
+++ 25-akpm/arch/ppc64/kernel/vmlinux.lds.S	2004-04-03 02:59:47.290163744 -0800
@@ -13,6 +13,7 @@ SECTIONS
   /* Read-only sections, merged into text segment: */
   .text : {
 	*(.text .text.*)
+	SCHED_TEXT
 	*(.fixup)
 	. = ALIGN(4096);
 	_etext = .;
diff -puN arch/ppc/kernel/process.c~wchan-use-ELF-sections arch/ppc/kernel/process.c
--- 25/arch/ppc/kernel/process.c~wchan-use-ELF-sections	2004-04-03 02:59:47.232172560 -0800
+++ 25-akpm/arch/ppc/kernel/process.c	2004-04-03 02:59:47.291163592 -0800
@@ -661,8 +661,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)
 
diff -puN arch/ppc/kernel/semaphore.c~wchan-use-ELF-sections arch/ppc/kernel/semaphore.c
--- 25/arch/ppc/kernel/semaphore.c~wchan-use-ELF-sections	2004-04-03 02:59:47.233172408 -0800
+++ 25-akpm/arch/ppc/kernel/semaphore.c	2004-04-03 02:59:47.292163440 -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)
+void __sched __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)
+int __sched __down_interruptible(struct semaphore * sem)
 {
 	int retval = 0;
 	struct task_struct *tsk = current;
diff -puN arch/ppc/kernel/vmlinux.lds.S~wchan-use-ELF-sections arch/ppc/kernel/vmlinux.lds.S
--- 25/arch/ppc/kernel/vmlinux.lds.S~wchan-use-ELF-sections	2004-04-03 02:59:47.235172104 -0800
+++ 25-akpm/arch/ppc/kernel/vmlinux.lds.S	2004-04-03 02:59:47.292163440 -0800
@@ -31,6 +31,7 @@ SECTIONS
   .text      :
   {
     *(.text)
+    SCHED_TEXT
     *(.fixup)
     *(.got1)
     __got2_start = .;
diff -puN arch/s390/kernel/process.c~wchan-use-ELF-sections arch/s390/kernel/process.c
--- 25/arch/s390/kernel/process.c~wchan-use-ELF-sections	2004-04-03 02:59:47.236171952 -0800
+++ 25-akpm/arch/s390/kernel/process.c	2004-04-03 02:59:47.292163440 -0800
@@ -384,8 +384,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)
 
diff -puN arch/s390/kernel/semaphore.c~wchan-use-ELF-sections arch/s390/kernel/semaphore.c
--- 25/arch/s390/kernel/semaphore.c~wchan-use-ELF-sections	2004-04-03 02:59:47.237171800 -0800
+++ 25-akpm/arch/s390/kernel/semaphore.c	2004-04-03 02:59:47.293163288 -0800
@@ -11,6 +11,7 @@
  */
 #include <linux/sched.h>
 #include <linux/errno.h>
+#include <linux/init.h>
 
 #include <asm/semaphore.h>
 
@@ -60,7 +61,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)
+void __sched __down(struct semaphore * sem)
 {
 	struct task_struct *tsk = current;
 	DECLARE_WAITQUEUE(wait, tsk);
@@ -82,7 +83,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)
+int __sched __down_interruptible(struct semaphore * sem)
 {
 	int retval = 0;
 	struct task_struct *tsk = current;
diff -puN arch/s390/kernel/vmlinux.lds.S~wchan-use-ELF-sections arch/s390/kernel/vmlinux.lds.S
--- 25/arch/s390/kernel/vmlinux.lds.S~wchan-use-ELF-sections	2004-04-03 02:59:47.238171648 -0800
+++ 25-akpm/arch/s390/kernel/vmlinux.lds.S	2004-04-03 02:59:47.293163288 -0800
@@ -23,6 +23,7 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
+	SCHED_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x0700
diff -puN arch/sh/kernel/process.c~wchan-use-ELF-sections arch/sh/kernel/process.c
--- 25/arch/sh/kernel/process.c~wchan-use-ELF-sections	2004-04-03 02:59:47.240171344 -0800
+++ 25-akpm/arch/sh/kernel/process.c	2004-04-03 02:59:47.294163136 -0800
@@ -464,8 +464,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)
 
@@ -481,7 +479,7 @@ unsigned long get_wchan(struct task_stru
 	 * The same comment as on the Alpha applies here, too ...
 	 */
 	pc = thread_saved_pc(p);
-	if (pc >= (unsigned long) interruptible_sleep_on && pc < (unsigned long) add_timer) {
+	if (pc >= first_sched && pc < last_sched) {
 		schedule_frame = ((unsigned long *)(long)p->thread.sp)[1];
 		return (unsigned long)((unsigned long *)schedule_frame)[1];
 	}
diff -puN arch/sh/kernel/semaphore.c~wchan-use-ELF-sections arch/sh/kernel/semaphore.c
--- 25/arch/sh/kernel/semaphore.c~wchan-use-ELF-sections	2004-04-03 02:59:47.241171192 -0800
+++ 25-akpm/arch/sh/kernel/semaphore.c	2004-04-03 02:59:47.294163136 -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)
+void __sched __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)
+int __sched __down_interruptible(struct semaphore * sem)
 {
 	int ret = 0;
 	DOWN_VAR
diff -puN arch/sh/kernel/vmlinux.lds.S~wchan-use-ELF-sections arch/sh/kernel/vmlinux.lds.S
--- 25/arch/sh/kernel/vmlinux.lds.S~wchan-use-ELF-sections	2004-04-03 02:59:47.242171040 -0800
+++ 25-akpm/arch/sh/kernel/vmlinux.lds.S	2004-04-03 02:59:47.294163136 -0800
@@ -22,6 +22,7 @@ SECTIONS
 	} = 0
   .text : {
 	*(.text)
+	SCHED_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x0009
diff -puN arch/sparc64/kernel/process.c~wchan-use-ELF-sections arch/sparc64/kernel/process.c
--- 25/arch/sparc64/kernel/process.c~wchan-use-ELF-sections	2004-04-03 02:59:47.243170888 -0800
+++ 25-akpm/arch/sparc64/kernel/process.c	2004-04-03 02:59:47.295162984 -0800
@@ -28,6 +28,7 @@
 #include <linux/config.h>
 #include <linux/reboot.h>
 #include <linux/delay.h>
+#include <linux/init.h>
 
 #include <asm/oplib.h>
 #include <asm/uaccess.h>
@@ -823,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;
diff -puN arch/sparc64/kernel/semaphore.c~wchan-use-ELF-sections arch/sparc64/kernel/semaphore.c
--- 25/arch/sparc64/kernel/semaphore.c~wchan-use-ELF-sections	2004-04-03 02:59:47.245170584 -0800
+++ 25-akpm/arch/sparc64/kernel/semaphore.c	2004-04-03 02:59:47.296162832 -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 void __sched __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)
+void __sched 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 int __sched __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)
+int __sched down_interruptible(struct semaphore *sem)
 {
 	int ret = 0;
 	
diff -puN arch/sparc64/kernel/vmlinux.lds.S~wchan-use-ELF-sections arch/sparc64/kernel/vmlinux.lds.S
--- 25/arch/sparc64/kernel/vmlinux.lds.S~wchan-use-ELF-sections	2004-04-03 02:59:47.246170432 -0800
+++ 25-akpm/arch/sparc64/kernel/vmlinux.lds.S	2004-04-03 02:59:47.296162832 -0800
@@ -15,6 +15,7 @@ SECTIONS
   .text 0x0000000000404000 :
   {
     *(.text)
+    SCHED_TEXT
     *(.gnu.warning)
   } =0
   _etext = .;
diff -puN arch/sparc64/lib/rwsem.c~wchan-use-ELF-sections arch/sparc64/lib/rwsem.c
--- 25/arch/sparc64/lib/rwsem.c~wchan-use-ELF-sections	2004-04-03 02:59:47.248170128 -0800
+++ 25-akpm/arch/sparc64/lib/rwsem.c	2004-04-03 02:59:47.297162680 -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)
+void __sched __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)
+void __sched __down_write(struct rw_semaphore *sem)
 {
 	__asm__ __volatile__(
 		"! beginning __down_write\n\t"
diff -puN arch/sparc/kernel/process.c~wchan-use-ELF-sections arch/sparc/kernel/process.c
--- 25/arch/sparc/kernel/process.c~wchan-use-ELF-sections	2004-04-03 02:59:47.249169976 -0800
+++ 25-akpm/arch/sparc/kernel/process.c	2004-04-03 02:59:47.297162680 -0800
@@ -28,6 +28,7 @@
 #include <linux/reboot.h>
 #include <linux/delay.h>
 #include <linux/pm.h>
+#include <linux/init.h>
 
 #include <asm/auxio.h>
 #include <asm/oplib.h>
@@ -694,9 +695,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;
diff -puN arch/sparc/kernel/semaphore.c~wchan-use-ELF-sections arch/sparc/kernel/semaphore.c
--- 25/arch/sparc/kernel/semaphore.c~wchan-use-ELF-sections	2004-04-03 02:59:47.250169824 -0800
+++ 25-akpm/arch/sparc/kernel/semaphore.c	2004-04-03 02:59:47.298162528 -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)
+void __sched __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)
+int __sched __down_interruptible(struct semaphore * sem)
 {
 	int retval = 0;
 	struct task_struct *tsk = current;
diff -puN arch/sparc/kernel/vmlinux.lds.S~wchan-use-ELF-sections arch/sparc/kernel/vmlinux.lds.S
--- 25/arch/sparc/kernel/vmlinux.lds.S~wchan-use-ELF-sections	2004-04-03 02:59:47.252169520 -0800
+++ 25-akpm/arch/sparc/kernel/vmlinux.lds.S	2004-04-03 02:59:47.298162528 -0800
@@ -12,6 +12,7 @@ SECTIONS
   .text 0xf0004000 :
   {
     *(.text)
+    SCHED_TEXT
     *(.gnu.warning)
   } =0
   _etext = .;
diff -puN arch/sparc/lib/rwsem.S~wchan-use-ELF-sections arch/sparc/lib/rwsem.S
--- 25/arch/sparc/lib/rwsem.S~wchan-use-ELF-sections	2004-04-03 02:59:47.253169368 -0800
+++ 25-akpm/arch/sparc/lib/rwsem.S	2004-04-03 02:59:47.298162528 -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 -puN arch/v850/kernel/process.c~wchan-use-ELF-sections arch/v850/kernel/process.c
--- 25/arch/v850/kernel/process.c~wchan-use-ELF-sections	2004-04-03 02:59:47.254169216 -0800
+++ 25-akpm/arch/v850/kernel/process.c	2004-04-03 02:59:47.299162376 -0800
@@ -203,8 +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)
 
@@ -228,7 +226,6 @@ unsigned long get_wchan (struct task_str
 		    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)
 			return pc;
 		fp = *(unsigned long *) fp;
diff -puN arch/v850/kernel/semaphore.c~wchan-use-ELF-sections arch/v850/kernel/semaphore.c
--- 25/arch/v850/kernel/semaphore.c~wchan-use-ELF-sections	2004-04-03 02:59:47.255169064 -0800
+++ 25-akpm/arch/v850/kernel/semaphore.c	2004-04-03 02:59:47.299162376 -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)
+void __sched __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)
+int __sched __down_interruptible(struct semaphore * sem)
 {
 	int retval = 0;
 	struct task_struct *tsk = current;
diff -puN arch/v850/kernel/vmlinux.lds.S~wchan-use-ELF-sections arch/v850/kernel/vmlinux.lds.S
--- 25/arch/v850/kernel/vmlinux.lds.S~wchan-use-ELF-sections	2004-04-03 02:59:47.256168912 -0800
+++ 25-akpm/arch/v850/kernel/vmlinux.lds.S	2004-04-03 02:59:47.300162224 -0800
@@ -64,6 +64,7 @@
 #define TEXT_CONTENTS							      \
 		__stext = . ;						      \
         	*(.text)						      \
+		SCHED_TEXT
 			*(.exit.text)	/* 2.5 convention */		      \
 			*(.text.exit)	/* 2.4 convention */		      \
 			*(.text.lock)					      \
diff -puN arch/x86_64/kernel/process.c~wchan-use-ELF-sections arch/x86_64/kernel/process.c
--- 25/arch/x86_64/kernel/process.c~wchan-use-ELF-sections	2004-04-03 02:59:47.258168608 -0800
+++ 25-akpm/arch/x86_64/kernel/process.c	2004-04-03 02:59:47.301162072 -0800
@@ -576,8 +576,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)
 
diff -puN arch/x86_64/kernel/semaphore.c~wchan-use-ELF-sections arch/x86_64/kernel/semaphore.c
--- 25/arch/x86_64/kernel/semaphore.c~wchan-use-ELF-sections	2004-04-03 02:59:47.259168456 -0800
+++ 25-akpm/arch/x86_64/kernel/semaphore.c	2004-04-03 02:59:47.301162072 -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)
+void __sched __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)
+int __sched __down_interruptible(struct semaphore * sem)
 {
 	int retval = 0;
 	struct task_struct *tsk = current;
diff -puN arch/x86_64/kernel/vmlinux.lds.S~wchan-use-ELF-sections arch/x86_64/kernel/vmlinux.lds.S
--- 25/arch/x86_64/kernel/vmlinux.lds.S~wchan-use-ELF-sections	2004-04-03 02:59:47.260168304 -0800
+++ 25-akpm/arch/x86_64/kernel/vmlinux.lds.S	2004-04-03 02:59:47.301162072 -0800
@@ -15,6 +15,7 @@ SECTIONS
   _text = .;			/* Text and read-only data */
   .text : {
 	*(.text)
+	SCHED_TEXT
 	*(.fixup)
 	*(.gnu.warning)
 	} = 0x9090
diff -puN arch/x86_64/lib/thunk.S~wchan-use-ELF-sections arch/x86_64/lib/thunk.S
--- 25/arch/x86_64/lib/thunk.S~wchan-use-ELF-sections	2004-04-03 02:59:47.261168152 -0800
+++ 25-akpm/arch/x86_64/lib/thunk.S	2004-04-03 02:59:47.302161920 -0800
@@ -35,6 +35,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
@@ -65,7 +66,7 @@ restore_norax:	
 
 #ifdef CONFIG_SMP
 /* Support for read/write spinlocks. */
-	
+	.text
 /* rax:	pointer to rwlock_t */	
 ENTRY(__write_lock_failed)
 	lock
diff -puN include/asm-generic/vmlinux.lds.h~wchan-use-ELF-sections include/asm-generic/vmlinux.lds.h
--- 25/include/asm-generic/vmlinux.lds.h~wchan-use-ELF-sections	2004-04-03 02:59:47.263167848 -0800
+++ 25-akpm/include/asm-generic/vmlinux.lds.h	2004-04-03 02:59:47.302161920 -0800
@@ -51,3 +51,8 @@
 		*(.security_initcall.init) 				\
 		__security_initcall_end = .;				\
 	}
+
+#define SCHED_TEXT							\
+		__scheduling_functions_start_here = .;			\
+		*(.sched.text)						\
+		__scheduling_functions_end_here = .;
diff -puN include/linux/init.h~wchan-use-ELF-sections include/linux/init.h
--- 25/include/linux/init.h~wchan-use-ELF-sections	2004-04-03 02:59:47.264167696 -0800
+++ 25-akpm/include/linux/init.h	2004-04-03 02:59:47.302161920 -0800
@@ -46,6 +46,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 -puN include/linux/sched.h~wchan-use-ELF-sections include/linux/sched.h
--- 25/include/linux/sched.h~wchan-use-ELF-sections	2004-04-03 02:59:47.266167392 -0800
+++ 25-akpm/include/linux/sched.h	2004-04-03 02:59:47.303161768 -0800
@@ -170,6 +170,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 -puN kernel/sched.c~wchan-use-ELF-sections kernel/sched.c
--- 25/kernel/sched.c~wchan-use-ELF-sections	2004-04-03 02:59:47.267167240 -0800
+++ 25-akpm/kernel/sched.c	2004-04-03 02:59:47.306161312 -0800
@@ -225,6 +225,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:
  */
@@ -1587,12 +1594,10 @@ out:
 	rebalance_tick(rq, 0);
 }
 
-void scheduling_functions_start_here(void) { }
-
 /*
  * schedule() is the main scheduler function.
  */
-asmlinkage void schedule(void)
+asmlinkage void __sched schedule(void)
 {
 	long *switch_count;
 	task_t *prev, *next;
@@ -1731,7 +1736,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 void __sched preempt_schedule(void)
 {
 	struct thread_info *ti = current_thread_info();
 
@@ -1869,7 +1874,7 @@ void fastcall complete_all(struct comple
 	spin_unlock_irqrestore(&x->wait.lock, flags);
 }
 
-void fastcall wait_for_completion(struct completion *x)
+void fastcall __sched wait_for_completion(struct completion *x)
 {
 	might_sleep();
 	spin_lock_irq(&x->wait.lock);
@@ -1907,7 +1912,7 @@ EXPORT_SYMBOL(wait_for_completion);
 	__remove_wait_queue(q, &wait);			\
 	spin_unlock_irqrestore(&q->lock, flags);
 
-void fastcall interruptible_sleep_on(wait_queue_head_t *q)
+void fastcall __sched interruptible_sleep_on(wait_queue_head_t *q)
 {
 	SLEEP_ON_VAR
 
@@ -1920,7 +1925,7 @@ void fastcall interruptible_sleep_on(wai
 
 EXPORT_SYMBOL(interruptible_sleep_on);
 
-long fastcall interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
+long fastcall __sched interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
 	SLEEP_ON_VAR
 
@@ -1935,7 +1940,7 @@ long fastcall interruptible_sleep_on_tim
 
 EXPORT_SYMBOL(interruptible_sleep_on_timeout);
 
-void fastcall sleep_on(wait_queue_head_t *q)
+void fastcall __sched sleep_on(wait_queue_head_t *q)
 {
 	SLEEP_ON_VAR
 
@@ -1948,7 +1953,7 @@ void fastcall sleep_on(wait_queue_head_t
 
 EXPORT_SYMBOL(sleep_on);
 
-long fastcall sleep_on_timeout(wait_queue_head_t *q, long timeout)
+long fastcall __sched sleep_on_timeout(wait_queue_head_t *q, long timeout)
 {
 	SLEEP_ON_VAR
 
@@ -1963,8 +1968,6 @@ long fastcall sleep_on_timeout(wait_queu
 
 EXPORT_SYMBOL(sleep_on_timeout);
 
-void scheduling_functions_end_here(void) { }
-
 void set_user_nice(task_t *p, long nice)
 {
 	unsigned long flags;
@@ -2424,7 +2427,7 @@ asmlinkage long sys_sched_yield(void)
 	return 0;
 }
 
-void __cond_resched(void)
+void __sched __cond_resched(void)
 {
 	set_current_state(TASK_RUNNING);
 	schedule();
@@ -2438,7 +2441,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)
+void __sched yield(void)
 {
 	set_current_state(TASK_RUNNING);
 	sys_sched_yield();
@@ -2453,7 +2456,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)
+void __sched io_schedule(void)
 {
 	struct runqueue *rq = this_rq();
 
@@ -2464,7 +2467,7 @@ void io_schedule(void)
 
 EXPORT_SYMBOL(io_schedule);
 
-long io_schedule_timeout(long timeout)
+long __sched io_schedule_timeout(long timeout)
 {
 	struct runqueue *rq = this_rq();
 	long ret;
@@ -3010,7 +3013,7 @@ EXPORT_SYMBOL(__might_sleep);
  *
  * Called inside preempt_disable().
  */
-void __preempt_spin_lock(spinlock_t *lock)
+void __sched __preempt_spin_lock(spinlock_t *lock)
 {
 	if (preempt_count() > 1) {
 		_raw_spin_lock(lock);
@@ -3026,7 +3029,7 @@ void __preempt_spin_lock(spinlock_t *loc
 
 EXPORT_SYMBOL(__preempt_spin_lock);
 
-void __preempt_write_lock(rwlock_t *lock)
+void __sched __preempt_write_lock(rwlock_t *lock)
 {
 	if (preempt_count() > 1) {
 		_raw_write_lock(lock);
diff -puN kernel/timer.c~wchan-use-ELF-sections kernel/timer.c
--- 25/kernel/timer.c~wchan-use-ELF-sections	2004-04-03 02:59:47.269166936 -0800
+++ 25-akpm/kernel/timer.c	2004-04-03 02:59:47.307161160 -0800
@@ -996,7 +996,7 @@ static void process_timeout(unsigned lon
  *
  * In all cases the return value is guaranteed to be non-negative.
  */
-fastcall signed long schedule_timeout(signed long timeout)
+fastcall signed long __sched schedule_timeout(signed long timeout)
 {
 	struct timer_list timer;
 	unsigned long expire;
@@ -1056,7 +1056,7 @@ asmlinkage long sys_gettid(void)
 	return current->pid;
 }
 
-static long nanosleep_restart(struct restart_block *restart)
+static long __sched nanosleep_restart(struct restart_block *restart)
 {
 	unsigned long expire = restart->arg0, now = jiffies;
 	struct timespec __user *rmtp = (struct timespec __user *) restart->arg1;
diff -puN lib/rwsem.c~wchan-use-ELF-sections lib/rwsem.c
--- 25/lib/rwsem.c~wchan-use-ELF-sections	2004-04-03 02:59:47.270166784 -0800
+++ 25-akpm/lib/rwsem.c	2004-04-03 02:59:47.308161008 -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 fastcall *rwsem_down_read_failed(struct rw_semaphore *sem)
+struct rw_semaphore fastcall __sched *rwsem_down_read_failed(struct rw_semaphore *sem)
 {
 	struct rwsem_waiter waiter;
 
@@ -178,7 +179,7 @@ struct rw_semaphore fastcall *rwsem_down
 /*
  * wait for the write lock to be granted
  */
-struct rw_semaphore fastcall *rwsem_down_write_failed(struct rw_semaphore *sem)
+struct rw_semaphore fastcall __sched *rwsem_down_write_failed(struct rw_semaphore *sem)
 {
 	struct rwsem_waiter waiter;
 

_
