home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2006 November (DVD) / PCWELT_11_2006.ISO / casper / filesystem.squashfs / usr / src / linux-headers-2.6.17-6 / include / asm-sh / rwsem.h < prev    next >
Encoding:
C/C++ Source or Header  |  2006-08-11  |  3.6 KB  |  176 lines

  1. /*
  2.  * include/asm-ppc/rwsem.h: R/W semaphores for SH using the stuff
  3.  * in lib/rwsem.c.
  4.  */
  5.  
  6. #ifndef _ASM_SH_RWSEM_H
  7. #define _ASM_SH_RWSEM_H
  8.  
  9. #ifdef __KERNEL__
  10. #include <linux/list.h>
  11. #include <linux/spinlock.h>
  12. #include <asm/atomic.h>
  13. #include <asm/system.h>
  14.  
  15. /*
  16.  * the semaphore definition
  17.  */
  18. struct rw_semaphore {
  19.     long        count;
  20. #define RWSEM_UNLOCKED_VALUE        0x00000000
  21. #define RWSEM_ACTIVE_BIAS        0x00000001
  22. #define RWSEM_ACTIVE_MASK        0x0000ffff
  23. #define RWSEM_WAITING_BIAS        (-0x00010000)
  24. #define RWSEM_ACTIVE_READ_BIAS        RWSEM_ACTIVE_BIAS
  25. #define RWSEM_ACTIVE_WRITE_BIAS        (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
  26.     spinlock_t        wait_lock;
  27.     struct list_head    wait_list;
  28. #if RWSEM_DEBUG
  29.     int            debug;
  30. #endif
  31. };
  32.  
  33. /*
  34.  * initialisation
  35.  */
  36. #if RWSEM_DEBUG
  37. #define __RWSEM_DEBUG_INIT      , 0
  38. #else
  39. #define __RWSEM_DEBUG_INIT    /* */
  40. #endif
  41.  
  42. #define __RWSEM_INITIALIZER(name) \
  43.     { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
  44.       LIST_HEAD_INIT((name).wait_list) \
  45.       __RWSEM_DEBUG_INIT }
  46.  
  47. #define DECLARE_RWSEM(name)        \
  48.     struct rw_semaphore name = __RWSEM_INITIALIZER(name)
  49.  
  50. extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
  51. extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
  52. extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
  53. extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
  54.  
  55. static inline void init_rwsem(struct rw_semaphore *sem)
  56. {
  57.     sem->count = RWSEM_UNLOCKED_VALUE;
  58.     spin_lock_init(&sem->wait_lock);
  59.     INIT_LIST_HEAD(&sem->wait_list);
  60. #if RWSEM_DEBUG
  61.     sem->debug = 0;
  62. #endif
  63. }
  64.  
  65. /*
  66.  * lock for reading
  67.  */
  68. static inline void __down_read(struct rw_semaphore *sem)
  69. {
  70.     if (atomic_inc_return((atomic_t *)(&sem->count)) > 0)
  71.         smp_wmb();
  72.     else
  73.         rwsem_down_read_failed(sem);
  74. }
  75.  
  76. static inline int __down_read_trylock(struct rw_semaphore *sem)
  77. {
  78.     int tmp;
  79.  
  80.     while ((tmp = sem->count) >= 0) {
  81.         if (tmp == cmpxchg(&sem->count, tmp,
  82.                    tmp + RWSEM_ACTIVE_READ_BIAS)) {
  83.             smp_wmb();
  84.             return 1;
  85.         }
  86.     }
  87.     return 0;
  88. }
  89.  
  90. /*
  91.  * lock for writing
  92.  */
  93. static inline void __down_write(struct rw_semaphore *sem)
  94. {
  95.     int tmp;
  96.  
  97.     tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS,
  98.                 (atomic_t *)(&sem->count));
  99.     if (tmp == RWSEM_ACTIVE_WRITE_BIAS)
  100.         smp_wmb();
  101.     else
  102.         rwsem_down_write_failed(sem);
  103. }
  104.  
  105. static inline int __down_write_trylock(struct rw_semaphore *sem)
  106. {
  107.     int tmp;
  108.  
  109.     tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
  110.               RWSEM_ACTIVE_WRITE_BIAS);
  111.     smp_wmb();
  112.     return tmp == RWSEM_UNLOCKED_VALUE;
  113. }
  114.  
  115. /*
  116.  * unlock after reading
  117.  */
  118. static inline void __up_read(struct rw_semaphore *sem)
  119. {
  120.     int tmp;
  121.  
  122.     smp_wmb();
  123.     tmp = atomic_dec_return((atomic_t *)(&sem->count));
  124.     if (tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0)
  125.         rwsem_wake(sem);
  126. }
  127.  
  128. /*
  129.  * unlock after writing
  130.  */
  131. static inline void __up_write(struct rw_semaphore *sem)
  132. {
  133.     smp_wmb();
  134.     if (atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
  135.                   (atomic_t *)(&sem->count)) < 0)
  136.         rwsem_wake(sem);
  137. }
  138.  
  139. /*
  140.  * implement atomic add functionality
  141.  */
  142. static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
  143. {
  144.     atomic_add(delta, (atomic_t *)(&sem->count));
  145. }
  146.  
  147. /*
  148.  * downgrade write lock to read lock
  149.  */
  150. static inline void __downgrade_write(struct rw_semaphore *sem)
  151. {
  152.     int tmp;
  153.  
  154.     smp_wmb();
  155.     tmp = atomic_add_return(-RWSEM_WAITING_BIAS, (atomic_t *)(&sem->count));
  156.     if (tmp < 0)
  157.         rwsem_downgrade_wake(sem);
  158. }
  159.  
  160. /*
  161.  * implement exchange and add functionality
  162.  */
  163. static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
  164. {
  165.     smp_mb();
  166.     return atomic_add_return(delta, (atomic_t *)(&sem->count));
  167. }
  168.  
  169. static inline int rwsem_is_locked(struct rw_semaphore *sem)
  170. {
  171.     return (sem->count != 0);
  172. }
  173.  
  174. #endif /* __KERNEL__ */
  175. #endif /* _ASM_SH_RWSEM_H */
  176.