From 57f0f512b273f60d52568b8c6b77e17f5636edc0 Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Wed, 5 Aug 2015 17:04:01 -0300 Subject: Initial import --- arch/metag/include/asm/spinlock_lnkget.h | 249 +++++++++++++++++++++++++++++++ 1 file changed, 249 insertions(+) create mode 100644 arch/metag/include/asm/spinlock_lnkget.h (limited to 'arch/metag/include/asm/spinlock_lnkget.h') diff --git a/arch/metag/include/asm/spinlock_lnkget.h b/arch/metag/include/asm/spinlock_lnkget.h new file mode 100644 index 000000000..ad8436fee --- /dev/null +++ b/arch/metag/include/asm/spinlock_lnkget.h @@ -0,0 +1,249 @@ +#ifndef __ASM_SPINLOCK_LNKGET_H +#define __ASM_SPINLOCK_LNKGET_H + +/* + * None of these asm statements clobber memory as LNKSET writes around + * the cache so the memory it modifies cannot safely be read by any means + * other than these accessors. + */ + +static inline int arch_spin_is_locked(arch_spinlock_t *lock) +{ + int ret; + + asm volatile ("LNKGETD %0, [%1]\n" + "TST %0, #1\n" + "MOV %0, #1\n" + "XORZ %0, %0, %0\n" + : "=&d" (ret) + : "da" (&lock->lock) + : "cc"); + return ret; +} + +static inline void arch_spin_lock(arch_spinlock_t *lock) +{ + int tmp; + + asm volatile ("1: LNKGETD %0,[%1]\n" + " TST %0, #1\n" + " ADD %0, %0, #1\n" + " LNKSETDZ [%1], %0\n" + " BNZ 1b\n" + " DEFR %0, TXSTAT\n" + " ANDT %0, %0, #HI(0x3f000000)\n" + " CMPT %0, #HI(0x02000000)\n" + " BNZ 1b\n" + : "=&d" (tmp) + : "da" (&lock->lock) + : "cc"); + + smp_mb(); +} + +/* Returns 0 if failed to acquire lock */ +static inline int arch_spin_trylock(arch_spinlock_t *lock) +{ + int tmp; + + asm volatile (" LNKGETD %0,[%1]\n" + " TST %0, #1\n" + " ADD %0, %0, #1\n" + " LNKSETDZ [%1], %0\n" + " BNZ 1f\n" + " DEFR %0, TXSTAT\n" + " ANDT %0, %0, #HI(0x3f000000)\n" + " CMPT %0, #HI(0x02000000)\n" + " MOV %0, #1\n" + "1: XORNZ %0, %0, %0\n" + : "=&d" (tmp) + : "da" (&lock->lock) + : "cc"); + + smp_mb(); + + return tmp; +} + +static inline void arch_spin_unlock(arch_spinlock_t *lock) +{ + smp_mb(); + + asm volatile (" SETD [%0], %1\n" + : + : "da" (&lock->lock), "da" (0) + : "memory"); +} + +/* + * RWLOCKS + * + * + * Write locks are easy - we just set bit 31. When unlocking, we can + * just write zero since the lock is exclusively held. + */ + +static inline void arch_write_lock(arch_rwlock_t *rw) +{ + int tmp; + + asm volatile ("1: LNKGETD %0,[%1]\n" + " CMP %0, #0\n" + " ADD %0, %0, %2\n" + " LNKSETDZ [%1], %0\n" + " BNZ 1b\n" + " DEFR %0, TXSTAT\n" + " ANDT %0, %0, #HI(0x3f000000)\n" + " CMPT %0, #HI(0x02000000)\n" + " BNZ 1b\n" + : "=&d" (tmp) + : "da" (&rw->lock), "bd" (0x80000000) + : "cc"); + + smp_mb(); +} + +static inline int arch_write_trylock(arch_rwlock_t *rw) +{ + int tmp; + + asm volatile (" LNKGETD %0,[%1]\n" + " CMP %0, #0\n" + " ADD %0, %0, %2\n" + " LNKSETDZ [%1], %0\n" + " BNZ 1f\n" + " DEFR %0, TXSTAT\n" + " ANDT %0, %0, #HI(0x3f000000)\n" + " CMPT %0, #HI(0x02000000)\n" + " MOV %0,#1\n" + "1: XORNZ %0, %0, %0\n" + : "=&d" (tmp) + : "da" (&rw->lock), "bd" (0x80000000) + : "cc"); + + smp_mb(); + + return tmp; +} + +static inline void arch_write_unlock(arch_rwlock_t *rw) +{ + smp_mb(); + + asm volatile (" SETD [%0], %1\n" + : + : "da" (&rw->lock), "da" (0) + : "memory"); +} + +/* write_can_lock - would write_trylock() succeed? */ +static inline int arch_write_can_lock(arch_rwlock_t *rw) +{ + int ret; + + asm volatile ("LNKGETD %0, [%1]\n" + "CMP %0, #0\n" + "MOV %0, #1\n" + "XORNZ %0, %0, %0\n" + : "=&d" (ret) + : "da" (&rw->lock) + : "cc"); + return ret; +} + +/* + * Read locks are a bit more hairy: + * - Exclusively load the lock value. + * - Increment it. + * - Store new lock value if positive, and we still own this location. + * If the value is negative, we've already failed. + * - If we failed to store the value, we want a negative result. + * - If we failed, try again. + * Unlocking is similarly hairy. We may have multiple read locks + * currently active. However, we know we won't have any write + * locks. + */ +static inline void arch_read_lock(arch_rwlock_t *rw) +{ + int tmp; + + asm volatile ("1: LNKGETD %0,[%1]\n" + " ADDS %0, %0, #1\n" + " LNKSETDPL [%1], %0\n" + " BMI 1b\n" + " DEFR %0, TXSTAT\n" + " ANDT %0, %0, #HI(0x3f000000)\n" + " CMPT %0, #HI(0x02000000)\n" + " BNZ 1b\n" + : "=&d" (tmp) + : "da" (&rw->lock) + : "cc"); + + smp_mb(); +} + +static inline void arch_read_unlock(arch_rwlock_t *rw) +{ + int tmp; + + smp_mb(); + + asm volatile ("1: LNKGETD %0,[%1]\n" + " SUB %0, %0, #1\n" + " LNKSETD [%1], %0\n" + " DEFR %0, TXSTAT\n" + " ANDT %0, %0, #HI(0x3f000000)\n" + " CMPT %0, #HI(0x02000000)\n" + " BNZ 1b\n" + : "=&d" (tmp) + : "da" (&rw->lock) + : "cc", "memory"); +} + +static inline int arch_read_trylock(arch_rwlock_t *rw) +{ + int tmp; + + asm volatile (" LNKGETD %0,[%1]\n" + " ADDS %0, %0, #1\n" + " LNKSETDPL [%1], %0\n" + " BMI 1f\n" + " DEFR %0, TXSTAT\n" + " ANDT %0, %0, #HI(0x3f000000)\n" + " CMPT %0, #HI(0x02000000)\n" + " MOV %0,#1\n" + " BZ 2f\n" + "1: MOV %0,#0\n" + "2:\n" + : "=&d" (tmp) + : "da" (&rw->lock) + : "cc"); + + smp_mb(); + + return tmp; +} + +/* read_can_lock - would read_trylock() succeed? */ +static inline int arch_read_can_lock(arch_rwlock_t *rw) +{ + int tmp; + + asm volatile ("LNKGETD %0, [%1]\n" + "CMP %0, %2\n" + "MOV %0, #1\n" + "XORZ %0, %0, %0\n" + : "=&d" (tmp) + : "da" (&rw->lock), "bd" (0x80000000) + : "cc"); + return tmp; +} + +#define arch_read_lock_flags(lock, flags) arch_read_lock(lock) +#define arch_write_lock_flags(lock, flags) arch_write_lock(lock) + +#define arch_spin_relax(lock) cpu_relax() +#define arch_read_relax(lock) cpu_relax() +#define arch_write_relax(lock) cpu_relax() + +#endif /* __ASM_SPINLOCK_LNKGET_H */ -- cgit v1.2.3-54-g00ecf