Thread (17 messages) 17 messages, 1 author, 2017-12-12
DORMANTno replies

[RFC PATCH 15/16] MIPS: prep stack walkers for THREAD_INFO_IN_TASK

From: Matt Redfearn <hidden>
Date: 2017-12-12 10:05:24
Subsystem: mips, the rest · Maintainers: Thomas Bogendoerfer, Linus Torvalds

When CONFIG_THREAD_INFO_IN_TASK is selected, task stacks may be freed
before a task is destroyed. To account for this, the stacks are
refcounted, and when manipulating the stack of another task, it is
necessary to get/put the stack to ensure it isn't freed and/or re-used
while we do so.

This patch reworks the MIPS stack walking code to account for this.
When CONFIG_THREAD_INFO_IN_TASK is not selected these perform no
refcounting, and this should only be a structural change that does not
affect behaviour.

Signed-off-by: Matt Redfearn <redacted>
---

 arch/mips/kernel/process.c    | 3 ++-
 arch/mips/kernel/stacktrace.c | 5 +++++
 2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index 45d0b6b037ee..24b4e8c02508 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -627,7 +627,7 @@ unsigned long get_wchan(struct task_struct *task)
 
 	if (!task || task == current || task->state == TASK_RUNNING)
 		goto out;
-	if (!task_stack_page(task))
+	if (!try_get_task_stack(task))
 		goto out;
 
 	pc = thread_saved_pc(task);
@@ -639,6 +639,7 @@ unsigned long get_wchan(struct task_struct *task)
 		pc = unwind_stack(task, &sp, pc, &ra);
 #endif
 
+	put_task_stack(task);
 out:
 	return pc;
 }
diff --git a/arch/mips/kernel/stacktrace.c b/arch/mips/kernel/stacktrace.c
index 7c7c902249f2..babf2dd165a0 100644
--- a/arch/mips/kernel/stacktrace.c
+++ b/arch/mips/kernel/stacktrace.c
@@ -81,6 +81,9 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
 
 	WARN_ON(trace->nr_entries || !trace->max_entries);
 
+	if (!try_get_task_stack(tsk))
+		return;
+
 	if (tsk != current) {
 		regs->regs[29] = tsk->thread.reg29;
 		regs->regs[31] = 0;
@@ -88,5 +91,7 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
 	} else
 		prepare_frametrace(regs);
 	save_context_stack(trace, tsk, regs, tsk == current);
+
+	put_task_stack(tsk);
 }
 EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
-- 
2.7.4
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help