aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel
diff options
context:
space:
mode:
authorTony Luck <tony.luck@intel.com>2009-09-25 11:42:16 -0400
committerTony Luck <tony.luck@intel.com>2009-09-25 11:42:16 -0400
commit2c86963b093c1a0887dfc6b32c6e5ea3a80f2922 (patch)
treed1ed58dd0a644dd670e3724a575112fedd4b4250 /arch/ia64/kernel
parent53cddfcc0e760d2b364878b6dadbd0c6d087cfae (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/kernel')
-rw-r--r--arch/ia64/kernel/head.S89
-rw-r--r--arch/ia64/kernel/ia64_ksyms.c20
2 files changed, 0 insertions, 109 deletions
diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
index 1a6e44515eb4..696eff28a0c4 100644
--- a/arch/ia64/kernel/head.S
+++ b/arch/ia64/kernel/head.S
@@ -1130,95 +1130,6 @@ SET_REG(b5);
1130#endif /* CONFIG_IA64_BRL_EMU */ 1130#endif /* CONFIG_IA64_BRL_EMU */
1131 1131
1132#ifdef CONFIG_SMP 1132#ifdef CONFIG_SMP
1133 /*
1134 * This routine handles spinlock contention. It uses a non-standard calling
1135 * convention to avoid converting leaf routines into interior routines. Because
1136 * of this special convention, there are several restrictions:
1137 *
1138 * - do not use gp relative variables, this code is called from the kernel
1139 * and from modules, r1 is undefined.
1140 * - do not use stacked registers, the caller owns them.
1141 * - do not use the scratch stack space, the caller owns it.
1142 * - do not use any registers other than the ones listed below
1143 *
1144 * Inputs:
1145 * ar.pfs - saved CFM of caller
1146 * ar.ccv - 0 (and available for use)
1147 * r27 - flags from spin_lock_irqsave or 0. Must be preserved.
1148 * r28 - available for use.
1149 * r29 - available for use.
1150 * r30 - available for use.
1151 * r31 - address of lock, available for use.
1152 * b6 - return address
1153 * p14 - available for use.
1154 * p15 - used to track flag status.
1155 *
1156 * If you patch this code to use more registers, do not forget to update
1157 * the clobber lists for spin_lock() in arch/ia64/include/asm/spinlock.h.
1158 */
1159
1160#if (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
1161
1162GLOBAL_ENTRY(ia64_spinlock_contention_pre3_4)
1163 .prologue
1164 .save ar.pfs, r0 // this code effectively has a zero frame size
1165 .save rp, r28
1166 .body
1167 nop 0
1168 tbit.nz p15,p0=r27,IA64_PSR_I_BIT
1169 .restore sp // pop existing prologue after next insn
1170 mov b6 = r28
1171 .prologue
1172 .save ar.pfs, r0
1173 .altrp b6
1174 .body
1175 ;;
1176(p15) ssm psr.i // reenable interrupts if they were on
1177 // DavidM says that srlz.d is slow and is not required in this case
1178.wait:
1179 // exponential backoff, kdb, lockmeter etc. go in here
1180 hint @pause
1181 ld4 r30=[r31] // don't use ld4.bias; if it's contended, we won't write the word
1182 nop 0
1183 ;;
1184 cmp4.ne p14,p0=r30,r0
1185(p14) br.cond.sptk.few .wait
1186(p15) rsm psr.i // disable interrupts if we reenabled them
1187 br.cond.sptk.few b6 // lock is now free, try to acquire
1188 .global ia64_spinlock_contention_pre3_4_end // for kernprof
1189ia64_spinlock_contention_pre3_4_end:
1190END(ia64_spinlock_contention_pre3_4)
1191
1192#else
1193
1194GLOBAL_ENTRY(ia64_spinlock_contention)
1195 .prologue
1196 .altrp b6
1197 .body
1198 tbit.nz p15,p0=r27,IA64_PSR_I_BIT
1199 ;;
1200.wait:
1201(p15) ssm psr.i // reenable interrupts if they were on
1202 // DavidM says that srlz.d is slow and is not required in this case
1203.wait2:
1204 // exponential backoff, kdb, lockmeter etc. go in here
1205 hint @pause
1206 ld4 r30=[r31] // don't use ld4.bias; if it's contended, we won't write the word
1207 ;;
1208 cmp4.ne p14,p0=r30,r0
1209 mov r30 = 1
1210(p14) br.cond.sptk.few .wait2
1211(p15) rsm psr.i // disable interrupts if we reenabled them
1212 ;;
1213 cmpxchg4.acq r30=[r31], r30, ar.ccv
1214 ;;
1215 cmp4.ne p14,p0=r0,r30
1216(p14) br.cond.sptk.few .wait
1217
1218 br.ret.sptk.many b6 // lock is now taken
1219END(ia64_spinlock_contention)
1220
1221#endif
1222 1133
1223#ifdef CONFIG_HOTPLUG_CPU 1134#ifdef CONFIG_HOTPLUG_CPU
1224GLOBAL_ENTRY(ia64_jump_to_sal) 1135GLOBAL_ENTRY(ia64_jump_to_sal)
diff --git a/arch/ia64/kernel/ia64_ksyms.c b/arch/ia64/kernel/ia64_ksyms.c
index 8ebccb589e1c..14d39e300627 100644
--- a/arch/ia64/kernel/ia64_ksyms.c
+++ b/arch/ia64/kernel/ia64_ksyms.c
@@ -84,26 +84,6 @@ EXPORT_SYMBOL(ia64_save_scratch_fpregs);
84#include <asm/unwind.h> 84#include <asm/unwind.h>
85EXPORT_SYMBOL(unw_init_running); 85EXPORT_SYMBOL(unw_init_running);
86 86
87#ifdef ASM_SUPPORTED
88# ifdef CONFIG_SMP
89# if (__GNUC__ == 3 && __GNUC_MINOR__ < 3)
90/*
91 * This is not a normal routine and we don't want a function descriptor for it, so we use
92 * a fake declaration here.
93 */
94extern char ia64_spinlock_contention_pre3_4;
95EXPORT_SYMBOL(ia64_spinlock_contention_pre3_4);
96# else
97/*
98 * This is not a normal routine and we don't want a function descriptor for it, so we use
99 * a fake declaration here.
100 */
101extern char ia64_spinlock_contention;
102EXPORT_SYMBOL(ia64_spinlock_contention);
103# endif
104# endif
105#endif
106
107#if defined(CONFIG_IA64_ESI) || defined(CONFIG_IA64_ESI_MODULE) 87#if defined(CONFIG_IA64_ESI) || defined(CONFIG_IA64_ESI_MODULE)
108extern void esi_call_phys (void); 88extern void esi_call_phys (void);
109EXPORT_SYMBOL_GPL(esi_call_phys); 89EXPORT_SYMBOL_GPL(esi_call_phys);