1 #ifndef _ALPHA_SPINLOCK_H 2 #define _ALPHA_SPINLOCK_H 3 4 #include <linux/kernel.h> 5 #include <asm/current.h> 6 7 /* 8 * Simple spin lock operations. There are two variants, one clears IRQ's 9 * on the local processor, one does not. 10 * 11 * We make no fairness assumptions. They have a cost. 12 */ 13 14 #define arch_spin_lock_flags(lock, flags) arch_spin_lock(lock) 15 #define arch_spin_is_locked(x) ((x)->lock != 0) 16 #define arch_spin_unlock_wait(x) \ 17 do { cpu_relax(); } while ((x)->lock) 18 19 static inline void arch_spin_unlock(arch_spinlock_t * lock) 20 { 21 mb(); 22 lock->lock = 0; 23 } 24 25 static inline void arch_spin_lock(arch_spinlock_t * lock) 26 { 27 long tmp; 28 29 __asm__ __volatile__( 30 "1: ldl_l %0,%1\n" 31 " bne %0,2f\n" 32 " lda %0,1\n" 33 " stl_c %0,%1\n" 34 " beq %0,2f\n" 35 " mb\n" 36 ".subsection 2\n" 37 "2: ldl %0,%1\n" 38 " bne %0,2b\n" 39 " br 1b\n" 40 ".previous" 41 : "=&r" (tmp), "=m" (lock->lock) 42 : "m"(lock->lock) : "memory"); 43 } 44 45 static inline int arch_spin_trylock(arch_spinlock_t *lock) 46 { 47 return !test_and_set_bit(0, &lock->lock); 48 } 49 50 /***********************************************************/ 51 52 static inline int arch_read_can_lock(arch_rwlock_t *lock) 53 { 54 return (lock->lock & 1) == 0; 55 } 56 57 static inline int arch_write_can_lock(arch_rwlock_t *lock) 58 { 59 return lock->lock == 0; 60 } 61 62 static inline void arch_read_lock(arch_rwlock_t *lock) 63 { 64 long regx; 65 66 __asm__ __volatile__( 67 "1: ldl_l %1,%0\n" 68 " blbs %1,6f\n" 69 " subl %1,2,%1\n" 70 " stl_c %1,%0\n" 71 " beq %1,6f\n" 72 " mb\n" 73 ".subsection 2\n" 74 "6: ldl %1,%0\n" 75 " blbs %1,6b\n" 76 " br 1b\n" 77 ".previous" 78 : "=m" (*lock), "=&r" (regx) 79 : "m" (*lock) : "memory"); 80 } 81 82 static inline void arch_write_lock(arch_rwlock_t *lock) 83 { 84 long regx; 85 86 __asm__ __volatile__( 87 "1: ldl_l %1,%0\n" 88 " bne %1,6f\n" 89 " lda %1,1\n" 90 " stl_c %1,%0\n" 91 " beq %1,6f\n" 92 " mb\n" 93 ".subsection 2\n" 94 "6: ldl %1,%0\n" 95 " bne %1,6b\n" 96 " br 1b\n" 97 ".previous" 98 : "=m" (*lock), "=&r" (regx) 99 : "m" (*lock) : "memory"); 100 } 101 102 static inline int arch_read_trylock(arch_rwlock_t * lock) 103 { 104 long regx; 105 int success; 106 107 __asm__ __volatile__( 108 "1: ldl_l %1,%0\n" 109 " lda %2,0\n" 110 " blbs %1,2f\n" 111 " subl %1,2,%2\n" 112 " stl_c %2,%0\n" 113 " beq %2,6f\n" 114 "2: mb\n" 115 ".subsection 2\n" 116 "6: br 1b\n" 117 ".previous" 118 : "=m" (*lock), "=&r" (regx), "=&r" (success) 119 : "m" (*lock) : "memory"); 120 121 return success; 122 } 123 124 static inline int arch_write_trylock(arch_rwlock_t * lock) 125 { 126 long regx; 127 int success; 128 129 __asm__ __volatile__( 130 "1: ldl_l %1,%0\n" 131 " lda %2,0\n" 132 " bne %1,2f\n" 133 " lda %2,1\n" 134 " stl_c %2,%0\n" 135 " beq %2,6f\n" 136 "2: mb\n" 137 ".subsection 2\n" 138 "6: br 1b\n" 139 ".previous" 140 : "=m" (*lock), "=&r" (regx), "=&r" (success) 141 : "m" (*lock) : "memory"); 142 143 return success; 144 } 145 146 static inline void arch_read_unlock(arch_rwlock_t * lock) 147 { 148 long regx; 149 __asm__ __volatile__( 150 " mb\n" 151 "1: ldl_l %1,%0\n" 152 " addl %1,2,%1\n" 153 " stl_c %1,%0\n" 154 " beq %1,6f\n" 155 ".subsection 2\n" 156 "6: br 1b\n" 157 ".previous" 158 : "=m" (*lock), "=&r" (regx) 159 : "m" (*lock) : "memory"); 160 } 161 162 static inline void arch_write_unlock(arch_rwlock_t * lock) 163 { 164 mb(); 165 lock->lock = 0; 166 } 167 168 #define arch_read_lock_flags(lock, flags) arch_read_lock(lock) 169 #define arch_write_lock_flags(lock, flags) arch_write_lock(lock) 170 171 #endif /* _ALPHA_SPINLOCK_H */ 172