diff options
author | Tony Luck <tony.luck@intel.com> | 2009-09-25 11:42:16 -0400 |
---|---|---|
committer | Tony Luck <tony.luck@intel.com> | 2009-09-25 11:42:16 -0400 |
commit | 2c86963b093c1a0887dfc6b32c6e5ea3a80f2922 (patch) | |
tree | d1ed58dd0a644dd670e3724a575112fedd4b4250 /arch/ia64/oprofile | |
parent | 53cddfcc0e760d2b364878b6dadbd0c6d087cfae (diff) |
[IA64] implement ticket locks for Itanium
Back in January 2008 Nick Piggin implemented "ticket" spinlocks
for X86 (See commit 314cdbefd1fd0a7acf3780e9628465b77ea6a836).
IA64 implementation has a couple of differences because of the
available atomic operations ... e.g. we have no fetchadd2 instruction
that operates on a 16-bit quantity so we make ticket locks use
a 32-bit word for each of the current ticket and now-serving values.
Performance on uncontended locks is about 8% worse than the previous
implementation, but this seems a good trade for determinism in the
contended case. Performance impact on macro-level benchmarks is in
the noise.
Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/oprofile')
-rw-r--r-- | arch/ia64/oprofile/backtrace.c | 20 |
1 files changed, 1 insertions, 19 deletions
diff --git a/arch/ia64/oprofile/backtrace.c b/arch/ia64/oprofile/backtrace.c index adb01566bd57..5cdd7e4a597c 100644 --- a/arch/ia64/oprofile/backtrace.c +++ b/arch/ia64/oprofile/backtrace.c | |||
@@ -32,24 +32,6 @@ typedef struct | |||
32 | u64 *prev_pfs_loc; /* state for WAR for old spinlock ool code */ | 32 | u64 *prev_pfs_loc; /* state for WAR for old spinlock ool code */ |
33 | } ia64_backtrace_t; | 33 | } ia64_backtrace_t; |
34 | 34 | ||
35 | #if (__GNUC__ == 3 && __GNUC_MINOR__ < 3) | ||
36 | /* | ||
37 | * Returns non-zero if the PC is in the spinlock contention out-of-line code | ||
38 | * with non-standard calling sequence (on older compilers). | ||
39 | */ | ||
40 | static __inline__ int in_old_ool_spinlock_code(unsigned long pc) | ||
41 | { | ||
42 | extern const char ia64_spinlock_contention_pre3_4[] __attribute__ ((weak)); | ||
43 | extern const char ia64_spinlock_contention_pre3_4_end[] __attribute__ ((weak)); | ||
44 | unsigned long sc_start = (unsigned long)ia64_spinlock_contention_pre3_4; | ||
45 | unsigned long sc_end = (unsigned long)ia64_spinlock_contention_pre3_4_end; | ||
46 | return (sc_start && sc_end && pc >= sc_start && pc < sc_end); | ||
47 | } | ||
48 | #else | ||
49 | /* Newer spinlock code does a proper br.call and works fine with the unwinder */ | ||
50 | #define in_old_ool_spinlock_code(pc) 0 | ||
51 | #endif | ||
52 | |||
53 | /* Returns non-zero if the PC is in the Interrupt Vector Table */ | 35 | /* Returns non-zero if the PC is in the Interrupt Vector Table */ |
54 | static __inline__ int in_ivt_code(unsigned long pc) | 36 | static __inline__ int in_ivt_code(unsigned long pc) |
55 | { | 37 | { |
@@ -80,7 +62,7 @@ static __inline__ int next_frame(ia64_backtrace_t *bt) | |||
80 | */ | 62 | */ |
81 | if (bt->prev_pfs_loc && bt->regs && bt->frame.pfs_loc == bt->prev_pfs_loc) | 63 | if (bt->prev_pfs_loc && bt->regs && bt->frame.pfs_loc == bt->prev_pfs_loc) |
82 | bt->frame.pfs_loc = &bt->regs->ar_pfs; | 64 | bt->frame.pfs_loc = &bt->regs->ar_pfs; |
83 | bt->prev_pfs_loc = (in_old_ool_spinlock_code(bt->frame.ip) ? bt->frame.pfs_loc : NULL); | 65 | bt->prev_pfs_loc = NULL; |
84 | 66 | ||
85 | return unw_unwind(&bt->frame) == 0; | 67 | return unw_unwind(&bt->frame) == 0; |
86 | } | 68 | } |