patch-2.4.0-test3 linux/arch/sparc64/lib/dec_and_lock.S

Next file: linux/arch/sparc64/mm/modutil.c
Previous file: linux/arch/sparc64/lib/Makefile
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.0-test2/linux/arch/sparc64/lib/dec_and_lock.S linux/arch/sparc64/lib/dec_and_lock.S
@@ -0,0 +1,61 @@
+/* $Id$
+ * dec_and_lock.S: Sparc64 version of "atomic_dec_and_lock()"
+ *                 using cas and ldstub instructions.
+ *
+ * Copyright (C) 2000 David S. Miller (davem@redhat.com)
+ */
+
+	.text
+	.align	64
+
+	/* CAS basically works like this:
+	 *
+	 * void CAS(MEM, REG1, REG2)
+	 * {
+	 *   START_ATOMIC();
+	 *   if (*(MEM) == REG1) {
+	 *     TMP = *(MEM);
+	 *     *(MEM) = REG2;
+	 *     REG2 = TMP;
+	 *   }
+	 *   END_ATOMIC();
+	 * }
+	 *
+	 * All non-contention cases are handled in 2 I-cache
+	 * lines which is 1 L2 cache line.
+	 */
+
+	.globl	atomic_dec_and_lock
+atomic_dec_and_lock:	/* %o0 = counter, %o1 = lock */
+loop1:	lduw	[%o0], %g5
+	subcc	%g5, 1, %g7
+	be,pn	%icc, to_zero
+	 nop
+nzero:	cas	[%o0], %g5, %g7
+	cmp	%g5, %g7
+	bne,pn	%icc, loop1
+	 mov	0, %g1
+
+out:	retl
+	 mov	%g1, %o0
+to_zero:ldstub	[%o1], %g3
+	brnz,pn	%g3, spin_on_lock
+	 membar	#StoreLoad | #StoreStore
+loop2:	cas	[%o0], %g5, %g7		/* ASSERT(g7 == 0) */
+	brnz,pt	%g7, out
+	 mov	1, %g1
+
+	lduw	[%o0], %g5
+	subcc	%g5, 1, %g7
+	be,pn	%icc, loop2
+	 nop
+	membar	#StoreStore | #LoadStore
+	stb	%g0, [%o1]
+	b,pt	%xcc, nzero
+	 nop
+
+spin_on_lock:
+	ldub	[%o1], %g3
+	brnz,pt	%g3, spin_on_lock
+	 membar	#LoadLoad
+	b,a,pt	%xcc, to_zero

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)