rwsem.h
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:3k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * include/asm-ppc/rwsem.h: R/W semaphores for PPC using the stuff
  3.  * in lib/rwsem.c.  Adapted largely from include/asm-i386/rwsem.h
  4.  * by Paul Mackerras <paulus@samba.org>.
  5.  *
  6.  * This program is free software; you can redistribute it and/or
  7.  * modify it under the terms of the GNU General Public License
  8.  * as published by the Free Software Foundation; either version
  9.  * 2 of the License, or (at your option) any later version.
  10.  */
  11. #ifndef _PPC64_RWSEM_H
  12. #define _PPC64_RWSEM_H
  13. #ifdef __KERNEL__
  14. #include <linux/list.h>
  15. #include <linux/spinlock.h>
  16. #include <asm/atomic.h>
  17. #include <asm/system.h>
  18. /*
  19.  * the semaphore definition
  20.  */
  21. struct rw_semaphore {
  22. /* XXX this should be able to be an atomic_t  -- paulus */
  23. signed int count;
  24. #define RWSEM_UNLOCKED_VALUE 0x00000000
  25. #define RWSEM_ACTIVE_BIAS 0x00000001
  26. #define RWSEM_ACTIVE_MASK 0x0000ffff
  27. #define RWSEM_WAITING_BIAS (-0x00010000)
  28. #define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
  29. #define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
  30. spinlock_t wait_lock;
  31. struct list_head wait_list;
  32. #if RWSEM_DEBUG
  33. int debug;
  34. #endif
  35. };
  36. /*
  37.  * initialisation
  38.  */
  39. #if RWSEM_DEBUG
  40. #define __RWSEM_DEBUG_INIT      , 0
  41. #else
  42. #define __RWSEM_DEBUG_INIT /* */
  43. #endif
  44. #define __RWSEM_INITIALIZER(name) 
  45. { RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, 
  46.   LIST_HEAD_INIT((name).wait_list) 
  47.   __RWSEM_DEBUG_INIT }
  48. #define DECLARE_RWSEM(name)
  49. struct rw_semaphore name = __RWSEM_INITIALIZER(name)
  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. static inline void init_rwsem(struct rw_semaphore *sem)
  54. {
  55. sem->count = RWSEM_UNLOCKED_VALUE;
  56. spin_lock_init(&sem->wait_lock);
  57. INIT_LIST_HEAD(&sem->wait_list);
  58. #if RWSEM_DEBUG
  59. sem->debug = 0;
  60. #endif
  61. }
  62. /*
  63.  * lock for reading
  64.  */
  65. static inline void __down_read(struct rw_semaphore *sem)
  66. {
  67. if (atomic_inc_return((atomic_t *)(&sem->count)) >= 0)
  68. smp_wmb();
  69. else
  70. rwsem_down_read_failed(sem);
  71. }
  72. /*
  73.  * lock for writing
  74.  */
  75. static inline void __down_write(struct rw_semaphore *sem)
  76. {
  77. int tmp;
  78. tmp = atomic_add_return(RWSEM_ACTIVE_WRITE_BIAS,
  79. (atomic_t *)(&sem->count));
  80. if (tmp == RWSEM_ACTIVE_WRITE_BIAS)
  81. smp_wmb();
  82. else
  83. rwsem_down_write_failed(sem);
  84. }
  85. /*
  86.  * unlock after reading
  87.  */
  88. static inline void __up_read(struct rw_semaphore *sem)
  89. {
  90. int tmp;
  91. smp_wmb();
  92. tmp = atomic_dec_return((atomic_t *)(&sem->count));
  93. if (tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0)
  94. rwsem_wake(sem);
  95. }
  96. /*
  97.  * unlock after writing
  98.  */
  99. static inline void __up_write(struct rw_semaphore *sem)
  100. {
  101. smp_wmb();
  102. if (atomic_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
  103.       (atomic_t *)(&sem->count)) < 0)
  104. rwsem_wake(sem);
  105. }
  106. /*
  107.  * implement atomic add functionality
  108.  */
  109. static inline void rwsem_atomic_add(int delta, struct rw_semaphore *sem)
  110. {
  111. atomic_add(delta, (atomic_t *)(&sem->count));
  112. }
  113. /*
  114.  * implement exchange and add functionality
  115.  */
  116. static inline int rwsem_atomic_update(int delta, struct rw_semaphore *sem)
  117. {
  118. smp_mb();
  119. return atomic_add_return(delta, (atomic_t *)(&sem->count));
  120. }
  121. #endif /* __KERNEL__ */
  122. #endif /* _PPC_RWSEM_XADD_H */