semaphore-helper.h
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:3k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /*
  2.  * SMP- and interrupt-safe semaphores helper functions.
  3.  *
  4.  * (C) Copyright 1996 Linus Torvalds
  5.  * (C) Copyright 1999 Andrea Arcangeli
  6.  * (C) Copyright 1999, 2001 Ralf Baechle
  7.  * (C) Copyright 1999, 2001 Silicon Graphics, Inc.
  8.  */
  9. #ifndef _ASM_SEMAPHORE_HELPER_H
  10. #define _ASM_SEMAPHORE_HELPER_H
  11. /*
  12.  * These two _must_ execute atomically wrt each other.
  13.  */
  14. static inline void wake_one_more(struct semaphore * sem)
  15. {
  16. atomic_inc(&sem->waking);
  17. }
  18. static inline int waking_non_zero(struct semaphore *sem)
  19. {
  20. int ret, tmp;
  21. __asm__ __volatile__(
  22. "1:tllt%1, %2ttt# waking_non_zeront"
  23. "blezt%1, 2fnt"
  24. "subut%0, %1, 1nt"
  25. "sct%0, %2nt"
  26. "beqzt%0, 1bn"
  27. "2:"
  28. : "=r" (ret), "=r" (tmp), "+m" (sem->waking)
  29. : "0" (0));
  30. return ret;
  31. }
  32. /*
  33.  * waking_non_zero_interruptible:
  34.  * 1 got the lock
  35.  * 0 go to sleep
  36.  * -EINTR interrupted
  37.  *
  38.  * We must undo the sem->count down_interruptible decrement
  39.  * simultaneously and atomically with the sem->waking adjustment,
  40.  * otherwise we can race with wake_one_more.
  41.  *
  42.  * This is accomplished by doing a 64-bit lld/scd on the 2 32-bit words.
  43.  *
  44.  * Pseudocode:
  45.  *
  46.  * If(sem->waking > 0) {
  47.  * Decrement(sem->waking)
  48.  * Return(SUCCESS)
  49.  * } else If(signal_pending(tsk)) {
  50.  * Increment(sem->count)
  51.  * Return(-EINTR)
  52.  * } else {
  53.  * Return(SLEEP)
  54.  * }
  55.  */
  56. static inline int
  57. waking_non_zero_interruptible(struct semaphore *sem, struct task_struct *tsk)
  58. {
  59. long ret, tmp;
  60. #ifdef __MIPSEB__
  61.         __asm__ __volatile__(
  62. ".settpushttt# waking_non_zero_interruptiblent"
  63. ".settnoatnt"
  64. "0:tlldt%1, %2nt"
  65. "lit%0, 0nt"
  66. "sllt$1, %1, 0nt"
  67. "blezt$1, 1fnt"
  68. "daddiut%1, %1, -1nt"
  69. "lit%0, 1nt"
  70. "bt2fnt"
  71. "1:tbeqzt%3, 2fnt"
  72. "lit%0, %4nt"
  73. "dlit$1, 0x0000000100000000nt"
  74. "daddut%1, %1, $1nt"
  75. "2:tscdt%1, %2nt"
  76. "beqzt%1, 0bnt"
  77. ".settpop"
  78. : "=&r" (ret), "=&r" (tmp), "=m" (*sem)
  79. : "r" (signal_pending(tsk)), "i" (-EINTR));
  80. #elif defined(__MIPSEL__)
  81. __asm__ __volatile__(
  82. ".settpushttt# waking_non_zero_interruptiblent"
  83. ".sett noatn"
  84. "0:tlldt%1, %2nt"
  85. "lit%0, 0nt"
  86. "blezt%1, 1fnt"
  87. "dlit$1, 0x0000000100000000nt"
  88. "dsubut%1, %1, $1nt"
  89. "lit%0, 1nt"
  90. "bt2fn"
  91. "1:tbeqzt%3, 2fnt"
  92. "lit%0, %4nt"
  93. /*
  94.  * It would be nice to assume that sem->count
  95.  * is != -1, but we will guard against that case
  96.  */
  97. "daddiut$1, %1, 1nt"
  98. "dsll32t$1, $1, 0nt"
  99. "dsrl32t$1, $1, 0nt"
  100. "dsrl32t%1, %1, 0nt"
  101. "dsll32t%1, %1, 0nt"
  102. "ort%1, %1, $1n"
  103. "2:tscdt%1, %2nt"
  104. "beqzt %1, 0bnt"
  105. ".settpop"
  106. : "=&r" (ret), "=&r" (tmp), "=m" (*sem)
  107. : "r" (signal_pending(tsk)), "i" (-EINTR));
  108. #endif
  109. return ret;
  110. }
  111. /*
  112.  * waking_non_zero_trylock is unused.  we do everything in
  113.  * down_trylock and let non-ll/sc hosts bounce around.
  114.  */
  115. static inline int waking_non_zero_trylock(struct semaphore *sem)
  116. {
  117. #if WAITQUEUE_DEBUG
  118. CHECK_MAGIC(sem->__magic);
  119. #endif
  120. return 0;
  121. }
  122. #endif /* _ASM_SEMAPHORE_HELPER_H */