From: Rusty Russell <rusty@rustcorp.com.au>

1) Create an in_sched_functions() function in sched.c and make the
   archs use it.  (Two archs have wchan #if 0'd out: left them alone).

2) Move __sched from linux/init.h to linux/sched.h and add comment.

3) Rename __scheduling_functions_start_here/end_here to __sched_text_start/end.

Thanks to wli and Sam Ravnborg for clue donation.


---

 25-akpm/arch/alpha/kernel/process.c         |    8 +-------
 25-akpm/arch/arm/kernel/process.c           |    8 +-------
 25-akpm/arch/arm26/kernel/process.c         |    8 +-------
 25-akpm/arch/cris/arch-v10/kernel/process.c |    4 ++--
 25-akpm/arch/h8300/kernel/process.c         |    8 +-------
 25-akpm/arch/i386/kernel/kgdb_stub.c        |    4 +---
 25-akpm/arch/i386/kernel/process.c          |    9 +--------
 25-akpm/arch/ia64/kernel/process.c          |    9 +--------
 25-akpm/arch/m68k/kernel/process.c          |   11 ++---------
 25-akpm/arch/m68knommu/kernel/process.c     |   11 ++---------
 25-akpm/arch/mips/kernel/process.c          |   10 ++--------
 25-akpm/arch/ppc/kernel/process.c           |    8 +-------
 25-akpm/arch/ppc64/kernel/process.c         |    8 +-------
 25-akpm/arch/s390/kernel/process.c          |   10 +---------
 25-akpm/arch/sh/kernel/process.c            |    8 +-------
 25-akpm/arch/sparc/kernel/process.c         |    3 +--
 25-akpm/arch/sparc64/kernel/process.c       |    3 +--
 25-akpm/arch/v850/kernel/process.c          |    4 ++--
 25-akpm/arch/x86_64/kernel/kgdb_stub.c      |    5 +----
 25-akpm/arch/x86_64/kernel/process.c        |   10 +---------
 25-akpm/include/asm-generic/vmlinux.lds.h   |    4 ++--
 25-akpm/include/linux/init.h                |    2 --
 25-akpm/include/linux/sched.h               |    6 ++++--
 25-akpm/kernel/sched.c                      |   15 ++++++++-------
 24 files changed, 39 insertions(+), 137 deletions(-)

diff -puN arch/alpha/kernel/process.c~sched-in_sched_functions arch/alpha/kernel/process.c
--- 25/arch/alpha/kernel/process.c~sched-in_sched_functions	2004-04-14 22:41:51.963496312 -0700
+++ 25-akpm/arch/alpha/kernel/process.c	2004-04-14 22:41:51.999490840 -0700
@@ -510,12 +510,6 @@ thread_saved_pc(task_t *t)
 	return 0;
 }
 
-/*
- * These bracket the sleeping functions..
- */
-#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)
 {
@@ -534,7 +528,7 @@ get_wchan(struct task_struct *p)
 	 */
 
 	pc = thread_saved_pc(p);
-	if (pc >= first_sched && pc < last_sched) {
+	if (in_sched_functions(pc)) {
 		schedule_frame = ((unsigned long *)p->thread_info->pcb.ksp)[6];
 		return ((unsigned long *)schedule_frame)[12];
 	}
diff -puN arch/arm26/kernel/process.c~sched-in_sched_functions arch/arm26/kernel/process.c
--- 25/arch/arm26/kernel/process.c~sched-in_sched_functions	2004-04-14 22:41:51.965496008 -0700
+++ 25-akpm/arch/arm26/kernel/process.c	2004-04-14 22:41:52.000490688 -0700
@@ -397,12 +397,6 @@ pid_t kernel_thread(int (*fn)(void *), v
         return __ret;
 }
 
-/*
- * These bracket the sleeping functions..
- */
-#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;
@@ -417,7 +411,7 @@ 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 (!in_sched_functions(lr))
 			return lr;
 		fp = *(unsigned long *) (fp - 12);
 	} while (count ++ < 16);
diff -puN arch/arm/kernel/process.c~sched-in_sched_functions arch/arm/kernel/process.c
--- 25/arch/arm/kernel/process.c~sched-in_sched_functions	2004-04-14 22:41:51.967495704 -0700
+++ 25-akpm/arch/arm/kernel/process.c	2004-04-14 22:41:52.000490688 -0700
@@ -411,12 +411,6 @@ pid_t kernel_thread(int (*fn)(void *), v
 	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
 }
 
-/*
- * These bracket the sleeping functions..
- */
-#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;
@@ -431,7 +425,7 @@ 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 (!in_sched_functions(lr))
 			return lr;
 		fp = *(unsigned long *) (fp - 12);
 	} while (count ++ < 16);
diff -puN arch/cris/arch-v10/kernel/process.c~sched-in_sched_functions arch/cris/arch-v10/kernel/process.c
--- 25/arch/cris/arch-v10/kernel/process.c~sched-in_sched_functions	2004-04-14 22:41:51.968495552 -0700
+++ 25-akpm/arch/cris/arch-v10/kernel/process.c	2004-04-14 22:41:52.001490536 -0700
@@ -217,8 +217,8 @@ asmlinkage int sys_execve(const char *fn
  * These bracket the sleeping functions..
  */
 
-#define first_sched     ((unsigned long) scheduling_functions_start_here)
-#define last_sched      ((unsigned long) scheduling_functions_end_here)
+#define first_sched	((unsigned long)__sched_text_start)
+#define last_sched	((unsigned long)__sched_text_end)
 
 unsigned long get_wchan(struct task_struct *p)
 {
diff -puN arch/h8300/kernel/process.c~sched-in_sched_functions arch/h8300/kernel/process.c
--- 25/arch/h8300/kernel/process.c~sched-in_sched_functions	2004-04-14 22:41:51.969495400 -0700
+++ 25-akpm/arch/h8300/kernel/process.c	2004-04-14 22:41:52.001490536 -0700
@@ -261,12 +261,6 @@ out:
 	return error;
 }
 
-/*
- * These bracket the sleeping functions..
- */
-#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;
@@ -287,7 +281,7 @@ unsigned long get_wchan(struct task_stru
 		    fp >= 8184+stack_page)
 			return 0;
 		pc = ((unsigned long *)fp)[1];
-		if (pc < first_sched || pc >= last_sched)
+		if (!in_sched_functions(pc))
 			return pc;
 		fp = *(unsigned long *) fp;
 	} while (count++ < 16);
diff -puN arch/i386/kernel/kgdb_stub.c~sched-in_sched_functions arch/i386/kernel/kgdb_stub.c
--- 25/arch/i386/kernel/kgdb_stub.c~sched-in_sched_functions	2004-04-14 22:41:51.971495096 -0700
+++ 25-akpm/arch/i386/kernel/kgdb_stub.c	2004-04-14 22:41:52.003490232 -0700
@@ -654,8 +654,6 @@ gdb_regs_to_regs(int *gdb_regs, struct p
 #endif
 
 }				/* gdb_regs_to_regs */
-#define first_sched	scheduling_functions_start_here
-#define last_sched	scheduling_functions_end_here
 
 int thread_list = 0;
 
@@ -716,7 +714,7 @@ get_gdb_regs(struct task_struct *p, stru
 		gdb_regs[_PC] = *(unsigned long *) (gdb_regs[_EBP] + 4);
 		gdb_regs[_ESP] = gdb_regs[_EBP] + 8;
 		gdb_regs[_EBP] = *(unsigned long *) gdb_regs[_EBP];
-		if (gdb_regs[_PC] < first_sched || gdb_regs[_PC] >= last_sched)
+		if (!in_sched_functions(gdb_regs[_PC]))
 			return;
 	} while (count++ < 16);
 	return;
diff -puN arch/i386/kernel/process.c~sched-in_sched_functions arch/i386/kernel/process.c
--- 25/arch/i386/kernel/process.c~sched-in_sched_functions	2004-04-14 22:41:51.972494944 -0700
+++ 25-akpm/arch/i386/kernel/process.c	2004-04-14 22:41:52.004490080 -0700
@@ -629,11 +629,6 @@ out:
 	return error;
 }
 
-/*
- * These bracket the sleeping functions..
- */
-#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))
 #define top_ebp                (THREAD_SIZE - 2*sizeof(unsigned long))
 
@@ -654,14 +649,12 @@ unsigned long get_wchan(struct task_stru
 		if (ebp < stack_page || ebp > top_ebp+stack_page)
 			return 0;
 		eip = *(unsigned long *) (ebp+4);
-		if (eip < first_sched || eip >= last_sched)
+		if (!in_sched_functions(eip))
 			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 -puN arch/ia64/kernel/process.c~sched-in_sched_functions arch/ia64/kernel/process.c
--- 25/arch/ia64/kernel/process.c~sched-in_sched_functions	2004-04-14 22:41:51.974494640 -0700
+++ 25-akpm/arch/ia64/kernel/process.c	2004-04-14 22:41:52.005489928 -0700
@@ -657,11 +657,6 @@ get_wchan (struct task_struct *p)
 	struct unw_frame_info info;
 	unsigned long ip;
 	int count = 0;
-	/*
-	 * These bracket the sleeping functions..
-	 */
-#	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
@@ -676,12 +671,10 @@ 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 (!in_sched_functions(ip))
 			return ip;
 	} while (count++ < 16);
 	return 0;
-#	undef first_sched
-#	undef last_sched
 }
 
 void
diff -puN arch/m68k/kernel/process.c~sched-in_sched_functions arch/m68k/kernel/process.c
--- 25/arch/m68k/kernel/process.c~sched-in_sched_functions	2004-04-14 22:41:51.975494488 -0700
+++ 25-akpm/arch/m68k/kernel/process.c	2004-04-14 22:41:52.005489928 -0700
@@ -67,8 +67,7 @@ unsigned long thread_saved_pc(struct tas
 {
 	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 (in_sched_functions(sw->retpc))
 		return ((unsigned long *)sw->a6)[1];
 	else
 		return sw->retpc;
@@ -382,12 +381,6 @@ out:
 	return error;
 }
 
-/*
- * These bracket the sleeping functions..
- */
-#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;
@@ -403,7 +396,7 @@ unsigned long get_wchan(struct task_stru
 		    fp >= 8184+stack_page)
 			return 0;
 		pc = ((unsigned long *)fp)[1];
-		if (pc < first_sched || pc >= last_sched)
+		if (!in_sched_functions(pc))
 			return pc;
 		fp = *(unsigned long *) fp;
 	} while (count++ < 16);
diff -puN arch/m68knommu/kernel/process.c~sched-in_sched_functions arch/m68knommu/kernel/process.c
--- 25/arch/m68knommu/kernel/process.c~sched-in_sched_functions	2004-04-14 22:41:51.976494336 -0700
+++ 25-akpm/arch/m68knommu/kernel/process.c	2004-04-14 22:41:52.006489776 -0700
@@ -404,12 +404,6 @@ out:
 	return error;
 }
 
-/*
- * These bracket the sleeping functions..
- */
-#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;
@@ -425,7 +419,7 @@ unsigned long get_wchan(struct task_stru
 		    fp >= 8184+stack_page)
 			return 0;
 		pc = ((unsigned long *)fp)[1];
-		if (pc < first_sched || pc >= last_sched)
+		if (!in_sched_functions(pc))
 			return pc;
 		fp = *(unsigned long *) fp;
 	} while (count++ < 16);
@@ -440,8 +434,7 @@ unsigned long thread_saved_pc(struct tas
 	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 (in_sched_functions(sw->retpc))
 		return ((unsigned long *)sw->a6)[1];
 	else
 		return sw->retpc;
diff -puN arch/mips/kernel/process.c~sched-in_sched_functions arch/mips/kernel/process.c
--- 25/arch/mips/kernel/process.c~sched-in_sched_functions	2004-04-14 22:41:51.977494184 -0700
+++ 25-akpm/arch/mips/kernel/process.c	2004-04-14 22:41:52.007489624 -0700
@@ -280,12 +280,6 @@ unsigned long thread_saved_pc(struct tas
 	return ((unsigned long *)t->reg29)[schedule_frame.pc_offset];
 }
 
-/*
- * These bracket the sleeping functions..
- */
-#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)
 {
@@ -297,7 +291,7 @@ 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 (!in_sched_functions(pc))
 		goto out;
 
 	if (pc >= (unsigned long) sleep_on_timeout)
@@ -331,7 +325,7 @@ schedule_timeout_caller:
 	 */
 	pc    = ((unsigned long *)frame)[schedule_timeout_frame.pc_offset];
 
-	if (pc >= first_sched && pc < last_sched) {
+	if (in_sched_functions(pc)) {
 		/* 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 -puN arch/ppc64/kernel/process.c~sched-in_sched_functions arch/ppc64/kernel/process.c
--- 25/arch/ppc64/kernel/process.c~sched-in_sched_functions	2004-04-14 22:41:51.979493880 -0700
+++ 25-akpm/arch/ppc64/kernel/process.c	2004-04-14 22:41:52.007489624 -0700
@@ -472,12 +472,6 @@ static inline int validate_sp(unsigned l
 	return 1;
 }
 
-/*
- * These bracket the sleeping functions..
- */
-#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;
@@ -496,7 +490,7 @@ unsigned long get_wchan(struct task_stru
 			return 0;
 		if (count > 0) {
 			ip = *(unsigned long *)(sp + 16);
-			if (ip < first_sched || ip >= last_sched)
+			if (!in_sched_functions(ip))
 				return ip;
 		}
 	} while (count++ < 16);
diff -puN arch/ppc/kernel/process.c~sched-in_sched_functions arch/ppc/kernel/process.c
--- 25/arch/ppc/kernel/process.c~sched-in_sched_functions	2004-04-14 22:41:51.980493728 -0700
+++ 25-akpm/arch/ppc/kernel/process.c	2004-04-14 22:41:52.008489472 -0700
@@ -658,12 +658,6 @@ void __init ll_puts(const char *s)
 }
 #endif
 
-/*
- * These bracket the sleeping functions..
- */
-#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;
@@ -678,7 +672,7 @@ 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 (!in_sched_functions(ip))
 				return ip;
 		}
 	} while (count++ < 16);
diff -puN arch/s390/kernel/process.c~sched-in_sched_functions arch/s390/kernel/process.c
--- 25/arch/s390/kernel/process.c~sched-in_sched_functions	2004-04-14 22:41:51.981493576 -0700
+++ 25-akpm/arch/s390/kernel/process.c	2004-04-14 22:41:52.009489320 -0700
@@ -381,12 +381,6 @@ void dump_thread(struct pt_regs * regs, 
 	dump->regs.per_info = current->thread.per_info;
 }
 
-/*
- * These bracket the sleeping functions..
- */
-#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;
@@ -409,12 +403,10 @@ unsigned long get_wchan(struct task_stru
 #else
 		r14 = *(unsigned long *) (bc+112);
 #endif
-		if (r14 < first_sched || r14 >= last_sched)
+		if (!in_sched_functions(r14))
 			return r14;
 		bc = (*(unsigned long *) bc) & PSW_ADDR_INSN;
 	} while (count++ < 16);
 	return 0;
 }
-#undef last_sched
-#undef first_sched
 
diff -puN arch/sh/kernel/process.c~sched-in_sched_functions arch/sh/kernel/process.c
--- 25/arch/sh/kernel/process.c~sched-in_sched_functions	2004-04-14 22:41:51.983493272 -0700
+++ 25-akpm/arch/sh/kernel/process.c	2004-04-14 22:41:52.009489320 -0700
@@ -461,12 +461,6 @@ out:
 	return error;
 }
 
-/*
- * These bracket the sleeping functions..
- */
-#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;
@@ -479,7 +473,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 >= first_sched && pc < last_sched) {
+	if (in_sched_functions(pc)) {
 		schedule_frame = ((unsigned long *)(long)p->thread.sp)[1];
 		return (unsigned long)((unsigned long *)schedule_frame)[1];
 	}
diff -puN arch/sparc64/kernel/process.c~sched-in_sched_functions arch/sparc64/kernel/process.c
--- 25/arch/sparc64/kernel/process.c~sched-in_sched_functions	2004-04-14 22:41:51.984493120 -0700
+++ 25-akpm/arch/sparc64/kernel/process.c	2004-04-14 22:41:52.010489168 -0700
@@ -847,8 +847,7 @@ 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 (!in_sched_functions(pc)) {
 			ret = pc;
 			goto out;
 		}
diff -puN arch/sparc/kernel/process.c~sched-in_sched_functions arch/sparc/kernel/process.c
--- 25/arch/sparc/kernel/process.c~sched-in_sched_functions	2004-04-14 22:41:51.986492816 -0700
+++ 25-akpm/arch/sparc/kernel/process.c	2004-04-14 22:41:52.011489016 -0700
@@ -715,8 +715,7 @@ 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 (!in_sched_functions(pc)) {
 			ret = pc;
 			goto out;
 		}
diff -puN arch/v850/kernel/process.c~sched-in_sched_functions arch/v850/kernel/process.c
--- 25/arch/v850/kernel/process.c~sched-in_sched_functions	2004-04-14 22:41:51.987492664 -0700
+++ 25-akpm/arch/v850/kernel/process.c	2004-04-14 22:41:52.011489016 -0700
@@ -203,8 +203,8 @@ int sys_execve (char *name, char **argv,
 /*
  * These bracket the sleeping functions..
  */
-#define first_sched	((unsigned long) scheduling_functions_start_here)
-#define last_sched	((unsigned long) scheduling_functions_end_here)
+#define first_sched	((unsigned long)__sched_text_start)
+#define last_sched	((unsigned long)__sched_text_end)
 
 unsigned long get_wchan (struct task_struct *p)
 {
diff -puN arch/x86_64/kernel/kgdb_stub.c~sched-in_sched_functions arch/x86_64/kernel/kgdb_stub.c
--- 25/arch/x86_64/kernel/kgdb_stub.c~sched-in_sched_functions	2004-04-14 22:41:51.988492512 -0700
+++ 25-akpm/arch/x86_64/kernel/kgdb_stub.c	2004-04-14 22:41:52.013488712 -0700
@@ -667,9 +667,6 @@ gdb_regs_to_regs(unsigned long *gdb_regs
 #endif
 }				/* gdb_regs_to_regs */
 
-#define first_sched	scheduling_functions_start_here
-#define last_sched	scheduling_functions_end_here
-
 int thread_list = 0;
 extern void thread_return(void);
 
@@ -730,7 +727,7 @@ get_gdb_regs(struct task_struct *p, stru
 		rsp = (unsigned long *)rbp;
 		pc = rsp[1];
 
-		if (pc < first_sched || pc >= last_sched)
+		if (!in_sched_functions(pc))
 			break;
 		gdb_regs[_PC] = (unsigned long)pc;
 		gdb_regs[_RSP] = (unsigned long)rsp;
diff -puN arch/x86_64/kernel/process.c~sched-in_sched_functions arch/x86_64/kernel/process.c
--- 25/arch/x86_64/kernel/process.c~sched-in_sched_functions	2004-04-14 22:41:51.990492208 -0700
+++ 25-akpm/arch/x86_64/kernel/process.c	2004-04-14 22:41:52.014488560 -0700
@@ -573,12 +573,6 @@ asmlinkage long sys_vfork(struct pt_regs
 		    NULL, NULL);
 }
 
-/*
- * These bracket the sleeping functions..
- */
-#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 stack;
@@ -595,14 +589,12 @@ unsigned long get_wchan(struct task_stru
 		if (fp < (unsigned long)stack || fp > (unsigned long)stack+THREAD_SIZE)
 			return 0; 
 		rip = *(u64 *)(fp+8); 
-		if (rip < first_sched || rip >= last_sched)
+		if (!in_sched_functions(rip))
 			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 -puN include/asm-generic/vmlinux.lds.h~sched-in_sched_functions include/asm-generic/vmlinux.lds.h
--- 25/include/asm-generic/vmlinux.lds.h~sched-in_sched_functions	2004-04-14 22:41:51.991492056 -0700
+++ 25-akpm/include/asm-generic/vmlinux.lds.h	2004-04-14 22:41:52.014488560 -0700
@@ -53,6 +53,6 @@
 	}
 
 #define SCHED_TEXT							\
-		__scheduling_functions_start_here = .;			\
+		__sched_text_start = .;					\
 		*(.sched.text)						\
-		__scheduling_functions_end_here = .;
+		__sched_text_end = .;
diff -puN include/linux/init.h~sched-in_sched_functions include/linux/init.h
--- 25/include/linux/init.h~sched-in_sched_functions	2004-04-14 22:41:51.992491904 -0700
+++ 25-akpm/include/linux/init.h	2004-04-14 22:41:52.015488408 -0700
@@ -47,8 +47,6 @@
 #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~sched-in_sched_functions include/linux/sched.h
--- 25/include/linux/sched.h~sched-in_sched_functions	2004-04-14 22:41:51.994491600 -0700
+++ 25-akpm/include/linux/sched.h	2004-04-14 22:41:52.016488256 -0700
@@ -180,9 +180,11 @@ 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;
 
+/* Attach to any functions which should be ignored in wchan output. */
+#define __sched		__attribute__((__section__(".sched.text")))
+/* Is this address in the __sched functions? */
+extern int in_sched_functions(unsigned long addr);
 
 #define	MAX_SCHEDULE_TIMEOUT	LONG_MAX
 extern signed long FASTCALL(schedule_timeout(signed long timeout));
diff -puN kernel/sched.c~sched-in_sched_functions kernel/sched.c
--- 25/kernel/sched.c~sched-in_sched_functions	2004-04-14 22:41:51.995491448 -0700
+++ 25-akpm/kernel/sched.c	2004-04-14 22:41:52.018487952 -0700
@@ -271,13 +271,6 @@ 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:
  */
@@ -3942,6 +3935,14 @@ void __init sched_init_smp(void)
 }
 #endif /* CONFIG_SMP */
 
+int in_sched_functions(unsigned long addr)
+{
+	/* Linker adds these: start and end of __sched functions */
+	extern char __sched_text_start[], __sched_text_end[];
+	return addr >= (unsigned long)__sched_text_start
+		&& addr < (unsigned long)__sched_text_end;
+}
+
 void __init sched_init(void)
 {
 	runqueue_t *rq;

_