linux/arch/sparc/include/asm/rwsem.h
<<
>>
Prefs
   1/*
   2 * rwsem.h: R/W semaphores implemented using CAS
   3 *
   4 * Written by David S. Miller (davem@redhat.com), 2001.
   5 * Derived from asm-i386/rwsem.h
   6 */
   7#ifndef _SPARC64_RWSEM_H
   8#define _SPARC64_RWSEM_H
   9
  10#ifndef _LINUX_RWSEM_H
  11#error "please don't include asm/rwsem.h directly, use linux/rwsem.h instead"
  12#endif
  13
  14#ifdef __KERNEL__
  15
  16#define RWSEM_UNLOCKED_VALUE            0x00000000L
  17#define RWSEM_ACTIVE_BIAS               0x00000001L
  18#define RWSEM_ACTIVE_MASK               0xffffffffL
  19#define RWSEM_WAITING_BIAS              (-RWSEM_ACTIVE_MASK-1)
  20#define RWSEM_ACTIVE_READ_BIAS          RWSEM_ACTIVE_BIAS
  21#define RWSEM_ACTIVE_WRITE_BIAS         (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
  22
  23/*
  24 * lock for reading
  25 */
  26static inline void __down_read(struct rw_semaphore *sem)
  27{
  28        if (unlikely(atomic64_inc_return((atomic64_t *)(&sem->count)) <= 0L))
  29                rwsem_down_read_failed(sem);
  30}
  31
  32static inline int __down_read_trylock(struct rw_semaphore *sem)
  33{
  34        long tmp;
  35
  36        while ((tmp = sem->count) >= 0L) {
  37                if (tmp == cmpxchg(&sem->count, tmp,
  38                                   tmp + RWSEM_ACTIVE_READ_BIAS)) {
  39                        return 1;
  40                }
  41        }
  42        return 0;
  43}
  44
  45/*
  46 * lock for writing
  47 */
  48static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
  49{
  50        long tmp;
  51
  52        tmp = atomic64_add_return(RWSEM_ACTIVE_WRITE_BIAS,
  53                                  (atomic64_t *)(&sem->count));
  54        if (unlikely(tmp != RWSEM_ACTIVE_WRITE_BIAS))
  55                rwsem_down_write_failed(sem);
  56}
  57
  58static inline void __down_write(struct rw_semaphore *sem)
  59{
  60        __down_write_nested(sem, 0);
  61}
  62
  63static inline int __down_write_trylock(struct rw_semaphore *sem)
  64{
  65        long tmp;
  66
  67        tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
  68                      RWSEM_ACTIVE_WRITE_BIAS);
  69        return tmp == RWSEM_UNLOCKED_VALUE;
  70}
  71
  72/*
  73 * unlock after reading
  74 */
  75static inline void __up_read(struct rw_semaphore *sem)
  76{
  77        long tmp;
  78
  79        tmp = atomic64_dec_return((atomic64_t *)(&sem->count));
  80        if (unlikely(tmp < -1L && (tmp & RWSEM_ACTIVE_MASK) == 0L))
  81                rwsem_wake(sem);
  82}
  83
  84/*
  85 * unlock after writing
  86 */
  87static inline void __up_write(struct rw_semaphore *sem)
  88{
  89        if (unlikely(atomic64_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
  90                                         (atomic64_t *)(&sem->count)) < 0L))
  91                rwsem_wake(sem);
  92}
  93
  94/*
  95 * implement atomic add functionality
  96 */
  97static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem)
  98{
  99        atomic64_add(delta, (atomic64_t *)(&sem->count));
 100}
 101
 102/*
 103 * downgrade write lock to read lock
 104 */
 105static inline void __downgrade_write(struct rw_semaphore *sem)
 106{
 107        long tmp;
 108
 109        tmp = atomic64_add_return(-RWSEM_WAITING_BIAS, (atomic64_t *)(&sem->count));
 110        if (tmp < 0L)
 111                rwsem_downgrade_wake(sem);
 112}
 113
 114/*
 115 * implement exchange and add functionality
 116 */
 117static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
 118{
 119        return atomic64_add_return(delta, (atomic64_t *)(&sem->count));
 120}
 121
 122#endif /* __KERNEL__ */
 123
 124#endif /* _SPARC64_RWSEM_H */
 125