Hello. On 09-05-2013 18:49, Tony Wu wrote:
schedule_mfi is supposed to be extracted from schedule(), and is used in thread_saved_pc and get_wchan.
But, after optimization, schedule() is reduced to a sibling call to __schedule(), and no real frame info can be extracted.
One solution is to compile schedule() with -fno-omit-frame-pointer and -fno-optimize-sibling-calls, but that will incur performance degradation.
This patch follows the sibling call and extracts the schedule_mfi from the __schedule with and without KALLSYMS enabled.
Signed-off-by: Tony Wu <tung7970@xxxxxxxxx> --- arch/mips/kernel/process.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index a794eb5..289ea69 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -314,15 +314,39 @@ err: static struct mips_frame_info schedule_mfi __read_mostly; +static unsigned long get___schedule_addr(void) +{ +#ifdef CONFIG_KALLSYMS + return kallsyms_lookup_name("__schedule"); +#else + union mips_instruction *ip = (void *)schedule; + int max_insns = 8; + int i; + + for (i = 0; i < max_insns; i++, ip++) { + if (ip->j_format.opcode == j_op) + return J_TARGET(ip, ip->j_format.target); + } + return 0; +#endif +} +
#ifdef's inside function body are frowned upon. Better code it as: #ifdef CONFIG_KALLSYMS static unsigned long get___schedule_addr(void) { return kallsyms_lookup_name("__schedule"); } #else static unsigned long get___schedule_addr(void) { union mips_instruction *ip = (void *)schedule; [...] return 0; } #endif WBR, Sergei