rwsem.h 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /* rwsem.h: R/W semaphores, public interface
  2. *
  3. * Written by David Howells (dhowells@redhat.com).
  4. * Derived from asm-i386/semaphore.h
  5. */
  6. #ifndef _LINUX_RWSEM_H
  7. #define _LINUX_RWSEM_H
  8. #include <linux/linkage.h>
  9. #include <linux/types.h>
  10. #include <linux/kernel.h>
  11. #include <linux/list.h>
  12. #include <linux/spinlock.h>
  13. #include <linux/atomic.h>
  14. struct rw_semaphore;
  15. #ifdef CONFIG_RWSEM_GENERIC_SPINLOCK
  16. #include <linux/rwsem-spinlock.h> /* use a generic implementation */
  17. #else
  18. /* All arch specific implementations share the same struct */
  19. struct rw_semaphore {
  20. long count;
  21. raw_spinlock_t wait_lock;
  22. struct list_head wait_list;
  23. #ifdef CONFIG_DEBUG_LOCK_ALLOC
  24. struct lockdep_map dep_map;
  25. #endif
  26. };
  27. extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
  28. extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
  29. extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *);
  30. extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
  31. /* Include the arch specific part */
  32. #include <asm/rwsem.h>
  33. /* In all implementations count != 0 means locked */
  34. static inline int rwsem_is_locked(struct rw_semaphore *sem)
  35. {
  36. return sem->count != 0;
  37. }
  38. #endif
  39. /* Common initializer macros and functions */
  40. #ifdef CONFIG_DEBUG_LOCK_ALLOC
  41. # define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
  42. #else
  43. # define __RWSEM_DEP_MAP_INIT(lockname)
  44. #endif
  45. #define __RWSEM_INITIALIZER(name) \
  46. { RWSEM_UNLOCKED_VALUE, \
  47. __RAW_SPIN_LOCK_UNLOCKED(name.wait_lock), \
  48. LIST_HEAD_INIT((name).wait_list) \
  49. __RWSEM_DEP_MAP_INIT(name) }
  50. #define DECLARE_RWSEM(name) \
  51. struct rw_semaphore name = __RWSEM_INITIALIZER(name)
  52. extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
  53. struct lock_class_key *key);
  54. #define init_rwsem(sem) \
  55. do { \
  56. static struct lock_class_key __key; \
  57. \
  58. __init_rwsem((sem), #sem, &__key); \
  59. } while (0)
  60. /*
  61. * lock for reading
  62. */
  63. extern void down_read(struct rw_semaphore *sem);
  64. /*
  65. * trylock for reading -- returns 1 if successful, 0 if contention
  66. */
  67. extern int down_read_trylock(struct rw_semaphore *sem);
  68. /*
  69. * lock for writing
  70. */
  71. extern void down_write(struct rw_semaphore *sem);
  72. /*
  73. * trylock for writing -- returns 1 if successful, 0 if contention
  74. */
  75. extern int down_write_trylock(struct rw_semaphore *sem);
  76. /*
  77. * release a read lock
  78. */
  79. extern void up_read(struct rw_semaphore *sem);
  80. /*
  81. * release a write lock
  82. */
  83. extern void up_write(struct rw_semaphore *sem);
  84. /*
  85. * downgrade write lock to read lock
  86. */
  87. extern void downgrade_write(struct rw_semaphore *sem);
  88. #ifdef CONFIG_DEBUG_LOCK_ALLOC
  89. /*
  90. * nested locking. NOTE: rwsems are not allowed to recurse
  91. * (which occurs if the same task tries to acquire the same
  92. * lock instance multiple times), but multiple locks of the
  93. * same lock class might be taken, if the order of the locks
  94. * is always the same. This ordering rule can be expressed
  95. * to lockdep via the _nested() APIs, but enumerating the
  96. * subclasses that are used. (If the nesting relationship is
  97. * static then another method for expressing nested locking is
  98. * the explicit definition of lock class keys and the use of
  99. * lockdep_set_class() at lock initialization time.
  100. * See Documentation/lockdep-design.txt for more details.)
  101. */
  102. extern void down_read_nested(struct rw_semaphore *sem, int subclass);
  103. extern void down_write_nested(struct rw_semaphore *sem, int subclass);
  104. #else
  105. # define down_read_nested(sem, subclass) down_read(sem)
  106. # define down_write_nested(sem, subclass) down_write(sem)
  107. #endif
  108. #endif /* _LINUX_RWSEM_H */