semaphore.h 3.1 KB

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