aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorFranck Bui-Huu <vagabon.xyz@gmail.com>2006-08-18 10:18:09 -0400
committerRalf Baechle <ralf@linux-mips.org>2006-09-27 08:37:58 -0400
commitb5943182592ba256639a569c7d5305cf60360733 (patch)
tree3bd1df9b9c8c88f78833801094f6790ea7875717 /arch/mips
parent29b376ff10aaea69ee4d93b70d0fbb2ebfd80f4e (diff)
[MIPS] get_wchan(): remove uses of mfinfo[64]
This array was used to 'cache' some frame info about scheduler functions to speed up get_wchan(). This array was 1Ko size and was only used when CONFIG_KALLSYMS was set but declared for all configs. Rather than make the array statement conditional, this patches removes this array and its uses. Indeed the common case doesn't seem to use this array and get_wchan() is not a critical path anyways. It results in a smaller bss and a smaller/cleaner code: text data bss dec hex filename 2543808 254148 139296 2937252 2cd1a4 vmlinux-new-get-wchan 2544080 254148 143392 2941620 2ce2b4 vmlinux~old Signed-off-by: Franck Bui-Huu <vagabon.xyz@gmail.com> Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/kernel/process.c132
1 files changed, 50 insertions, 82 deletions
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c
index b160ea30de0f..2613a0dd4b82 100644
--- a/arch/mips/kernel/process.c
+++ b/arch/mips/kernel/process.c
@@ -273,13 +273,15 @@ long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
273 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL); 273 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
274} 274}
275 275
276static struct mips_frame_info { 276/*
277 void *func; 277 *
278 unsigned long func_size; 278 */
279 int frame_size; 279struct mips_frame_info {
280 int pc_offset; 280 void *func;
281} *schedule_frame, mfinfo[64]; 281 unsigned long func_size;
282static int mfinfo_num; 282 int frame_size;
283 int pc_offset;
284};
283 285
284static inline int is_ra_save_ins(union mips_instruction *ip) 286static inline int is_ra_save_ins(union mips_instruction *ip)
285{ 287{
@@ -348,45 +350,30 @@ err:
348 return -1; 350 return -1;
349} 351}
350 352
353static struct mips_frame_info schedule_mfi __read_mostly;
354
351static int __init frame_info_init(void) 355static int __init frame_info_init(void)
352{ 356{
353 int i; 357 unsigned long size = 0;
354#ifdef CONFIG_KALLSYMS 358#ifdef CONFIG_KALLSYMS
359 unsigned long ofs;
355 char *modname; 360 char *modname;
356 char namebuf[KSYM_NAME_LEN + 1]; 361 char namebuf[KSYM_NAME_LEN + 1];
357 unsigned long start, size, ofs; 362
358 extern char __sched_text_start[], __sched_text_end[]; 363 kallsyms_lookup((unsigned long)schedule, &size, &ofs, &modname, namebuf);
359 extern char __lock_text_start[], __lock_text_end[];
360
361 start = (unsigned long)__sched_text_start;
362 for (i = 0; i < ARRAY_SIZE(mfinfo); i++) {
363 if (start == (unsigned long)schedule)
364 schedule_frame = &mfinfo[i];
365 if (!kallsyms_lookup(start, &size, &ofs, &modname, namebuf))
366 break;
367 mfinfo[i].func = (void *)(start + ofs);
368 mfinfo[i].func_size = size;
369 start += size - ofs;
370 if (start >= (unsigned long)__lock_text_end)
371 break;
372 if (start == (unsigned long)__sched_text_end)
373 start = (unsigned long)__lock_text_start;
374 }
375#else
376 mfinfo[0].func = schedule;
377 schedule_frame = &mfinfo[0];
378#endif 364#endif
379 for (i = 0; i < ARRAY_SIZE(mfinfo) && mfinfo[i].func; i++) 365 schedule_mfi.func = schedule;
380 get_frame_info(mfinfo + i); 366 schedule_mfi.func_size = size;
367
368 get_frame_info(&schedule_mfi);
381 369
382 /* 370 /*
383 * Without schedule() frame info, result given by 371 * Without schedule() frame info, result given by
384 * thread_saved_pc() and get_wchan() are not reliable. 372 * thread_saved_pc() and get_wchan() are not reliable.
385 */ 373 */
386 if (schedule_frame->pc_offset < 0) 374 if (schedule_mfi.pc_offset < 0)
387 printk("Can't analyze schedule() prologue at %p\n", schedule); 375 printk("Can't analyze schedule() prologue at %p\n", schedule);
388 376
389 mfinfo_num = i;
390 return 0; 377 return 0;
391} 378}
392 379
@@ -402,58 +389,11 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
402 /* New born processes are a special case */ 389 /* New born processes are a special case */
403 if (t->reg31 == (unsigned long) ret_from_fork) 390 if (t->reg31 == (unsigned long) ret_from_fork)
404 return t->reg31; 391 return t->reg31;
405 392 if (schedule_mfi.pc_offset < 0)
406 if (!schedule_frame || schedule_frame->pc_offset < 0)
407 return 0; 393 return 0;
408 return ((unsigned long *)t->reg29)[schedule_frame->pc_offset]; 394 return ((unsigned long *)t->reg29)[schedule_mfi.pc_offset];
409} 395}
410 396
411/* get_wchan - a maintenance nightmare^W^Wpain in the ass ... */
412unsigned long get_wchan(struct task_struct *p)
413{
414 unsigned long stack_page;
415 unsigned long pc;
416#ifdef CONFIG_KALLSYMS
417 unsigned long frame;
418#endif
419
420 if (!p || p == current || p->state == TASK_RUNNING)
421 return 0;
422
423 stack_page = (unsigned long)task_stack_page(p);
424 if (!stack_page || !mfinfo_num)
425 return 0;
426
427 pc = thread_saved_pc(p);
428#ifdef CONFIG_KALLSYMS
429 if (!in_sched_functions(pc))
430 return pc;
431
432 frame = p->thread.reg29 + schedule_frame->frame_size;
433 do {
434 int i;
435
436 if (frame < stack_page || frame > stack_page + THREAD_SIZE - 32)
437 return 0;
438
439 for (i = mfinfo_num - 1; i >= 0; i--) {
440 if (pc >= (unsigned long) mfinfo[i].func)
441 break;
442 }
443 if (i < 0)
444 break;
445
446 if (mfinfo[i].pc_offset < 0)
447 break;
448 pc = ((unsigned long *)frame)[mfinfo[i].pc_offset];
449 if (!mfinfo[i].frame_size)
450 break;
451 frame += mfinfo[i].frame_size;
452 } while (in_sched_functions(pc));
453#endif
454
455 return pc;
456}
457 397
458#ifdef CONFIG_KALLSYMS 398#ifdef CONFIG_KALLSYMS
459/* used by show_backtrace() */ 399/* used by show_backtrace() */
@@ -504,3 +444,31 @@ unsigned long unwind_stack(struct task_struct *task, unsigned long *sp,
504 return __kernel_text_address(pc) ? pc : 0; 444 return __kernel_text_address(pc) ? pc : 0;
505} 445}
506#endif 446#endif
447
448/*
449 * get_wchan - a maintenance nightmare^W^Wpain in the ass ...
450 */
451unsigned long get_wchan(struct task_struct *task)
452{
453 unsigned long pc = 0;
454#ifdef CONFIG_KALLSYMS
455 unsigned long sp;
456#endif
457
458 if (!task || task == current || task->state == TASK_RUNNING)
459 goto out;
460 if (!task_stack_page(task))
461 goto out;
462
463 pc = thread_saved_pc(task);
464
465#ifdef CONFIG_KALLSYMS
466 sp = task->thread.reg29 + schedule_mfi.frame_size;
467
468 while (in_sched_functions(pc))
469 pc = unwind_stack(task, &sp, pc, 0);
470#endif
471
472out:
473 return pc;
474}