semaphore.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. #ifndef _ASM_M32R_SEMAPHORE_H
  2. #define _ASM_M32R_SEMAPHORE_H
  3. #include <linux/linkage.h>
  4. #ifdef __KERNEL__
  5. /*
  6. * SMP- and interrupt-safe semaphores..
  7. *
  8. * Copyright (C) 1996 Linus Torvalds
  9. * Copyright (C) 2004 Hirokazu Takata <takata at linux-m32r.org>
  10. */
  11. #include <linux/config.h>
  12. #include <linux/wait.h>
  13. #include <linux/rwsem.h>
  14. #include <asm/assembler.h>
  15. #include <asm/system.h>
  16. #include <asm/atomic.h>
  17. struct semaphore {
  18. atomic_t count;
  19. int sleepers;
  20. wait_queue_head_t wait;
  21. };
  22. #define __SEMAPHORE_INITIALIZER(name, n) \
  23. { \
  24. .count = ATOMIC_INIT(n), \
  25. .sleepers = 0, \
  26. .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
  27. }
  28. #define __DECLARE_SEMAPHORE_GENERIC(name,count) \
  29. struct semaphore name = __SEMAPHORE_INITIALIZER(name,count)
  30. #define DECLARE_MUTEX(name) __DECLARE_SEMAPHORE_GENERIC(name,1)
  31. #define DECLARE_MUTEX_LOCKED(name) __DECLARE_SEMAPHORE_GENERIC(name,0)
  32. static inline void sema_init (struct semaphore *sem, int val)
  33. {
  34. /*
  35. * *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
  36. *
  37. * i'd rather use the more flexible initialization above, but sadly
  38. * GCC 2.7.2.3 emits a bogus warning. EGCS doesnt. Oh well.
  39. */
  40. atomic_set(&sem->count, val);
  41. sem->sleepers = 0;
  42. init_waitqueue_head(&sem->wait);
  43. }
  44. static inline void init_MUTEX (struct semaphore *sem)
  45. {
  46. sema_init(sem, 1);
  47. }
  48. static inline void init_MUTEX_LOCKED (struct semaphore *sem)
  49. {
  50. sema_init(sem, 0);
  51. }
  52. asmlinkage void __down_failed(void /* special register calling convention */);
  53. asmlinkage int __down_failed_interruptible(void /* params in registers */);
  54. asmlinkage int __down_failed_trylock(void /* params in registers */);
  55. asmlinkage void __up_wakeup(void /* special register calling convention */);
  56. asmlinkage void __down(struct semaphore * sem);
  57. asmlinkage int __down_interruptible(struct semaphore * sem);
  58. asmlinkage int __down_trylock(struct semaphore * sem);
  59. asmlinkage void __up(struct semaphore * sem);
  60. /*
  61. * Atomically decrement the semaphore's count. If it goes negative,
  62. * block the calling thread in the TASK_UNINTERRUPTIBLE state.
  63. */
  64. static inline void down(struct semaphore * sem)
  65. {
  66. unsigned long flags;
  67. long count;
  68. might_sleep();
  69. local_irq_save(flags);
  70. __asm__ __volatile__ (
  71. "# down \n\t"
  72. DCACHE_CLEAR("%0", "r4", "%1")
  73. M32R_LOCK" %0, @%1; \n\t"
  74. "addi %0, #-1; \n\t"
  75. M32R_UNLOCK" %0, @%1; \n\t"
  76. : "=&r" (count)
  77. : "r" (&sem->count)
  78. : "memory"
  79. #ifdef CONFIG_CHIP_M32700_TS1
  80. , "r4"
  81. #endif /* CONFIG_CHIP_M32700_TS1 */
  82. );
  83. local_irq_restore(flags);
  84. if (unlikely(count < 0))
  85. __down(sem);
  86. }
  87. /*
  88. * Interruptible try to acquire a semaphore. If we obtained
  89. * it, return zero. If we were interrupted, returns -EINTR
  90. */
  91. static inline int down_interruptible(struct semaphore * sem)
  92. {
  93. unsigned long flags;
  94. long count;
  95. int result = 0;
  96. might_sleep();
  97. local_irq_save(flags);
  98. __asm__ __volatile__ (
  99. "# down_interruptible \n\t"
  100. DCACHE_CLEAR("%0", "r4", "%1")
  101. M32R_LOCK" %0, @%1; \n\t"
  102. "addi %0, #-1; \n\t"
  103. M32R_UNLOCK" %0, @%1; \n\t"
  104. : "=&r" (count)
  105. : "r" (&sem->count)
  106. : "memory"
  107. #ifdef CONFIG_CHIP_M32700_TS1
  108. , "r4"
  109. #endif /* CONFIG_CHIP_M32700_TS1 */
  110. );
  111. local_irq_restore(flags);
  112. if (unlikely(count < 0))
  113. result = __down_interruptible(sem);
  114. return result;
  115. }
  116. /*
  117. * Non-blockingly attempt to down() a semaphore.
  118. * Returns zero if we acquired it
  119. */
  120. static inline int down_trylock(struct semaphore * sem)
  121. {
  122. unsigned long flags;
  123. long count;
  124. int result = 0;
  125. local_irq_save(flags);
  126. __asm__ __volatile__ (
  127. "# down_trylock \n\t"
  128. DCACHE_CLEAR("%0", "r4", "%1")
  129. M32R_LOCK" %0, @%1; \n\t"
  130. "addi %0, #-1; \n\t"
  131. M32R_UNLOCK" %0, @%1; \n\t"
  132. : "=&r" (count)
  133. : "r" (&sem->count)
  134. : "memory"
  135. #ifdef CONFIG_CHIP_M32700_TS1
  136. , "r4"
  137. #endif /* CONFIG_CHIP_M32700_TS1 */
  138. );
  139. local_irq_restore(flags);
  140. if (unlikely(count < 0))
  141. result = __down_trylock(sem);
  142. return result;
  143. }
  144. /*
  145. * Note! This is subtle. We jump to wake people up only if
  146. * the semaphore was negative (== somebody was waiting on it).
  147. * The default case (no contention) will result in NO
  148. * jumps for both down() and up().
  149. */
  150. static inline void up(struct semaphore * sem)
  151. {
  152. unsigned long flags;
  153. long count;
  154. local_irq_save(flags);
  155. __asm__ __volatile__ (
  156. "# up \n\t"
  157. DCACHE_CLEAR("%0", "r4", "%1")
  158. M32R_LOCK" %0, @%1; \n\t"
  159. "addi %0, #1; \n\t"
  160. M32R_UNLOCK" %0, @%1; \n\t"
  161. : "=&r" (count)
  162. : "r" (&sem->count)
  163. : "memory"
  164. #ifdef CONFIG_CHIP_M32700_TS1
  165. , "r4"
  166. #endif /* CONFIG_CHIP_M32700_TS1 */
  167. );
  168. local_irq_restore(flags);
  169. if (unlikely(count <= 0))
  170. __up(sem);
  171. }
  172. #endif /* __KERNEL__ */
  173. #endif /* _ASM_M32R_SEMAPHORE_H */