1024b246eSLinus Torvalds #ifndef _ALPHA_SPINLOCK_H 2024b246eSLinus Torvalds #define _ALPHA_SPINLOCK_H 3024b246eSLinus Torvalds 4024b246eSLinus Torvalds #include <asm/system.h> 5024b246eSLinus Torvalds #include <linux/kernel.h> 6024b246eSLinus Torvalds #include <asm/current.h> 7024b246eSLinus Torvalds 8024b246eSLinus Torvalds /* 9024b246eSLinus Torvalds * Simple spin lock operations. There are two variants, one clears IRQ's 10024b246eSLinus Torvalds * on the local processor, one does not. 11024b246eSLinus Torvalds * 12024b246eSLinus Torvalds * We make no fairness assumptions. They have a cost. 13024b246eSLinus Torvalds */ 14024b246eSLinus Torvalds 150199c4e6SThomas Gleixner #define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock) 160199c4e6SThomas Gleixner #define arch_spin_is_locked(x) ((x)->lock != 0) 170199c4e6SThomas Gleixner #define arch_spin_unlock_wait(x) \ 18024b246eSLinus Torvalds do { cpu_relax(); } while ((x)->lock) 19024b246eSLinus Torvalds 200199c4e6SThomas Gleixner static inline void arch_spin_unlock(arch_spinlock_t * lock) 21024b246eSLinus Torvalds { 22024b246eSLinus Torvalds mb(); 23024b246eSLinus Torvalds lock->lock = 0; 24024b246eSLinus Torvalds } 25024b246eSLinus Torvalds 260199c4e6SThomas Gleixner static inline void arch_spin_lock(arch_spinlock_t * lock) 27024b246eSLinus Torvalds { 28024b246eSLinus Torvalds long tmp; 29024b246eSLinus Torvalds 30024b246eSLinus Torvalds __asm__ __volatile__( 31024b246eSLinus Torvalds "1: ldl_l %0,%1\n" 32024b246eSLinus Torvalds " bne %0,2f\n" 33024b246eSLinus Torvalds " lda %0,1\n" 34024b246eSLinus Torvalds " stl_c %0,%1\n" 35024b246eSLinus Torvalds " beq %0,2f\n" 36024b246eSLinus Torvalds " mb\n" 37024b246eSLinus Torvalds ".subsection 2\n" 38024b246eSLinus Torvalds "2: ldl %0,%1\n" 39024b246eSLinus Torvalds " bne %0,2b\n" 40024b246eSLinus Torvalds " br 1b\n" 41024b246eSLinus Torvalds ".previous" 42024b246eSLinus Torvalds : "=&r" (tmp), "=m" (lock->lock) 43024b246eSLinus Torvalds : "m"(lock->lock) : "memory"); 44024b246eSLinus Torvalds } 45024b246eSLinus Torvalds 460199c4e6SThomas Gleixner static inline int arch_spin_trylock(arch_spinlock_t *lock) 47024b246eSLinus Torvalds { 48024b246eSLinus Torvalds return !test_and_set_bit(0, &lock->lock); 49024b246eSLinus Torvalds } 50024b246eSLinus Torvalds 51024b246eSLinus Torvalds /***********************************************************/ 52024b246eSLinus Torvalds 53*e5931943SThomas Gleixner static inline int arch_read_can_lock(arch_rwlock_t *lock) 54024b246eSLinus Torvalds { 55024b246eSLinus Torvalds return (lock->lock & 1) == 0; 56024b246eSLinus Torvalds } 57024b246eSLinus Torvalds 58*e5931943SThomas Gleixner static inline int arch_write_can_lock(arch_rwlock_t *lock) 59024b246eSLinus Torvalds { 60024b246eSLinus Torvalds return lock->lock == 0; 61024b246eSLinus Torvalds } 62024b246eSLinus Torvalds 63*e5931943SThomas Gleixner static inline void arch_read_lock(arch_rwlock_t *lock) 64024b246eSLinus Torvalds { 65024b246eSLinus Torvalds long regx; 66024b246eSLinus Torvalds 67024b246eSLinus Torvalds __asm__ __volatile__( 68024b246eSLinus Torvalds "1: ldl_l %1,%0\n" 69024b246eSLinus Torvalds " blbs %1,6f\n" 70024b246eSLinus Torvalds " subl %1,2,%1\n" 71024b246eSLinus Torvalds " stl_c %1,%0\n" 72024b246eSLinus Torvalds " beq %1,6f\n" 73024b246eSLinus Torvalds " mb\n" 74024b246eSLinus Torvalds ".subsection 2\n" 75024b246eSLinus Torvalds "6: ldl %1,%0\n" 76024b246eSLinus Torvalds " blbs %1,6b\n" 77024b246eSLinus Torvalds " br 1b\n" 78024b246eSLinus Torvalds ".previous" 79024b246eSLinus Torvalds : "=m" (*lock), "=&r" (regx) 80024b246eSLinus Torvalds : "m" (*lock) : "memory"); 81024b246eSLinus Torvalds } 82024b246eSLinus Torvalds 83*e5931943SThomas Gleixner static inline void arch_write_lock(arch_rwlock_t *lock) 84024b246eSLinus Torvalds { 85024b246eSLinus Torvalds long regx; 86024b246eSLinus Torvalds 87024b246eSLinus Torvalds __asm__ __volatile__( 88024b246eSLinus Torvalds "1: ldl_l %1,%0\n" 89024b246eSLinus Torvalds " bne %1,6f\n" 90024b246eSLinus Torvalds " lda %1,1\n" 91024b246eSLinus Torvalds " stl_c %1,%0\n" 92024b246eSLinus Torvalds " beq %1,6f\n" 93024b246eSLinus Torvalds " mb\n" 94024b246eSLinus Torvalds ".subsection 2\n" 95024b246eSLinus Torvalds "6: ldl %1,%0\n" 96024b246eSLinus Torvalds " bne %1,6b\n" 97024b246eSLinus Torvalds " br 1b\n" 98024b246eSLinus Torvalds ".previous" 99024b246eSLinus Torvalds : "=m" (*lock), "=&r" (regx) 100024b246eSLinus Torvalds : "m" (*lock) : "memory"); 101024b246eSLinus Torvalds } 102024b246eSLinus Torvalds 103*e5931943SThomas Gleixner static inline int arch_read_trylock(arch_rwlock_t * lock) 104024b246eSLinus Torvalds { 105024b246eSLinus Torvalds long regx; 106024b246eSLinus Torvalds int success; 107024b246eSLinus Torvalds 108024b246eSLinus Torvalds __asm__ __volatile__( 109024b246eSLinus Torvalds "1: ldl_l %1,%0\n" 110024b246eSLinus Torvalds " lda %2,0\n" 111024b246eSLinus Torvalds " blbs %1,2f\n" 112024b246eSLinus Torvalds " subl %1,2,%2\n" 113024b246eSLinus Torvalds " stl_c %2,%0\n" 114024b246eSLinus Torvalds " beq %2,6f\n" 115024b246eSLinus Torvalds "2: mb\n" 116024b246eSLinus Torvalds ".subsection 2\n" 117024b246eSLinus Torvalds "6: br 1b\n" 118024b246eSLinus Torvalds ".previous" 119024b246eSLinus Torvalds : "=m" (*lock), "=&r" (regx), "=&r" (success) 120024b246eSLinus Torvalds : "m" (*lock) : "memory"); 121024b246eSLinus Torvalds 122024b246eSLinus Torvalds return success; 123024b246eSLinus Torvalds } 124024b246eSLinus Torvalds 125*e5931943SThomas Gleixner static inline int arch_write_trylock(arch_rwlock_t * lock) 126024b246eSLinus Torvalds { 127024b246eSLinus Torvalds long regx; 128024b246eSLinus Torvalds int success; 129024b246eSLinus Torvalds 130024b246eSLinus Torvalds __asm__ __volatile__( 131024b246eSLinus Torvalds "1: ldl_l %1,%0\n" 132024b246eSLinus Torvalds " lda %2,0\n" 133024b246eSLinus Torvalds " bne %1,2f\n" 134024b246eSLinus Torvalds " lda %2,1\n" 135024b246eSLinus Torvalds " stl_c %2,%0\n" 136024b246eSLinus Torvalds " beq %2,6f\n" 137024b246eSLinus Torvalds "2: mb\n" 138024b246eSLinus Torvalds ".subsection 2\n" 139024b246eSLinus Torvalds "6: br 1b\n" 140024b246eSLinus Torvalds ".previous" 141024b246eSLinus Torvalds : "=m" (*lock), "=&r" (regx), "=&r" (success) 142024b246eSLinus Torvalds : "m" (*lock) : "memory"); 143024b246eSLinus Torvalds 144024b246eSLinus Torvalds return success; 145024b246eSLinus Torvalds } 146024b246eSLinus Torvalds 147*e5931943SThomas Gleixner static inline void arch_read_unlock(arch_rwlock_t * lock) 148024b246eSLinus Torvalds { 149024b246eSLinus Torvalds long regx; 150024b246eSLinus Torvalds __asm__ __volatile__( 151024b246eSLinus Torvalds " mb\n" 152024b246eSLinus Torvalds "1: ldl_l %1,%0\n" 153024b246eSLinus Torvalds " addl %1,2,%1\n" 154024b246eSLinus Torvalds " stl_c %1,%0\n" 155024b246eSLinus Torvalds " beq %1,6f\n" 156024b246eSLinus Torvalds ".subsection 2\n" 157024b246eSLinus Torvalds "6: br 1b\n" 158024b246eSLinus Torvalds ".previous" 159024b246eSLinus Torvalds : "=m" (*lock), "=&r" (regx) 160024b246eSLinus Torvalds : "m" (*lock) : "memory"); 161024b246eSLinus Torvalds } 162024b246eSLinus Torvalds 163*e5931943SThomas Gleixner static inline void arch_write_unlock(arch_rwlock_t * lock) 164024b246eSLinus Torvalds { 165024b246eSLinus Torvalds mb(); 166024b246eSLinus Torvalds lock->lock = 0; 167024b246eSLinus Torvalds } 168024b246eSLinus Torvalds 169*e5931943SThomas Gleixner #define arch_read_lock_flags(lock, flags) arch_read_lock(lock) 170*e5931943SThomas Gleixner #define arch_write_lock_flags(lock, flags) arch_write_lock(lock) 171f5f7eac4SRobin Holt 1720199c4e6SThomas Gleixner #define arch_spin_relax(lock) cpu_relax() 1730199c4e6SThomas Gleixner #define arch_read_relax(lock) cpu_relax() 1740199c4e6SThomas Gleixner #define arch_write_relax(lock) cpu_relax() 175024b246eSLinus Torvalds 176024b246eSLinus Torvalds #endif /* _ALPHA_SPINLOCK_H */ 177