You've already forked linux-rockchip
mirror of
https://github.com/armbian/linux-rockchip.git
synced 2026-01-06 11:08:10 -08:00
sched: Add wrapper for get_wchan() to keep task blocked
Having a stable wchan means the process must be blocked and for it to stay that way while performing stack unwinding. Suggested-by: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Kees Cook <keescook@chromium.org> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Geert Uytterhoeven <geert@linux-m68k.org> Acked-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk> [arm] Tested-by: Mark Rutland <mark.rutland@arm.com> [arm64] Link: https://lkml.kernel.org/r/20211008111626.332092234@infradead.org
This commit is contained in:
committed by
Peter Zijlstra
parent
bc9bbb8173
commit
42a20f86dc
@@ -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)
|
||||
|
||||
|
||||
@@ -376,12 +376,11 @@ 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
|
||||
|
||||
@@ -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__ */
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -276,13 +276,11 @@ 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);
|
||||
|
||||
@@ -257,7 +257,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 update_sctlr_el1(u64 sctlr);
|
||||
|
||||
|
||||
@@ -528,13 +528,11 @@ __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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -111,12 +111,11 @@ 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;
|
||||
|
||||
if (likely(task && task != current && !task_is_running(task)))
|
||||
walk_stackframe(task, NULL, save_wchan, &pc);
|
||||
walk_stackframe(task, NULL, save_wchan, &pc);
|
||||
return pc;
|
||||
}
|
||||
|
||||
|
||||
@@ -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) \
|
||||
({ \
|
||||
|
||||
@@ -128,15 +128,12 @@ 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 {
|
||||
|
||||
@@ -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. */
|
||||
|
||||
|
||||
@@ -130,13 +130,11 @@ 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;
|
||||
|
||||
@@ -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) \
|
||||
|
||||
@@ -523,15 +523,12 @@ 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
|
||||
|
||||
@@ -150,7 +150,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) \
|
||||
({ \
|
||||
|
||||
@@ -263,13 +263,11 @@ 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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user