semaphore.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #ifndef _ALPHA_SEMAPHORE_H
  2. #define _ALPHA_SEMAPHORE_H
  3. /*
  4. * SMP- and interrupt-safe semaphores..
  5. *
  6. * (C) Copyright 1996 Linus Torvalds
  7. * (C) Copyright 1996, 2000 Richard Henderson
  8. */
  9. #include <asm/current.h>
  10. #include <asm/system.h>
  11. #include <asm/atomic.h>
  12. #include <linux/compiler.h>
  13. #include <linux/wait.h>
  14. #include <linux/rwsem.h>
  15. struct semaphore {
  16. atomic_t count;
  17. wait_queue_head_t wait;
  18. };
  19. #define __SEMAPHORE_INITIALIZER(name, n) \
  20. { \
  21. .count = ATOMIC_INIT(n), \
  22. .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait), \
  23. }
  24. #define __MUTEX_INITIALIZER(name) \
  25. __SEMAPHORE_INITIALIZER(name,1)
  26. #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
  27. struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
  28. #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
  29. #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
  30. static inline void sema_init(struct semaphore *sem, int val)
  31. {
  32. /*
  33. * Logically,
  34. * *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
  35. * except that gcc produces better initializing by parts yet.
  36. */
  37. atomic_set(&sem->count, val);
  38. init_waitqueue_head(&sem->wait);
  39. }
  40. static inline void init_MUTEX (struct semaphore *sem)
  41. {
  42. sema_init(sem, 1);
  43. }
  44. static inline void init_MUTEX_LOCKED (struct semaphore *sem)
  45. {
  46. sema_init(sem, 0);
  47. }
  48. extern void down(struct semaphore *);
  49. extern void __down_failed(struct semaphore *);
  50. extern int down_interruptible(struct semaphore *);
  51. extern int __down_failed_interruptible(struct semaphore *);
  52. extern int down_trylock(struct semaphore *);
  53. extern void up(struct semaphore *);
  54. extern void __up_wakeup(struct semaphore *);
  55. /*
  56. * Hidden out of line code is fun, but extremely messy. Rely on newer
  57. * compilers to do a respectable job with this. The contention cases
  58. * are handled out of line in arch/alpha/kernel/semaphore.c.
  59. */
  60. static inline void __down(struct semaphore *sem)
  61. {
  62. long count;
  63. might_sleep();
  64. count = atomic_dec_return(&sem->count);
  65. if (unlikely(count < 0))
  66. __down_failed(sem);
  67. }
  68. static inline int __down_interruptible(struct semaphore *sem)
  69. {
  70. long count;
  71. might_sleep();
  72. count = atomic_dec_return(&sem->count);
  73. if (unlikely(count < 0))
  74. return __down_failed_interruptible(sem);
  75. return 0;
  76. }
  77. /*
  78. * down_trylock returns 0 on success, 1 if we failed to get the lock.
  79. */
  80. static inline int __down_trylock(struct semaphore *sem)
  81. {
  82. long ret;
  83. /* "Equivalent" C:
  84. do {
  85. ret = ldl_l;
  86. --ret;
  87. if (ret < 0)
  88. break;
  89. ret = stl_c = ret;
  90. } while (ret == 0);
  91. */
  92. __asm__ __volatile__(
  93. "1: ldl_l %0,%1\n"
  94. " subl %0,1,%0\n"
  95. " blt %0,2f\n"
  96. " stl_c %0,%1\n"
  97. " beq %0,3f\n"
  98. " mb\n"
  99. "2:\n"
  100. ".subsection 2\n"
  101. "3: br 1b\n"
  102. ".previous"
  103. : "=&r" (ret), "=m" (sem->count)
  104. : "m" (sem->count));
  105. return ret < 0;
  106. }
  107. static inline void __up(struct semaphore *sem)
  108. {
  109. if (unlikely(atomic_inc_return(&sem->count) <= 0))
  110. __up_wakeup(sem);
  111. }
  112. #if !defined(CONFIG_DEBUG_SEMAPHORE)
  113. extern inline void down(struct semaphore *sem)
  114. {
  115. __down(sem);
  116. }
  117. extern inline int down_interruptible(struct semaphore *sem)
  118. {
  119. return __down_interruptible(sem);
  120. }
  121. extern inline int down_trylock(struct semaphore *sem)
  122. {
  123. return __down_trylock(sem);
  124. }
  125. extern inline void up(struct semaphore *sem)
  126. {
  127. __up(sem);
  128. }
  129. #endif
  130. #endif