patch-2.1.42 linux/include/asm-sparc64/spinlock.h
Next file: linux/include/asm-sparc64/unistd.h
Previous file: linux/include/asm-sparc64/softirq.h
Back to the patch index
Back to the overall index
- Lines: 209
- Date:
Wed May 28 10:49:11 1997
- Orig file:
v2.1.41/linux/include/asm-sparc64/spinlock.h
- Orig date:
Wed Apr 23 19:01:28 1997
diff -u --recursive --new-file v2.1.41/linux/include/asm-sparc64/spinlock.h linux/include/asm-sparc64/spinlock.h
@@ -52,9 +52,206 @@
#define write_unlock_irqrestore(lock, flags) restore_flags(flags)
#else /* !(__SMP__) */
-#error SMP not supported on sparc64
+
+typedef unsigned char spinlock_t;
+#define SPIN_LOCK_UNLOCKED 0
+#define spin_lock_init(lock) (*(lock) = 0)
+#define spin_unlock_wait(lock) do { barrier(); } while(*(volatile spinlock_t *)lock)
+
+extern __inline__ void spin_lock(spinlock_t *lock)
+{
+ __asm__ __volatile__("
+1: ldstub [%0], %%g2
+ brnz,a,pn %%g2, 2f
+ ldub [%0], %%g2
+ .text 2
+2: brnz,a,pt 2b
+ ldub [%0], %%g2
+ b,a,pt %%xcc, 1b
+ .previous
+" : /* no outputs */
+ : "r" (lock)
+ : "g2", "memory");
+}
+
+extern __inline__ int spin_trylock(spinlock_t *lock)
+{
+ unsigned int result;
+ __asm__ __volatile__("ldstub [%1], %0"
+ : "=r" (result)
+ : "r" (lock)
+ : "memory");
+ return (result == 0);
+}
+
+extern __inline__ void spin_unlock(spinlock_t *lock)
+{
+ __asm__ __volatile__("stb %%g0, [%0]" : : "r" (lock) : "memory");
+}
+
+extern __inline__ void spin_lock_irq(spinlock_t *lock)
+{
+ __asm__ __volatile__("
+ wrpr %%g0, 15, %%pil
+ ldstub [%0], %%g2
+ brnz,a,pn %%g2, 2f
+ ldub [%0], %%g2
+ .text 2
+2: brnz,a,pt 2b
+ ldub [%0], %%g2
+ b,a,pt %%xcc, 1b
+ .previous
+" : /* no outputs */
+ : "r" (lock)
+ : "g2", "memory");
+}
+
+extern __inline__ void spin_unlock_irq(spinlock_t *lock)
+{
+ __asm__ __volatile__("
+ stb %%g0, [%0]
+ wrpr %%g0, 0x0, %%pil
+" : /* no outputs */
+ : "r" (lock)
+ : "memory");
+}
+
+#define spin_lock_irqsave(lock, flags) \
+do { register spinlock_t *lp asm("g1"); \
+ lp = lock; \
+ __asm__ __volatile__( \
+ " rdpr %%pil, %0\n\t" \
+ " wrpr %%g0, 15, %%pil\n\t" \
+ "1: ldstub [%1], %%g2\n\t" \
+ " brnz,a,pnt %%g2, 2f\n\t" \
+ " ldub [%1], %%g2\n\t" \
+ " .text 2\n\t" \
+ "2: brnz,a,pt %%g2, 2b\n\t" \
+ " ldub [%1], %%g2\n\t" \
+ " b,a,pt %%xcc, 1b\n\t" \
+ " .previous\n" \
+ : "=r" (flags) \
+ : "r" (lp) \
+ : "g2", "memory"); \
+} while(0)
+
+extern __inline__ void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
+{
+ __asm__ __volatile__("
+ stb %%g0, [%0]
+ wrpr %1, 0x0, %%pil
+" : /* no outputs */
+ : "r" (lock), "r" (flags)
+ : "memory");
+}
+
+/* Multi-reader locks, these are much saner than the 32-bit Sparc ones... */
+
+typedef unsigned long rwlock_t;
+#define RW_LOCK_UNLOCKED 0
+
+extern __inline__ void read_lock(rwlock_t *rw)
+{
+ __asm__ __volatile__("
+ ldx [%0], %%g2
+1:
+ brlz,pn %%g2, 2f
+4: add %%g2, 1, %%g3
+ casx [%0], %%g2, %%g3
+ cmp %%g2, %%g3
+ bne,a,pn %%xcc, 1b
+ ldx [%0],%%g2
+ .text 2
+2: ldx [%0], %%g2
+3: brlz,pt %%g2, 3b
+ ldx [%0], %%g2
+ b,a,pt %%xcc, 4b
+ .previous
+" : /* no outputs */
+ : "r" (rw)
+ : "g2", "g3", "memory");
+}
+
+extern __inline__ void read_unlock(rwlock_t *rw)
+{
+ __asm__ __volatile__("
+ ldx [%0], %%g2
+1:
+ sub %%g2, 1, %%g3
+ casx [%0], %%g2, %%g3
+ cmp %%g2, %%g3
+ bne,a,pn %%xcc, 1b
+ ldx [%0], %%g2
+" : /* no outputs */
+ : "r" (rw)
+ : "g2", "g3", "memory");
+}
+
+extern __inline__ void write_lock(rwlock_t *rw)
+{
+ __asm__ __volatile__("
+ sethi %%uhi(0x8000000000000000), %%g5
+ ldx [%0] %%g2
+ sllx %%g5, 32, %%g5
+1:
+ brlz,pn %%g2, 5f
+4: or %%g2, %%g5, %%g3
+ casx [%0], %%g2, %%g3
+ cmp %%g2, %%g3
+ bne,a,pn %%xcc, 1b
+ ldx [%0], %%g2
+ andncc %%g3, %%g5, %%g0
+ bne,a,pn %%xcc, 3f
+ ldx [%0], %%g2
+ .text 2
+3:
+ andn %%g2, %%g5, %%g3
+ casx [%0], %%g2, %%g3
+ cmp %%g2, %%g3
+ bne,a,pn %%xcc, 3b
+ ldx [%0], %%g2
+5: ldx [%0], %%g2
+6: brlz,pt %%g2, 6b
+ ldx [%0], %%g2
+ b,a,pt %%xcc, 4b
+" : /* no outputs */
+ : "r" (rw)
+ : "g2", "g3", "g5", "memory", "cc");
+}
+
+extern __inline__ void write_unlock(rwlock_t *rw)
+{
+ __asm__ __volatile__("
+ sethi %%uhi(0x8000000000000000), %%g5
+ ldx [%0], %%g2
+ sllx %%g5, 32, %%g5
+1:
+ andn %%g2, %%g5, %%g3
+ casx [%0], %%g2, %%g3
+ cmp %%g2, %%g3
+ bne,a,pn %%xcc, 1b
+ ldx [%0], %%g2
+" : /* no outputs */
+ : "r" (rw)
+ : "g2", "g3", "g5", "memory", "cc");
+}
+
+#define read_lock_irq(lock) do { __cli(); read_lock(lock); } while (0)
+#define read_unlock_irq(lock) do { read_unlock(lock); __sti(); } while (0)
+#define write_lock_irq(lock) do { __cli(); write_lock(lock); } while (0)
+#define write_unlock_irq(lock) do { write_unlock(lock); __sti(); } while (0)
+
+#define read_lock_irqsave(lock, flags) \
+ do { __save_and_cli(flags); read_lock(lock); } while (0)
+#define read_unlock_irqrestore(lock, flags) \
+ do { read_unlock(lock); __restore_flags(flags); } while (0)
+#define write_lock_irqsave(lock, flags) \
+ do { __save_and_cli(flags); write_lock(lock); } while (0)
+#define write_unlock_irqrestore(lock, flags) \
+ do { write_unlock(lock); __restore_flags(flags); } while (0)
+
#endif /* __SMP__ */
#endif /* !(__ASSEMBLY__) */
-#endif /* !(__SPARC64_SPINLOCK_H) */
+#endif /* !(__SPARC64_SPIN%0_H) */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov