summary refs log tree commit diff
path: root/arch/ia64
diff options
context:
space:
mode:
authorTony Luck <tony.luck@intel.com>2009-10-23 17:59:06 -0700
committerTony Luck <tony.luck@intel.com>2009-10-23 17:59:06 -0700
commit8add570a70d2ea6e9e15fce001c6503589c833d1 (patch)
tree2d9c3e75bbd0a9673f9a82d5a8cb98ef67585752 /arch/ia64
parent48fade6c5a96d29cd3d0e016557a3fd835fd4049 (diff)
parent883a3acf5b0d4782ac35981227a0d094e8b44850 (diff)
downloadlinux-8add570a70d2ea6e9e15fce001c6503589c833d1.tar.gz
Pull ticket-spinaphore into release branch
Diffstat (limited to 'arch/ia64')
-rw-r--r--arch/ia64/mm/tlb.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c
index f426dc78d959..ee09d261f2e6 100644
--- a/arch/ia64/mm/tlb.c
+++ b/arch/ia64/mm/tlb.c
@@ -100,24 +100,36 @@ wrap_mmu_context (struct mm_struct *mm)
  * this primitive it can be moved up to a spinaphore.h header.
  */
 struct spinaphore {
-	atomic_t	cur;
+	unsigned long	ticket;
+	unsigned long	serve;
 };
 
 static inline void spinaphore_init(struct spinaphore *ss, int val)
 {
-	atomic_set(&ss->cur, val);
+	ss->ticket = 0;
+	ss->serve = val;
 }
 
 static inline void down_spin(struct spinaphore *ss)
 {
-	while (unlikely(!atomic_add_unless(&ss->cur, -1, 0)))
-		while (atomic_read(&ss->cur) == 0)
-			cpu_relax();
+	unsigned long t = ia64_fetchadd(1, &ss->ticket, acq), serve;
+
+	if (time_before(t, ss->serve))
+		return;
+
+	ia64_invala();
+
+	for (;;) {
+		asm volatile ("ld4.c.nc %0=[%1]" : "=r"(serve) : "r"(&ss->serve) : "memory");
+		if (time_before(t, serve))
+			return;
+		cpu_relax();
+	}
 }
 
 static inline void up_spin(struct spinaphore *ss)
 {
-	atomic_add(1, &ss->cur);
+	ia64_fetchadd(1, &ss->serve, rel);
 }
 
 static struct spinaphore ptcg_sem;