linux/arch/metag/include/asm/spinlock_lock1.h
<<
>>
Prefs
   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