1024b246eSLinus Torvalds #ifndef _ALPHA_SPINLOCK_H 2024b246eSLinus Torvalds #define _ALPHA_SPINLOCK_H 3024b246eSLinus Torvalds 4024b246eSLinus Torvalds #include <linux/kernel.h> 5024b246eSLinus Torvalds #include <asm/current.h> 6*726328d9SPeter Zijlstra #include <asm/barrier.h> 7*726328d9SPeter Zijlstra #include <asm/processor.h> 8024b246eSLinus Torvalds 9024b246eSLinus Torvalds /* 10024b246eSLinus Torvalds * Simple spin lock operations. There are two variants, one clears IRQ's 11024b246eSLinus Torvalds * on the local processor, one does not. 12024b246eSLinus Torvalds * 13024b246eSLinus Torvalds * We make no fairness assumptions. They have a cost. 14024b246eSLinus Torvalds */ 15024b246eSLinus Torvalds 160199c4e6SThomas Gleixner #define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock) 170199c4e6SThomas Gleixner #define arch_spin_is_locked(x) ((x)->lock != 0) 18*726328d9SPeter Zijlstra 19*726328d9SPeter Zijlstra static inline void arch_spin_unlock_wait(arch_spinlock_t *lock) 20*726328d9SPeter Zijlstra { 21*726328d9SPeter Zijlstra smp_cond_load_acquire(&lock->lock, !VAL); 22*726328d9SPeter Zijlstra } 23024b246eSLinus Torvalds 248f8dcb3fSMatt Turner static inline int arch_spin_value_unlocked(arch_spinlock_t lock) 258f8dcb3fSMatt Turner { 268f8dcb3fSMatt Turner return lock.lock == 0; 278f8dcb3fSMatt Turner } 288f8dcb3fSMatt Turner 290199c4e6SThomas Gleixner static inline void arch_spin_unlock(arch_spinlock_t * lock) 30024b246eSLinus Torvalds { 31024b246eSLinus Torvalds mb(); 32024b246eSLinus Torvalds lock->lock = 0; 33024b246eSLinus Torvalds } 34024b246eSLinus Torvalds 350199c4e6SThomas Gleixner static inline void arch_spin_lock(arch_spinlock_t * lock) 36024b246eSLinus Torvalds { 37024b246eSLinus Torvalds long tmp; 38024b246eSLinus Torvalds 39024b246eSLinus Torvalds __asm__ __volatile__( 40024b246eSLinus Torvalds "1: ldl_l %0,%1\n" 41024b246eSLinus Torvalds " bne %0,2f\n" 42024b246eSLinus Torvalds " lda %0,1\n" 43024b246eSLinus Torvalds " stl_c %0,%1\n" 44024b246eSLinus Torvalds " beq %0,2f\n" 45024b246eSLinus Torvalds " mb\n" 46024b246eSLinus Torvalds ".subsection 2\n" 47024b246eSLinus Torvalds "2: ldl %0,%1\n" 48024b246eSLinus Torvalds " bne %0,2b\n" 49024b246eSLinus Torvalds " br 1b\n" 50024b246eSLinus Torvalds ".previous" 51024b246eSLinus Torvalds : "=&r" (tmp), "=m" (lock->lock) 52024b246eSLinus Torvalds : "m"(lock->lock) : "memory"); 53024b246eSLinus Torvalds } 54024b246eSLinus Torvalds 550199c4e6SThomas Gleixner static inline int arch_spin_trylock(arch_spinlock_t *lock) 56024b246eSLinus Torvalds { 57024b246eSLinus Torvalds return !test_and_set_bit(0, &lock->lock); 58024b246eSLinus Torvalds } 59024b246eSLinus Torvalds 60024b246eSLinus Torvalds /***********************************************************/ 61024b246eSLinus Torvalds 62e5931943SThomas Gleixner static inline int arch_read_can_lock(arch_rwlock_t *lock) 63024b246eSLinus Torvalds { 64024b246eSLinus Torvalds return (lock->lock & 1) == 0; 65024b246eSLinus Torvalds } 66024b246eSLinus Torvalds 67e5931943SThomas Gleixner static inline int arch_write_can_lock(arch_rwlock_t *lock) 68024b246eSLinus Torvalds { 69024b246eSLinus Torvalds return lock->lock == 0; 70024b246eSLinus Torvalds } 71024b246eSLinus Torvalds 72e5931943SThomas Gleixner static inline void arch_read_lock(arch_rwlock_t *lock) 73024b246eSLinus Torvalds { 74024b246eSLinus Torvalds long regx; 75024b246eSLinus Torvalds 76024b246eSLinus Torvalds __asm__ __volatile__( 77024b246eSLinus Torvalds "1: ldl_l %1,%0\n" 78024b246eSLinus Torvalds " blbs %1,6f\n" 79024b246eSLinus Torvalds " subl %1,2,%1\n" 80024b246eSLinus Torvalds " stl_c %1,%0\n" 81024b246eSLinus Torvalds " beq %1,6f\n" 82024b246eSLinus Torvalds " mb\n" 83024b246eSLinus Torvalds ".subsection 2\n" 84024b246eSLinus Torvalds "6: ldl %1,%0\n" 85024b246eSLinus Torvalds " blbs %1,6b\n" 86024b246eSLinus Torvalds " br 1b\n" 87024b246eSLinus Torvalds ".previous" 88024b246eSLinus Torvalds : "=m" (*lock), "=&r" (regx) 89024b246eSLinus Torvalds : "m" (*lock) : "memory"); 90024b246eSLinus Torvalds } 91024b246eSLinus Torvalds 92e5931943SThomas Gleixner static inline void arch_write_lock(arch_rwlock_t *lock) 93024b246eSLinus Torvalds { 94024b246eSLinus Torvalds long regx; 95024b246eSLinus Torvalds 96024b246eSLinus Torvalds __asm__ __volatile__( 97024b246eSLinus Torvalds "1: ldl_l %1,%0\n" 98024b246eSLinus Torvalds " bne %1,6f\n" 99024b246eSLinus Torvalds " lda %1,1\n" 100024b246eSLinus Torvalds " stl_c %1,%0\n" 101024b246eSLinus Torvalds " beq %1,6f\n" 102024b246eSLinus Torvalds " mb\n" 103024b246eSLinus Torvalds ".subsection 2\n" 104024b246eSLinus Torvalds "6: ldl %1,%0\n" 105024b246eSLinus Torvalds " bne %1,6b\n" 106024b246eSLinus Torvalds " br 1b\n" 107024b246eSLinus Torvalds ".previous" 108024b246eSLinus Torvalds : "=m" (*lock), "=&r" (regx) 109024b246eSLinus Torvalds : "m" (*lock) : "memory"); 110024b246eSLinus Torvalds } 111024b246eSLinus Torvalds 112e5931943SThomas Gleixner static inline int arch_read_trylock(arch_rwlock_t * lock) 113024b246eSLinus Torvalds { 114024b246eSLinus Torvalds long regx; 115024b246eSLinus Torvalds int success; 116024b246eSLinus Torvalds 117024b246eSLinus Torvalds __asm__ __volatile__( 118024b246eSLinus Torvalds "1: ldl_l %1,%0\n" 119024b246eSLinus Torvalds " lda %2,0\n" 120024b246eSLinus Torvalds " blbs %1,2f\n" 121024b246eSLinus Torvalds " subl %1,2,%2\n" 122024b246eSLinus Torvalds " stl_c %2,%0\n" 123024b246eSLinus Torvalds " beq %2,6f\n" 124024b246eSLinus Torvalds "2: mb\n" 125024b246eSLinus Torvalds ".subsection 2\n" 126024b246eSLinus Torvalds "6: br 1b\n" 127024b246eSLinus Torvalds ".previous" 128024b246eSLinus Torvalds : "=m" (*lock), "=&r" (regx), "=&r" (success) 129024b246eSLinus Torvalds : "m" (*lock) : "memory"); 130024b246eSLinus Torvalds 131024b246eSLinus Torvalds return success; 132024b246eSLinus Torvalds } 133024b246eSLinus Torvalds 134e5931943SThomas Gleixner static inline int arch_write_trylock(arch_rwlock_t * lock) 135024b246eSLinus Torvalds { 136024b246eSLinus Torvalds long regx; 137024b246eSLinus Torvalds int success; 138024b246eSLinus Torvalds 139024b246eSLinus Torvalds __asm__ __volatile__( 140024b246eSLinus Torvalds "1: ldl_l %1,%0\n" 141024b246eSLinus Torvalds " lda %2,0\n" 142024b246eSLinus Torvalds " bne %1,2f\n" 143024b246eSLinus Torvalds " lda %2,1\n" 144024b246eSLinus Torvalds " stl_c %2,%0\n" 145024b246eSLinus Torvalds " beq %2,6f\n" 146024b246eSLinus Torvalds "2: mb\n" 147024b246eSLinus Torvalds ".subsection 2\n" 148024b246eSLinus Torvalds "6: br 1b\n" 149024b246eSLinus Torvalds ".previous" 150024b246eSLinus Torvalds : "=m" (*lock), "=&r" (regx), "=&r" (success) 151024b246eSLinus Torvalds : "m" (*lock) : "memory"); 152024b246eSLinus Torvalds 153024b246eSLinus Torvalds return success; 154024b246eSLinus Torvalds } 155024b246eSLinus Torvalds 156e5931943SThomas Gleixner static inline void arch_read_unlock(arch_rwlock_t * lock) 157024b246eSLinus Torvalds { 158024b246eSLinus Torvalds long regx; 159024b246eSLinus Torvalds __asm__ __volatile__( 160024b246eSLinus Torvalds " mb\n" 161024b246eSLinus Torvalds "1: ldl_l %1,%0\n" 162024b246eSLinus Torvalds " addl %1,2,%1\n" 163024b246eSLinus Torvalds " stl_c %1,%0\n" 164024b246eSLinus Torvalds " beq %1,6f\n" 165024b246eSLinus Torvalds ".subsection 2\n" 166024b246eSLinus Torvalds "6: br 1b\n" 167024b246eSLinus Torvalds ".previous" 168024b246eSLinus Torvalds : "=m" (*lock), "=&r" (regx) 169024b246eSLinus Torvalds : "m" (*lock) : "memory"); 170024b246eSLinus Torvalds } 171024b246eSLinus Torvalds 172e5931943SThomas Gleixner static inline void arch_write_unlock(arch_rwlock_t * lock) 173024b246eSLinus Torvalds { 174024b246eSLinus Torvalds mb(); 175024b246eSLinus Torvalds lock->lock = 0; 176024b246eSLinus Torvalds } 177024b246eSLinus Torvalds 178e5931943SThomas Gleixner #define arch_read_lock_flags(lock, flags) arch_read_lock(lock) 179e5931943SThomas Gleixner #define arch_write_lock_flags(lock, flags) arch_write_lock(lock) 180f5f7eac4SRobin Holt 181024b246eSLinus Torvalds #endif /* _ALPHA_SPINLOCK_H */ 182