1#ifndef __ASM_SPINLOCK_LOCK1_H 2#define __ASM_SPINLOCK_LOCK1_H 3 4#include <asm/bug.h> 5#include <asm/global_lock.h> 6 7static inline int arch_spin_is_locked(arch_spinlock_t *lock) 8{ 9 int ret; 10 11 barrier(); 12 ret = lock->lock; 13 WARN_ON(ret != 0 && ret != 1); 14 return ret; 15} 16 17static inline void arch_spin_lock(arch_spinlock_t *lock) 18{ 19 unsigned int we_won = 0; 20 unsigned long flags; 21 22again: 23 __global_lock1(flags); 24 if (lock->lock == 0) { 25 fence(); 26 lock->lock = 1; 27 we_won = 1; 28 } 29 __global_unlock1(flags); 30 if (we_won == 0) 31 goto again; 32 WARN_ON(lock->lock != 1); 33} 34 35/* Returns 0 if failed to acquire lock */ 36static inline int arch_spin_trylock(arch_spinlock_t *lock) 37{ 38 unsigned long flags; 39 unsigned int ret; 40 41 __global_lock1(flags); 42 ret = lock->lock; 43 if (ret == 0) { 44 fence(); 45 lock->lock = 1; 46 } 47 __global_unlock1(flags); 48 return (ret == 0); 49} 50 51static inline void arch_spin_unlock(arch_spinlock_t *lock) 52{ 53 barrier(); 54 WARN_ON(!lock->lock); 55 lock->lock = 0; 56} 57 58/* 59 * RWLOCKS 60 * 61 * 62 * Write locks are easy - we just set bit 31. When unlocking, we can 63 * just write zero since the lock is exclusively held. 64 */ 65 66static inline void arch_write_lock(arch_rwlock_t *rw) 67{ 68 unsigned long flags; 69 unsigned int we_won = 0; 70 71again: 72 __global_lock1(flags); 73 if (rw->lock == 0) { 74 fence(); 75 rw->lock = 0x80000000; 76 we_won = 1; 77 } 78 __global_unlock1(flags); 79 if (we_won == 0) 80 goto again; 81 WARN_ON(rw->lock != 0x80000000); 82} 83 84static inline int arch_write_trylock(arch_rwlock_t *rw) 85{ 86 unsigned long flags; 87 unsigned int ret; 88 89 __global_lock1(flags); 90 ret = rw->lock; 91 if (ret == 0) { 92 fence(); 93 rw->lock = 0x80000000; 94 } 95 __global_unlock1(flags); 96 97 return (ret == 0); 98} 99 100static inline void arch_write_unlock(arch_rwlock_t *rw) 101{ 102 barrier(); 103 WARN_ON(rw->lock != 0x80000000); 104 rw->lock = 0; 105} 106 107/* write_can_lock - would write_trylock() succeed? */ 108static inline int arch_write_can_lock(arch_rwlock_t *rw) 109{ 110 unsigned int ret; 111 112 barrier(); 113 ret = rw->lock; 114 return (ret == 0); 115} 116 117/* 118 * Read locks are a bit more hairy: 119 * - Exclusively load the lock value. 120 * - Increment it. 121 * - Store new lock value if positive, and we still own this location. 122 * If the value is negative, we've already failed. 123 * - If we failed to store the value, we want a negative result. 124 * - If we failed, try again. 125 * Unlocking is similarly hairy. We may have multiple read locks 126 * currently active. However, we know we won't have any write 127 * locks. 128 */ 129static inline void arch_read_lock(arch_rwlock_t *rw) 130{ 131 unsigned long flags; 132 unsigned int we_won = 0, ret; 133 134again: 135 __global_lock1(flags); 136 ret = rw->lock; 137 if (ret < 0x80000000) { 138 fence(); 139 rw->lock = ret + 1; 140 we_won = 1; 141 } 142 __global_unlock1(flags); 143 if (!we_won) 144 goto again; 145} 146 147static inline void arch_read_unlock(arch_rwlock_t *rw) 148{ 149 unsigned long flags; 150 unsigned int ret; 151 152 __global_lock1(flags); 153 fence(); 154 ret = rw->lock--; 155 __global_unlock1(flags); 156 WARN_ON(ret == 0); 157} 158 159static inline int arch_read_trylock(arch_rwlock_t *rw) 160{ 161 unsigned long flags; 162 unsigned int ret; 163 164 __global_lock1(flags); 165 ret = rw->lock; 166 if (ret < 0x80000000) { 167 fence(); 168 rw->lock = ret + 1; 169 } 170 __global_unlock1(flags); 171 return (ret < 0x80000000); 172} 173 174/* read_can_lock - would read_trylock() succeed? */ 175static inline int arch_read_can_lock(arch_rwlock_t *rw) 176{ 177 unsigned int ret; 178 179 barrier(); 180 ret = rw->lock; 181 return (ret < 0x80000000); 182} 183 184#endif /* __ASM_SPINLOCK_LOCK1_H */ 185