semaphore.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. /* $Id: semaphore.h,v 1.3 2001/05/08 13:54:09 bjornw Exp $ */
  2. /* On the i386 these are coded in asm, perhaps we should as well. Later.. */
  3. #ifndef _CRIS_SEMAPHORE_H
  4. #define _CRIS_SEMAPHORE_H
  5. #define RW_LOCK_BIAS 0x01000000
  6. #include <linux/wait.h>
  7. #include <linux/spinlock.h>
  8. #include <linux/rwsem.h>
  9. #include <asm/system.h>
  10. #include <asm/atomic.h>
  11. /*
  12. * CRIS semaphores, implemented in C-only so far.
  13. */
  14. int printk(const char *fmt, ...);
  15. struct semaphore {
  16. atomic_t count;
  17. atomic_t waking;
  18. wait_queue_head_t wait;
  19. };
  20. #define __SEMAPHORE_INITIALIZER(name, n) \
  21. { \
  22. .count = ATOMIC_INIT(n), \
  23. .waking = ATOMIC_INIT(0), \
  24. .wait = __WAIT_QUEUE_HEAD_INITIALIZER((name).wait) \
  25. }
  26. #define __MUTEX_INITIALIZER(name) \
  27. __SEMAPHORE_INITIALIZER(name,1)
  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. extern inline void sema_init(struct semaphore *sem, int val)
  33. {
  34. *sem = (struct semaphore)__SEMAPHORE_INITIALIZER((*sem),val);
  35. }
  36. extern inline void init_MUTEX (struct semaphore *sem)
  37. {
  38. sema_init(sem, 1);
  39. }
  40. extern inline void init_MUTEX_LOCKED (struct semaphore *sem)
  41. {
  42. sema_init(sem, 0);
  43. }
  44. extern void __down(struct semaphore * sem);
  45. extern int __down_interruptible(struct semaphore * sem);
  46. extern int __down_trylock(struct semaphore * sem);
  47. extern void __up(struct semaphore * sem);
  48. /* notice - we probably can do cli/sti here instead of saving */
  49. extern inline void down(struct semaphore * sem)
  50. {
  51. unsigned long flags;
  52. int failed;
  53. might_sleep();
  54. /* atomically decrement the semaphores count, and if its negative, we wait */
  55. local_save_flags(flags);
  56. local_irq_disable();
  57. failed = --(sem->count.counter) < 0;
  58. local_irq_restore(flags);
  59. if(failed) {
  60. __down(sem);
  61. }
  62. }
  63. /*
  64. * This version waits in interruptible state so that the waiting
  65. * process can be killed. The down_interruptible routine
  66. * returns negative for signalled and zero for semaphore acquired.
  67. */
  68. extern inline int down_interruptible(struct semaphore * sem)
  69. {
  70. unsigned long flags;
  71. int failed;
  72. might_sleep();
  73. /* atomically decrement the semaphores count, and if its negative, we wait */
  74. local_save_flags(flags);
  75. local_irq_disable();
  76. failed = --(sem->count.counter) < 0;
  77. local_irq_restore(flags);
  78. if(failed)
  79. failed = __down_interruptible(sem);
  80. return(failed);
  81. }
  82. extern inline int down_trylock(struct semaphore * sem)
  83. {
  84. unsigned long flags;
  85. int failed;
  86. local_save_flags(flags);
  87. local_irq_disable();
  88. failed = --(sem->count.counter) < 0;
  89. local_irq_restore(flags);
  90. if(failed)
  91. failed = __down_trylock(sem);
  92. return(failed);
  93. }
  94. /*
  95. * Note! This is subtle. We jump to wake people up only if
  96. * the semaphore was negative (== somebody was waiting on it).
  97. * The default case (no contention) will result in NO
  98. * jumps for both down() and up().
  99. */
  100. extern inline void up(struct semaphore * sem)
  101. {
  102. unsigned long flags;
  103. int wakeup;
  104. /* atomically increment the semaphores count, and if it was negative, we wake people */
  105. local_save_flags(flags);
  106. local_irq_disable();
  107. wakeup = ++(sem->count.counter) <= 0;
  108. local_irq_restore(flags);
  109. if(wakeup) {
  110. __up(sem);
  111. }
  112. }
  113. #endif