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