]> git.hungrycats.org Git - linux/commitdiff
Revert "sched: Add wrapper for get_wchan() to keep task blocked"
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 18 Nov 2021 12:15:48 +0000 (13:15 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 18 Nov 2021 13:01:34 +0000 (14:01 +0100)
This reverts commit e9ede14c116f1a6246eee89d320d60a90a86b5d5 which is
commit 42a20f86dc19f9282d974df0ba4d226c865ab9dd upstream.

It has been reported to be causing problems, and is being reworked
upstream and has been dropped from the current 5.15.y stable queue until
it gets resolved.

Reported-by: Chris Rankin <rankincj@gmail.com>
Reported-by: Thorsten Leemhuis <linux@leemhuis.info>
Link: https://lore.kernel.org/r/ed000478-2a60-0066-c337-a04bffc112b1@leemhuis.info
Cc: Stephen Rothwell <sfr@canb.auug.org.au>
Cc: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Kees Cook <keescook@chromium.org>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Sasha Levin <sashal@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
50 files changed:
arch/alpha/include/asm/processor.h
arch/alpha/kernel/process.c
arch/arc/include/asm/processor.h
arch/arc/kernel/stacktrace.c
arch/arm/include/asm/processor.h
arch/arm/kernel/process.c
arch/arm64/include/asm/processor.h
arch/arm64/kernel/process.c
arch/csky/include/asm/processor.h
arch/csky/kernel/stacktrace.c
arch/h8300/include/asm/processor.h
arch/h8300/kernel/process.c
arch/hexagon/include/asm/processor.h
arch/hexagon/kernel/process.c
arch/ia64/include/asm/processor.h
arch/ia64/kernel/process.c
arch/m68k/include/asm/processor.h
arch/m68k/kernel/process.c
arch/microblaze/include/asm/processor.h
arch/microblaze/kernel/process.c
arch/mips/include/asm/processor.h
arch/mips/kernel/process.c
arch/nds32/include/asm/processor.h
arch/nds32/kernel/process.c
arch/nios2/include/asm/processor.h
arch/nios2/kernel/process.c
arch/openrisc/include/asm/processor.h
arch/openrisc/kernel/process.c
arch/parisc/include/asm/processor.h
arch/parisc/kernel/process.c
arch/powerpc/include/asm/processor.h
arch/powerpc/kernel/process.c
arch/riscv/include/asm/processor.h
arch/riscv/kernel/stacktrace.c
arch/s390/include/asm/processor.h
arch/s390/kernel/process.c
arch/sh/include/asm/processor_32.h
arch/sh/kernel/process_32.c
arch/sparc/include/asm/processor_32.h
arch/sparc/include/asm/processor_64.h
arch/sparc/kernel/process_32.c
arch/sparc/kernel/process_64.c
arch/um/include/asm/processor-generic.h
arch/um/kernel/process.c
arch/x86/include/asm/processor.h
arch/x86/kernel/process.c
arch/xtensa/include/asm/processor.h
arch/xtensa/kernel/process.c
include/linux/sched.h
kernel/sched/core.c

index 090499c99c1c1e7c4716494bd140f9308dbc7db9..6100431da07a3bfaf4c822d7af7ad02cb2994854 100644 (file)
@@ -42,7 +42,7 @@ extern void start_thread(struct pt_regs *, unsigned long, unsigned long);
 struct task_struct;
 extern void release_thread(struct task_struct *);
 
-unsigned long __get_wchan(struct task_struct *p);
+unsigned long get_wchan(struct task_struct *p);
 
 #define KSTK_EIP(tsk) (task_pt_regs(tsk)->pc)
 
index 5f8527081da92fc69d12b77be04f706475c21239..a5123ea426ce58ed230d0fde4e8dfbb0c4155d84 100644 (file)
@@ -376,11 +376,12 @@ thread_saved_pc(struct task_struct *t)
 }
 
 unsigned long
-__get_wchan(struct task_struct *p)
+get_wchan(struct task_struct *p)
 {
        unsigned long schedule_frame;
        unsigned long pc;
-
+       if (!p || p == current || task_is_running(p))
+               return 0;
        /*
         * This one depends on the frame size of schedule().  Do a
         * "disass schedule" in gdb to find the frame size.  Also, the
index 04a5268e592b9baad20b018f172be28048a2b7ab..e4031ecd3c8c1f1141ffd8eead2b7a615051fb02 100644 (file)
@@ -70,7 +70,7 @@ struct task_struct;
 extern void start_thread(struct pt_regs * regs, unsigned long pc,
                         unsigned long usp);
 
-extern unsigned int __get_wchan(struct task_struct *p);
+extern unsigned int get_wchan(struct task_struct *p);
 
 #endif /* !__ASSEMBLY__ */
 
index db96cc87838918119c1326f922f19859591db768..1b9576d21e244feda21d000e793fa8e9a800af11 100644 (file)
@@ -15,7 +15,7 @@
  *      = specifics of data structs where trace is saved(CONFIG_STACKTRACE etc)
  *
  *  vineetg: March 2009
- *  -Implemented correct versions of thread_saved_pc() and __get_wchan()
+ *  -Implemented correct versions of thread_saved_pc() and get_wchan()
  *
  *  rajeshwarr: 2008
  *  -Initial implementation
@@ -248,7 +248,7 @@ void show_stack(struct task_struct *tsk, unsigned long *sp, const char *loglvl)
  * Of course just returning schedule( ) would be pointless so unwind until
  * the function is not in schedular code
  */
-unsigned int __get_wchan(struct task_struct *tsk)
+unsigned int get_wchan(struct task_struct *tsk)
 {
        return arc_unwind_core(tsk, NULL, __get_first_nonsched, NULL);
 }
index 6af68edfa53abc7a72789f23eb7f90efb8a6b0b5..9e6b9728630773f445a094e7f9a837d2127a5ce1 100644 (file)
@@ -84,7 +84,7 @@ struct task_struct;
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
 
-unsigned long __get_wchan(struct task_struct *p);
+unsigned long get_wchan(struct task_struct *p);
 
 #define task_pt_regs(p) \
        ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
index 261be96fa0c30d70092f1e6934d06d1bfb489e07..fc9e8b37eaa8405144da5c7c553d4613215ab801 100644 (file)
@@ -283,11 +283,13 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
        return 0;
 }
 
-unsigned long __get_wchan(struct task_struct *p)
+unsigned long get_wchan(struct task_struct *p)
 {
        struct stackframe frame;
        unsigned long stack_page;
        int count = 0;
+       if (!p || p == current || task_is_running(p))
+               return 0;
 
        frame.fp = thread_saved_fp(p);
        frame.sp = thread_saved_sp(p);
index 922355eb7eeface46e54ddb2171ef43e1b4c1519..b6517fd03d7b6bb3bfcb6aeacbe1e6386e4eda99 100644 (file)
@@ -251,7 +251,7 @@ struct task_struct;
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
 
-unsigned long __get_wchan(struct task_struct *p);
+unsigned long get_wchan(struct task_struct *p);
 
 void set_task_sctlr_el1(u64 sctlr);
 
index 46995c972ff5fddc036c9a1e8df2b6ef08f4c13b..c858b857c1ecf04273a88134a48fba6a900305b9 100644 (file)
@@ -544,11 +544,13 @@ __notrace_funcgraph struct task_struct *__switch_to(struct task_struct *prev,
        return last;
 }
 
-unsigned long __get_wchan(struct task_struct *p)
+unsigned long get_wchan(struct task_struct *p)
 {
        struct stackframe frame;
        unsigned long stack_page, ret = 0;
        int count = 0;
+       if (!p || p == current || task_is_running(p))
+               return 0;
 
        stack_page = (unsigned long)try_get_task_stack(p);
        if (!stack_page)
index 817dd60ff152dca9c0abd7a6cce2baa76d35415f..9e933021fe8e08335ebfb26dd4a902e2588c2e78 100644 (file)
@@ -81,7 +81,7 @@ static inline void release_thread(struct task_struct *dead_task)
 
 extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
 
-unsigned long __get_wchan(struct task_struct *p);
+unsigned long get_wchan(struct task_struct *p);
 
 #define KSTK_EIP(tsk)          (task_pt_regs(tsk)->pc)
 #define KSTK_ESP(tsk)          (task_pt_regs(tsk)->usp)
index 9f78f5d2151172460d3effa09358b9a814a903df..1b280ef0800452bc8cf4e2e7ddeab29847cd3ae8 100644 (file)
@@ -111,11 +111,12 @@ static bool save_wchan(unsigned long pc, void *arg)
        return false;
 }
 
-unsigned long __get_wchan(struct task_struct *task)
+unsigned long get_wchan(struct task_struct *task)
 {
        unsigned long pc = 0;
 
-       walk_stackframe(task, NULL, save_wchan, &pc);
+       if (likely(task && task != current && !task_is_running(task)))
+               walk_stackframe(task, NULL, save_wchan, &pc);
        return pc;
 }
 
index 141a23eb62b747edd15ee4b27178eca2639a7e5f..a060b41b2d31ca74f79aecfb50cbcef35ebb8b39 100644 (file)
@@ -105,7 +105,7 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-unsigned long __get_wchan(struct task_struct *p);
+unsigned long get_wchan(struct task_struct *p);
 
 #define        KSTK_EIP(tsk)   \
        ({                       \
index 8833fa4f5d51640126a5e0c36a00b0164222ceae..2ac27e4248a4623468d1171b930f5764b1cea80e 100644 (file)
@@ -128,12 +128,15 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
        return 0;
 }
 
-unsigned long __get_wchan(struct task_struct *p)
+unsigned long get_wchan(struct task_struct *p)
 {
        unsigned long fp, pc;
        unsigned long stack_page;
        int count = 0;
 
+       if (!p || p == current || task_is_running(p))
+               return 0;
+
        stack_page = (unsigned long)p;
        fp = ((struct pt_regs *)p->thread.ksp)->er6;
        do {
index 615f7e49968e619626f423b10af853f2a80ddbf1..9f0cc99420bee39f8e97139da5f0c6a9844f6ba4 100644 (file)
@@ -64,7 +64,7 @@ struct thread_struct {
 extern void release_thread(struct task_struct *dead_task);
 
 /* Get wait channel for task P.  */
-extern unsigned long __get_wchan(struct task_struct *p);
+extern unsigned long get_wchan(struct task_struct *p);
 
 /*  The following stuff is pretty HEXAGON specific.  */
 
index 232dfd8956aa22bba4adb9b36292f782ceca8710..6a6835fb42425a6e69b86e9951751fb28d4d658c 100644 (file)
@@ -130,11 +130,13 @@ void flush_thread(void)
  * is an identification of the point at which the scheduler
  * was invoked by a blocked thread.
  */
-unsigned long __get_wchan(struct task_struct *p)
+unsigned long get_wchan(struct task_struct *p)
 {
        unsigned long fp, pc;
        unsigned long stack_page;
        int count = 0;
+       if (!p || p == current || task_is_running(p))
+               return 0;
 
        stack_page = (unsigned long)task_stack_page(p);
        fp = ((struct hexagon_switch_stack *)p->thread.switch_sp)->fp;
index 45365c2ef59833a5bffd3f9ee1755302ca0f37b8..2d8bcdc27d7f85251483cb85cd9eee1176087e75 100644 (file)
@@ -330,7 +330,7 @@ struct task_struct;
 #define release_thread(dead_task)
 
 /* Get wait channel for task P.  */
-extern unsigned long __get_wchan (struct task_struct *p);
+extern unsigned long get_wchan (struct task_struct *p);
 
 /* Return instruction pointer of blocked task TSK.  */
 #define KSTK_EIP(tsk)                                  \
index 834df24a88f12cd0514770f51dccd2cea04f773f..e56d63f4abf9decb151c1b6333062bf4c9657680 100644 (file)
@@ -523,12 +523,15 @@ exit_thread (struct task_struct *tsk)
 }
 
 unsigned long
-__get_wchan (struct task_struct *p)
+get_wchan (struct task_struct *p)
 {
        struct unw_frame_info info;
        unsigned long ip;
        int count = 0;
 
+       if (!p || p == current || task_is_running(p))
+               return 0;
+
        /*
         * Note: p may not be a blocked task (it could be current or
         * another process running on some other CPU.  Rather than
index bacec548cb3c617fd9e180916f440bed2df67cb6..3750819ac5a13bde46a73d0b9ae6af21dd5aa42f 100644 (file)
@@ -125,7 +125,7 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-unsigned long __get_wchan(struct task_struct *p);
+unsigned long get_wchan(struct task_struct *p);
 
 #define        KSTK_EIP(tsk)   \
     ({                 \
index d2357cba09abe58996947cba2d117a26d737da24..db49f90917112b8d76769050b5ed774e32b9550d 100644 (file)
@@ -263,11 +263,13 @@ int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
 }
 EXPORT_SYMBOL(dump_fpu);
 
-unsigned long __get_wchan(struct task_struct *p)
+unsigned long get_wchan(struct task_struct *p)
 {
        unsigned long fp, pc;
        unsigned long stack_page;
        int count = 0;
+       if (!p || p == current || task_is_running(p))
+               return 0;
 
        stack_page = (unsigned long)task_stack_page(p);
        fp = ((struct switch_stack *)p->thread.ksp)->a6;
index 7e9e92670df3340f2acd27f8563f3f6493a5de39..06c6e493590a23b2833b25b29326399ad380c121 100644 (file)
@@ -68,7 +68,7 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-unsigned long __get_wchan(struct task_struct *p);
+unsigned long get_wchan(struct task_struct *p);
 
 /* The size allocated for kernel stacks. This _must_ be a power of two! */
 # define KERNEL_STACK_SIZE     0x2000
index 5e2b91c1e8ced0f9eeb1ed04eaa34ea3639bce49..62aa237180b6724a121e2399bbd12b738d532839 100644 (file)
@@ -112,7 +112,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg,
        return 0;
 }
 
-unsigned long __get_wchan(struct task_struct *p)
+unsigned long get_wchan(struct task_struct *p)
 {
 /* TBD (used by procfs) */
        return 0;
index 252ed38ce8c5af53f8f9c11e584fbbbcff3244b9..0c3550c82b726863ad98f4f13bf23d17d7c50f20 100644 (file)
@@ -369,7 +369,7 @@ static inline void flush_thread(void)
 {
 }
 
-unsigned long __get_wchan(struct task_struct *p);
+unsigned long get_wchan(struct task_struct *p);
 
 #define __KSTK_TOS(tsk) ((unsigned long)task_stack_page(tsk) + \
                         THREAD_SIZE - 32 - sizeof(struct pt_regs))
index 637e6207e35000dd8d7354378a3114b8e5a465b2..73c8e7990a97316a5a3de70a96d0788646335086 100644 (file)
@@ -511,7 +511,7 @@ static int __init frame_info_init(void)
 
        /*
         * Without schedule() frame info, result given by
-        * thread_saved_pc() and __get_wchan() are not reliable.
+        * thread_saved_pc() and get_wchan() are not reliable.
         */
        if (schedule_mfi.pc_offset < 0)
                printk("Can't analyze schedule() prologue at %p\n", schedule);
@@ -652,9 +652,9 @@ unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
 #endif
 
 /*
- * __get_wchan - a maintenance nightmare^W^Wpain in the ass ...
+ * get_wchan - a maintenance nightmare^W^Wpain in the ass ...
  */
-unsigned long __get_wchan(struct task_struct *task)
+unsigned long get_wchan(struct task_struct *task)
 {
        unsigned long pc = 0;
 #ifdef CONFIG_KALLSYMS
@@ -662,6 +662,8 @@ unsigned long __get_wchan(struct task_struct *task)
        unsigned long ra = 0;
 #endif
 
+       if (!task || task == current || task_is_running(task))
+               goto out;
        if (!task_stack_page(task))
                goto out;
 
index e6bfc74972bb3bdfd7d9946bc039f18b11f0eaa5..b82369c7659d4dedeeec151859654bad0a789749 100644 (file)
@@ -83,7 +83,7 @@ extern struct task_struct *last_task_used_math;
 /* Prepare to copy thread state - unlazy all lazy status */
 #define prepare_to_copy(tsk)   do { } while (0)
 
-unsigned long __get_wchan(struct task_struct *p);
+unsigned long get_wchan(struct task_struct *p);
 
 #define cpu_relax()                    barrier()
 
index 49fab9e39cbffb6d9fbfda8e31bbe6901fad4389..391895b54d13cb5ace1a174104385ff4278e8c04 100644 (file)
@@ -233,12 +233,15 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t * fpu)
 
 EXPORT_SYMBOL(dump_fpu);
 
-unsigned long __get_wchan(struct task_struct *p)
+unsigned long get_wchan(struct task_struct *p)
 {
        unsigned long fp, lr;
        unsigned long stack_start, stack_end;
        int count = 0;
 
+       if (!p || p == current || task_is_running(p))
+               return 0;
+
        if (IS_ENABLED(CONFIG_FRAME_POINTER)) {
                stack_start = (unsigned long)end_of_stack(p);
                stack_end = (unsigned long)task_stack_page(p) + THREAD_SIZE;
@@ -255,3 +258,5 @@ unsigned long __get_wchan(struct task_struct *p)
        }
        return 0;
 }
+
+EXPORT_SYMBOL(get_wchan);
index b8125dfbcad2d6cbe42239aeb3b2afa77bf6a79b..94bcb86f679f5e7ee542eb10d841fddf9ffeada0 100644 (file)
@@ -69,7 +69,7 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-extern unsigned long __get_wchan(struct task_struct *p);
+extern unsigned long get_wchan(struct task_struct *p);
 
 #define task_pt_regs(p) \
        ((struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1)
index f8ea522a15880c4018588b01b6b4bcd6fa550a5f..9ff37ba2bb6032184fcf3d284b00f42f5b3b8ff5 100644 (file)
@@ -217,12 +217,15 @@ void dump(struct pt_regs *fp)
        pr_emerg("\n\n");
 }
 
-unsigned long __get_wchan(struct task_struct *p)
+unsigned long get_wchan(struct task_struct *p)
 {
        unsigned long fp, pc;
        unsigned long stack_page;
        int count = 0;
 
+       if (!p || p == current || task_is_running(p))
+               return 0;
+
        stack_page = (unsigned long)p;
        fp = ((struct switch_stack *)p->thread.ksp)->fp;        /* ;dgt2 */
        do {
index aa1699c18add85ee7ec81918ba0f4b0129b2ce1a..ad53b318488597fbabc7618f94d908616fd960fa 100644 (file)
@@ -73,7 +73,7 @@ struct thread_struct {
 
 void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp);
 void release_thread(struct task_struct *);
-unsigned long __get_wchan(struct task_struct *p);
+unsigned long get_wchan(struct task_struct *p);
 
 #define cpu_relax()     barrier()
 
index eeea6d54b198c6cf24ba8649ebe0b2fe7ba100d3..eb62429681fc806e5b48658d05488b3aa1e826c4 100644 (file)
@@ -265,7 +265,7 @@ void dump_elf_thread(elf_greg_t *dest, struct pt_regs* regs)
        dest[35] = 0;
 }
 
-unsigned long __get_wchan(struct task_struct *p)
+unsigned long get_wchan(struct task_struct *p)
 {
        /* TODO */
 
index 5e5ceb5b9631f9bd285e49fb747462040521cf44..b5fbcd2c17808b773725118ec795fbe9b70d147d 100644 (file)
@@ -277,7 +277,7 @@ struct mm_struct;
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
 
-extern unsigned long __get_wchan(struct task_struct *p);
+extern unsigned long get_wchan(struct task_struct *p);
 
 #define KSTK_EIP(tsk)  ((tsk)->thread.regs.iaoq[0])
 #define KSTK_ESP(tsk)  ((tsk)->thread.regs.gr[30])
index 05e89d4fa911ab4f004df603de609fc64f214220..184ec3c1eae440af9f102333c579db34d59c5319 100644 (file)
@@ -243,12 +243,15 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
 }
 
 unsigned long
-__get_wchan(struct task_struct *p)
+get_wchan(struct task_struct *p)
 {
        struct unwind_frame_info info;
        unsigned long ip;
        int count = 0;
 
+       if (!p || p == current || task_is_running(p))
+               return 0;
+
        /*
         * These bracket the sleeping functions..
         */
index e39bd0ff69f3a1ef2a5345886b1c2fc1d56abe71..f348e564f7dd5407737aad61e785fb023c2a51f8 100644 (file)
@@ -300,7 +300,7 @@ struct thread_struct {
 
 #define task_pt_regs(tsk)      ((tsk)->thread.regs)
 
-unsigned long __get_wchan(struct task_struct *p);
+unsigned long get_wchan(struct task_struct *p);
 
 #define KSTK_EIP(tsk)  ((tsk)->thread.regs? (tsk)->thread.regs->nip: 0)
 #define KSTK_ESP(tsk)  ((tsk)->thread.regs? (tsk)->thread.regs->gpr[1]: 0)
index 247ef0b9bfa4ed146a27fa94a68be1080cf6aad6..185beb29058011d91b389a7490cba98d0f57d04e 100644 (file)
@@ -2111,11 +2111,14 @@ int validate_sp(unsigned long sp, struct task_struct *p,
 
 EXPORT_SYMBOL(validate_sp);
 
-static unsigned long ___get_wchan(struct task_struct *p)
+static unsigned long __get_wchan(struct task_struct *p)
 {
        unsigned long ip, sp;
        int count = 0;
 
+       if (!p || p == current || task_is_running(p))
+               return 0;
+
        sp = p->thread.ksp;
        if (!validate_sp(sp, p, STACK_FRAME_OVERHEAD))
                return 0;
@@ -2134,14 +2137,14 @@ static unsigned long ___get_wchan(struct task_struct *p)
        return 0;
 }
 
-unsigned long __get_wchan(struct task_struct *p)
+unsigned long get_wchan(struct task_struct *p)
 {
        unsigned long ret;
 
        if (!try_get_task_stack(p))
                return 0;
 
-       ret = ___get_wchan(p);
+       ret = __get_wchan(p);
 
        put_task_stack(p);
 
index 086821b44def166e92805d6444c879e972804338..021ed64ee608f2c470d040f92d7403377f8cc10f 100644 (file)
@@ -58,7 +58,7 @@ static inline void release_thread(struct task_struct *dead_task)
 {
 }
 
-extern unsigned long __get_wchan(struct task_struct *p);
+extern unsigned long get_wchan(struct task_struct *p);
 
 
 static inline void wait_for_interrupt(void)
index 0fcdc0233faca3df8d1c5237f7d2f347737c33d4..315db3d0229bfbfcb14d6a765e179fd3ecdbba55 100644 (file)
@@ -128,14 +128,16 @@ static bool save_wchan(void *arg, unsigned long pc)
        return true;
 }
 
-unsigned long __get_wchan(struct task_struct *task)
+unsigned long get_wchan(struct task_struct *task)
 {
        unsigned long pc = 0;
 
-       if (!try_get_task_stack(task))
-               return 0;
-       walk_stackframe(task, NULL, save_wchan, &pc);
-       put_task_stack(task);
+       if (likely(task && task != current && !task_is_running(task))) {
+               if (!try_get_task_stack(task))
+                       return 0;
+               walk_stackframe(task, NULL, save_wchan, &pc);
+               put_task_stack(task);
+       }
        return pc;
 }
 
index f54c152bf2bf9a42ca6cbeb2c0c98394124bb0e2..879b8e3f609cd53abea5f44e211ed29e1d5b235c 100644 (file)
@@ -192,7 +192,7 @@ static inline void release_thread(struct task_struct *tsk) { }
 void guarded_storage_release(struct task_struct *tsk);
 void gs_load_bc_cb(struct pt_regs *regs);
 
-unsigned long __get_wchan(struct task_struct *p);
+unsigned long get_wchan(struct task_struct *p);
 #define task_pt_regs(tsk) ((struct pt_regs *) \
         (task_stack_page(tsk) + THREAD_SIZE) - 1)
 #define KSTK_EIP(tsk)  (task_pt_regs(tsk)->psw.addr)
index e5dd46b1bff8cbc3bd85c64799b14a07b20b4357..350e94d0cac23a4645ca5fcb7b63b46e662f55c2 100644 (file)
@@ -181,12 +181,12 @@ void execve_tail(void)
        asm volatile("sfpc %0" : : "d" (0));
 }
 
-unsigned long __get_wchan(struct task_struct *p)
+unsigned long get_wchan(struct task_struct *p)
 {
        struct unwind_state state;
        unsigned long ip = 0;
 
-       if (!task_stack_page(p))
+       if (!p || p == current || task_is_running(p) || !task_stack_page(p))
                return 0;
 
        if (!try_get_task_stack(p))
index 45240ec6b85a43de127afb13b786c1142fcdb178..aa92cc933889df791ee756400d348412cc070415 100644 (file)
@@ -180,7 +180,7 @@ static inline void show_code(struct pt_regs *regs)
 }
 #endif
 
-extern unsigned long __get_wchan(struct task_struct *p);
+extern unsigned long get_wchan(struct task_struct *p);
 
 #define KSTK_EIP(tsk)  (task_pt_regs(tsk)->pc)
 #define KSTK_ESP(tsk)  (task_pt_regs(tsk)->regs[15])
index 1c28e3cddb60dfc63fcf2e5f162d29c23b2c64a5..717de05c81f49f175f528433445f531107cc84d2 100644 (file)
@@ -182,10 +182,13 @@ __switch_to(struct task_struct *prev, struct task_struct *next)
        return prev;
 }
 
-unsigned long __get_wchan(struct task_struct *p)
+unsigned long get_wchan(struct task_struct *p)
 {
        unsigned long pc;
 
+       if (!p || p == current || task_is_running(p))
+               return 0;
+
        /*
         * The same comment as on the Alpha applies here, too ...
         */
index 647bf0ac7beb9445dbeb1730399a94038b394d22..b6242f7771e9e845ab9a24720e99f66a86c8ae51 100644 (file)
@@ -89,7 +89,7 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc,
 /* Free all resources held by a thread. */
 #define release_thread(tsk)            do { } while(0)
 
-unsigned long __get_wchan(struct task_struct *);
+unsigned long get_wchan(struct task_struct *);
 
 #define task_pt_regs(tsk) ((tsk)->thread.kregs)
 #define KSTK_EIP(tsk)  ((tsk)->thread.kregs->pc)
index ae851e8fce4c9298ed832eede6ecf8381bba6db6..5cf145f18f36b01f416f56084e213d697fae045e 100644 (file)
@@ -183,7 +183,7 @@ do { \
 /* Free all resources held by a thread. */
 #define release_thread(tsk)            do { } while (0)
 
-unsigned long __get_wchan(struct task_struct *task);
+unsigned long get_wchan(struct task_struct *task);
 
 #define task_pt_regs(tsk) (task_thread_info(tsk)->kregs)
 #define KSTK_EIP(tsk)  (task_pt_regs(tsk)->tpc)
index 29a2f396f8601b56d3cf7d3b4045b62782bfd853..93983d6d431def5441b5827425744e017cfe5c76 100644 (file)
@@ -368,7 +368,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg,
        return 0;
 }
 
-unsigned long __get_wchan(struct task_struct *task)
+unsigned long get_wchan(struct task_struct *task)
 {
        unsigned long pc, fp, bias = 0;
        unsigned long task_base = (unsigned long) task;
@@ -376,6 +376,9 @@ unsigned long __get_wchan(struct task_struct *task)
        struct reg_window32 *rw;
        int count = 0;
 
+       if (!task || task == current || task_is_running(task))
+               goto out;
+
        fp = task_thread_info(task)->ksp + bias;
        do {
                /* Bogus frame pointer? */
index fa8db86e561c7565f7ef8c0f55fa782395b945da..d33c58a58d4ffb7045eb578bc99297a213ce35ec 100644 (file)
@@ -666,7 +666,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
        return 0;
 }
 
-unsigned long __get_wchan(struct task_struct *task)
+unsigned long get_wchan(struct task_struct *task)
 {
        unsigned long pc, fp, bias = 0;
        struct thread_info *tp;
@@ -674,6 +674,9 @@ unsigned long __get_wchan(struct task_struct *task)
         unsigned long ret = 0;
        int count = 0; 
 
+       if (!task || task == current || task_is_running(task))
+               goto out;
+
        tp = task_thread_info(task);
        bias = STACK_BIAS;
        fp = task_thread_info(task)->ksp + bias;
index 579692a40a5560ffb6879a5376e909b6e4f76f27..b5cf0ed116d9eafa3e4353bb9ffdd05b522530cd 100644 (file)
@@ -106,6 +106,6 @@ extern struct cpuinfo_um boot_cpu_data;
 #define cache_line_size()      (boot_cpu_data.cache_alignment)
 
 #define KSTK_REG(tsk, reg) get_thread_reg(reg, &tsk->thread.switch_buf)
-extern unsigned long __get_wchan(struct task_struct *p);
+extern unsigned long get_wchan(struct task_struct *p);
 
 #endif
index 82107373ac7e9243ab2063b9828f5c3cddb13900..457a38db368b7d77ed4b13ccace09d0939a905f4 100644 (file)
@@ -364,11 +364,14 @@ unsigned long arch_align_stack(unsigned long sp)
 }
 #endif
 
-unsigned long __get_wchan(struct task_struct *p)
+unsigned long get_wchan(struct task_struct *p)
 {
        unsigned long stack_page, sp, ip;
        bool seen_sched = 0;
 
+       if ((p == NULL) || (p == current) || task_is_running(p))
+               return 0;
+
        stack_page = (unsigned long) task_stack_page(p);
        /* Bail if the process has no kernel stack for some reason */
        if (stack_page == 0)
index 6f9ed2e800f21751a1b5023887b011f12ba34d65..d2c11378c7832eca7aa74f26379a1fdda1403760 100644 (file)
@@ -588,7 +588,7 @@ static inline void load_sp0(unsigned long sp0)
 /* Free all resources held by a thread. */
 extern void release_thread(struct task_struct *);
 
-unsigned long __get_wchan(struct task_struct *p);
+unsigned long get_wchan(struct task_struct *p);
 
 /*
  * Generic CPUID function
index 266962547b58c96c8c09afd1d5d69038e258ec3c..cd426c3283ee157c948755657bf6e98e90e2b12e 100644 (file)
@@ -943,10 +943,13 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
  * because the task might wake up and we might look at a stack
  * changing under us.
  */
-unsigned long __get_wchan(struct task_struct *p)
+unsigned long get_wchan(struct task_struct *p)
 {
        unsigned long entry = 0;
 
+       if (p == current || task_is_running(p))
+               return 0;
+
        stack_trace_save_tsk(p, &entry, 1, 0);
        return entry;
 }
index ad15fbc572838c9f88692f2ce8fd0dc6a3961447..7f63aca6a0d340632646ccceb9f31ae63b878402 100644 (file)
@@ -215,7 +215,7 @@ struct mm_struct;
 /* Free all resources held by a thread. */
 #define release_thread(thread) do { } while(0)
 
-extern unsigned long __get_wchan(struct task_struct *p);
+extern unsigned long get_wchan(struct task_struct *p);
 
 #define KSTK_EIP(tsk)          (task_pt_regs(tsk)->pc)
 #define KSTK_ESP(tsk)          (task_pt_regs(tsk)->areg[1])
index 47f933fed87005d794c0f50343bfc81720207e8c..0601653406123f5e1006f582bdcb75040a740a50 100644 (file)
@@ -298,12 +298,15 @@ int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn,
  * These bracket the sleeping functions..
  */
 
-unsigned long __get_wchan(struct task_struct *p)
+unsigned long get_wchan(struct task_struct *p)
 {
        unsigned long sp, pc;
        unsigned long stack_page = (unsigned long) task_stack_page(p);
        int count = 0;
 
+       if (!p || p == current || task_is_running(p))
+               return 0;
+
        sp = p->thread.sp;
        pc = MAKE_PC_FROM_RA(p->thread.ra, p->thread.sp);
 
index 4ee118cf06971a21f8daaa68b26827314065b0b6..8e10c7accdbcc87976c1b9fe8067f15ea3dd3e06 100644 (file)
@@ -2030,7 +2030,6 @@ static inline void set_task_cpu(struct task_struct *p, unsigned int cpu)
 #endif /* CONFIG_SMP */
 
 extern bool sched_task_on_rq(struct task_struct *p);
-extern unsigned long get_wchan(struct task_struct *p);
 
 /*
  * In order to reduce various lock holder preemption latencies provide an
index 5ea5b6d8b2a94a2ee8d2c3844338dbc6afa641d3..9289da7f0ac4ae348f7f38950f6f1d5cc8dfd4b9 100644 (file)
@@ -1960,25 +1960,6 @@ bool sched_task_on_rq(struct task_struct *p)
        return task_on_rq_queued(p);
 }
 
-unsigned long get_wchan(struct task_struct *p)
-{
-       unsigned long ip = 0;
-       unsigned int state;
-
-       if (!p || p == current)
-               return 0;
-
-       /* Only get wchan if task is blocked and we can keep it that way. */
-       raw_spin_lock_irq(&p->pi_lock);
-       state = READ_ONCE(p->__state);
-       smp_rmb(); /* see try_to_wake_up() */
-       if (state != TASK_RUNNING && state != TASK_WAKING && !p->on_rq)
-               ip = __get_wchan(p);
-       raw_spin_unlock_irq(&p->pi_lock);
-
-       return ip;
-}
-
 static inline void enqueue_task(struct rq *rq, struct task_struct *p, int flags)
 {
        if (!(flags & ENQUEUE_NOCLOCK))