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 <matt.redfearn@mips.com>
---
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
|