condition.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /*
  2. * Copyright (C) 2008 by EmbeddedIT,
  3. * Ole Reinhardt <ole.reinhardt@embedded-it.de> All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * 2. Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * 3. Neither the name of the copyright holders nor the names of
  15. * contributors may be used to endorse or promote products derived
  16. * from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY EMBEDDED IT AND CONTRIBUTORS
  19. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  20. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  21. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EMBEDDED IT
  22. * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  23. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  24. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  25. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  26. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  27. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  28. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  29. *
  30. * For additional information see http://www.ethernut.de/
  31. *
  32. */
  33. /*
  34. * $Log$
  35. * Revision 1.3 2008/08/11 07:00:33 haraldkipp
  36. * BSD types replaced by stdint types (feature request #1282721).
  37. *
  38. * Revision 1.2 2008/04/29 01:51:35 thiagocorrea
  39. * Compile fix
  40. *
  41. * Revision 1.1 2008/04/21 22:24:53 olereinhardt
  42. * Implemented condition variables to use with NutOS as an application candy
  43. *
  44. */
  45. #include <sys/heap.h>
  46. #include <sys/event.h>
  47. #include <sys/atom.h>
  48. #include <sys/timer.h>
  49. #include <sys/thread.h>
  50. #include <sys/condition.h>
  51. #include <stddef.h> /* NULL definition */
  52. /*!
  53. * \addtogroup xgConditionVariables
  54. */
  55. /*@{*/
  56. /*!
  57. * \brief Creates a new condition variable
  58. *
  59. * \return Handle of the condition variable, NULL if not enough memory available
  60. */
  61. int NutConditionInit( CONDITION * cond)
  62. {
  63. cond = NutHeapAlloc(sizeof(struct _CONDITION));
  64. if (cond == NULL) return 1;
  65. NutMutexInit(&cond->mutex);
  66. return 0;
  67. }
  68. /*!
  69. * \brief Locks the condition mutex
  70. *
  71. * To avoid the "lost wakeup" bug it is important to always lock the condition before
  72. * modifying the condition or signalling the condition variable
  73. *
  74. * \param cond The condition to be locked
  75. *
  76. */
  77. void NutConditionLock(CONDITION * cond)
  78. {
  79. if (cond == NULL) return;
  80. NutMutexLock(&cond->mutex);
  81. }
  82. /*!
  83. * \brief Unocks the condition mutex
  84. *
  85. * Always unlock the confition after modifying the condition and signalling the
  86. * condition variable.
  87. *
  88. * \param cond The condition to be unlocked
  89. *
  90. */
  91. void NutConditionUnlock(CONDITION * cond)
  92. {
  93. if (cond == NULL) return;
  94. NutMutexUnlock(&cond->mutex);
  95. }
  96. /*!
  97. * \brief Waits until this thread is woken up on cond.
  98. *
  99. * The condition is unlocked before falling asleep and locked again before resuming.
  100. *
  101. * It is important to use the NutConditionWait() and NutConditionTimedWait()
  102. * functions only inside a loop which checks for the condition to be true.
  103. * It is not guaranteed that the waiting thread will find the condition
  104. * fulfilled after it wakes up, even if the signaling thread left the condition
  105. * in that state: another thread may have altered the condition before the
  106. * waiting thread got the chance to be woken up, even if the condition itself
  107. * is protected by locking with NutConditionLock.
  108. *
  109. * Always lock the condition before entering the above mentioned check loop
  110. * and always unlock the condition after successfully leaving the loop and
  111. * processing the data you wait for.
  112. *
  113. * \param cond The condition to wait on.
  114. *
  115. * \return 0 on success, -1 on error
  116. *
  117. */
  118. int NutConditionWait(CONDITION * cond)
  119. {
  120. if (cond == NULL) return -1;
  121. NutMutexUnlock(&cond->mutex);
  122. NutEventWait(cond->event, NUT_WAIT_INFINITE);
  123. NutMutexLock(&cond->mutex);
  124. return 0;
  125. }
  126. /*!
  127. * \brief Waits until this thread is woken up on cond but not longer than until
  128. * the time specified by abs_ms.
  129. *
  130. * The condition is unlocked before falling asleep and locked again before resuming.
  131. *
  132. * It is important to use the NutConditionWait() and NutConditionTimedWait()
  133. * functions only inside a loop which checks for the condition to be true.
  134. * It is not guaranteed that the waiting thread will find the condition
  135. * fulfilled after it wakes up, even if the signaling thread left the condition
  136. * in that state: another thread may have altered the condition before the
  137. * waiting thread got the chance to be woken up, even if the condition itself
  138. * is protected by locking with NutConditionLock.
  139. *
  140. * Always lock the condition before entering the above mentioned check loop
  141. * and always unlock the condition after successfully leaving the loop and
  142. * processing the data you wait for.
  143. *
  144. * \param cond The condition to wait on.
  145. * \param abs_ms Absolute time in ms to longest wait for. Use NutGetMillis() to
  146. * obtain the current time and add your desired offset. Overflows are
  147. * handled correct. At longest you can wait 2147483648ms
  148. *
  149. * \return 0 on success, -1 on error or timeout
  150. *
  151. *
  152. */
  153. int NutConditionTimedWait(CONDITION * cond, uint32_t abs_ms)
  154. {
  155. uint32_t ms;
  156. if (cond == NULL) return -1;
  157. ms = abs_ms - NutGetMillis();
  158. if (ms > 0x7FFFFFFF) return -1;
  159. NutMutexUnlock(&cond->mutex);
  160. NutEventWait(&cond->event, ms);
  161. NutMutexLock(&cond->mutex);
  162. return 0;
  163. }
  164. /*!
  165. * \brief If threads are waiting for cond, exactly one of them is woken up.
  166. *
  167. * Call this function after you fullfilled the condition. The conditon should be
  168. * locked befor fulfilling the condition should not be unlocked before calling
  169. * this function.
  170. *
  171. * \param cond The condition to signal
  172. * \return -1 on error. Otherwise the number of woken up threads.
  173. *
  174. */
  175. int NutConditionSignal(CONDITION * cond)
  176. {
  177. if (cond == NULL) return -1;
  178. return NutEventPost(&cond->event);
  179. }
  180. /*!
  181. * \brief If threads are waiting for cond, all of them are woken up.
  182. *
  183. * Call this function after you fullfilled the condition. The conditon should be
  184. * locked befor fulfilling the condition should not be unlocked before calling
  185. * this function.
  186. *
  187. * \param cond The condition to signal
  188. * \return -1 on error. Otherwise the number of woken up threads.
  189. *
  190. */
  191. int NutConditionBroadcast(CONDITION * cond)
  192. {
  193. if (cond == NULL) return -1;
  194. return NutEventBroadcast(&cond->event);
  195. }
  196. /*!
  197. * \brief Free the ressources used by this condition variable
  198. *
  199. * \param cond Pointer to the condition
  200. */
  201. void NutConditionFree(CONDITION * cond)
  202. {
  203. NutMutexDestroy(&cond->mutex);
  204. NutHeapFree(cond);
  205. cond = NULL;
  206. }
  207. /*@}*/