aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@suse.de>2006-09-26 04:52:28 -0400
committerAndi Kleen <andi@basil.nowhere.org>2006-09-26 04:52:28 -0400
commit0cb91a2293648507886563ccb91979cfc94d6a4b (patch)
treef2a994f8b874e3c81c5519d445a0c5fa5522e4b5
parentc16b63e09d9d03158e0a92e961234e94c4862620 (diff)
[PATCH] i386: Account spinlocks to the caller during profiling for !FP kernels
This ports the algorithm from x86-64 (with improvements) to i386. Previously this only worked for frame pointer enabled kernels. But spinlocks have a very simple stack frame that can be manually analyzed. Do this. Signed-off-by: Andi Kleen <ak@suse.de>
-rw-r--r--arch/i386/kernel/time.c23
-rw-r--r--include/asm-i386/ptrace.h4
-rw-r--r--kernel/spinlock.c5
3 files changed, 24 insertions, 8 deletions
diff --git a/arch/i386/kernel/time.c b/arch/i386/kernel/time.c
index edd00f6cee37..5af802ef00b2 100644
--- a/arch/i386/kernel/time.c
+++ b/arch/i386/kernel/time.c
@@ -130,18 +130,33 @@ static int set_rtc_mmss(unsigned long nowtime)
130 130
131int timer_ack; 131int timer_ack;
132 132
133#if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER)
134unsigned long profile_pc(struct pt_regs *regs) 133unsigned long profile_pc(struct pt_regs *regs)
135{ 134{
136 unsigned long pc = instruction_pointer(regs); 135 unsigned long pc = instruction_pointer(regs);
137 136
138 if (!user_mode_vm(regs) && in_lock_functions(pc)) 137#ifdef CONFIG_SMP
138 if (!user_mode_vm(regs) && in_lock_functions(pc)) {
139#ifdef CONFIG_FRAME_POINTER
139 return *(unsigned long *)(regs->ebp + 4); 140 return *(unsigned long *)(regs->ebp + 4);
140 141#else
142 unsigned long *sp;
143 if ((regs->xcs & 3) == 0)
144 sp = (unsigned long *)&regs->esp;
145 else
146 sp = (unsigned long *)regs->esp;
147 /* Return address is either directly at stack pointer
148 or above a saved eflags. Eflags has bits 22-31 zero,
149 kernel addresses don't. */
150 if (sp[0] >> 22)
151 return sp[0];
152 if (sp[1] >> 22)
153 return sp[1];
154#endif
155 }
156#endif
141 return pc; 157 return pc;
142} 158}
143EXPORT_SYMBOL(profile_pc); 159EXPORT_SYMBOL(profile_pc);
144#endif
145 160
146/* 161/*
147 * This is the same as the above, except we _also_ save the current 162 * This is the same as the above, except we _also_ save the current
diff --git a/include/asm-i386/ptrace.h b/include/asm-i386/ptrace.h
index f324c53b6f9a..30a442ec2059 100644
--- a/include/asm-i386/ptrace.h
+++ b/include/asm-i386/ptrace.h
@@ -80,11 +80,7 @@ static inline int user_mode_vm(struct pt_regs *regs)
80 return ((regs->xcs & 3) | (regs->eflags & VM_MASK)) != 0; 80 return ((regs->xcs & 3) | (regs->eflags & VM_MASK)) != 0;
81} 81}
82#define instruction_pointer(regs) ((regs)->eip) 82#define instruction_pointer(regs) ((regs)->eip)
83#if defined(CONFIG_SMP) && defined(CONFIG_FRAME_POINTER)
84extern unsigned long profile_pc(struct pt_regs *regs); 83extern unsigned long profile_pc(struct pt_regs *regs);
85#else
86#define profile_pc(regs) instruction_pointer(regs)
87#endif
88#endif /* __KERNEL__ */ 84#endif /* __KERNEL__ */
89 85
90#endif 86#endif
diff --git a/kernel/spinlock.c b/kernel/spinlock.c
index fb524b009eef..9644a41e0bef 100644
--- a/kernel/spinlock.c
+++ b/kernel/spinlock.c
@@ -7,6 +7,11 @@
7 * 7 *
8 * This file contains the spinlock/rwlock implementations for the 8 * This file contains the spinlock/rwlock implementations for the
9 * SMP and the DEBUG_SPINLOCK cases. (UP-nondebug inlines them) 9 * SMP and the DEBUG_SPINLOCK cases. (UP-nondebug inlines them)
10 *
11 * Note that some architectures have special knowledge about the
12 * stack frames of these functions in their profile_pc. If you
13 * change anything significant here that could change the stack
14 * frame contact the architecture maintainers.
10 */ 15 */
11 16
12#include <linux/linkage.h> 17#include <linux/linkage.h>