wm_wl_timers.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180
  1. #include <string.h>
  2. #include "wm_mem.h"
  3. #include "wm_wl_timers.h"
  4. #include "wm_wl_task.h"
  5. struct tls_timeo {
  6. struct tls_timeo *next;
  7. u32 time;
  8. tls_timeout_handler h;
  9. void *arg;
  10. };
  11. /** The one and only timeout list */
  12. struct tls_timeo *next_timeout[TLS_TIMEO_ALL_COUONT];
  13. /**
  14. * @brief Wait (forever) for a message to arrive in an mbox.
  15. * While waiting, timeouts are processed
  16. *
  17. * @param[in] timeo_assigned timer NO. by assigned
  18. * @param[in] mbox the mbox to fetch the message from
  19. * @param[out] **msg the place to store the message
  20. *
  21. * @return None
  22. *
  23. * @note None
  24. */
  25. void tls_timeouts_mbox_fetch_p(u8 timeo_assigned, tls_mbox_t mbox, void **msg)
  26. {
  27. u32 time_needed;
  28. struct tls_timeo *tmptimeout;
  29. tls_timeout_handler handler;
  30. void *arg;
  31. struct tls_timeo **timeo = &next_timeout[timeo_assigned];
  32. again:
  33. if (!(*timeo)) {
  34. time_needed = tls_arch_mbox_fetch(mbox, msg, 0);
  35. } else {
  36. if ((*timeo)->time > 0) {
  37. time_needed = tls_arch_mbox_fetch(mbox, msg, (*timeo)->time);
  38. } else {
  39. time_needed = SYS_ARCH_TIMEOUT;
  40. }
  41. if (time_needed == SYS_ARCH_TIMEOUT) {
  42. /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
  43. could be fetched. We should now call the timeout handler and
  44. deallocate the memory allocated for the timeout. */
  45. tmptimeout = *timeo;
  46. *timeo = tmptimeout->next;
  47. handler = tmptimeout->h;
  48. arg = tmptimeout->arg;
  49. tls_mem_free(tmptimeout);
  50. if (handler != NULL) {
  51. handler(arg);
  52. }
  53. /* We try again to fetch a message from the mbox. */
  54. goto again;
  55. } else {
  56. /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
  57. occured. The time variable is set to the number of
  58. milliseconds we waited for the message. */
  59. if (time_needed < (*timeo)->time) {
  60. (*timeo)->time -= time_needed;
  61. } else {
  62. (*timeo)->time = 0;
  63. }
  64. }
  65. }
  66. }
  67. /**
  68. * @brief create a one-shot timer (aka timeout)
  69. *
  70. * @param[in] timeo_assigned timer NO. by assigned
  71. * @param[in] msecs time in milliseconds after that the timer should expire
  72. * @param[in] handler callback function that would be called by the timeout
  73. * @param[in] *arg callback argument that would be passed to handler
  74. *
  75. * @return None
  76. *
  77. * @note while waiting for a message using sys_timeouts_mbox_fetch()
  78. */
  79. void tls_timeout_p(u8 timeo_assigned, u32 msecs, tls_timeout_handler handler, void *arg)
  80. {
  81. struct tls_timeo *timeout, *t;
  82. struct tls_timeo **timeo = &next_timeout[timeo_assigned];
  83. timeout = (struct tls_timeo *)tls_mem_alloc(sizeof(struct tls_timeo));
  84. if (timeout == NULL) {
  85. return;
  86. }
  87. timeout->next = NULL;
  88. timeout->h = handler;
  89. timeout->arg = arg;
  90. timeout->time = msecs;
  91. if (*timeo == NULL) {
  92. *timeo = timeout;
  93. return;
  94. }
  95. if ((*timeo)->time > msecs) {
  96. (*timeo)->time -= msecs;
  97. timeout->next = *timeo;
  98. *timeo = timeout;
  99. } else {
  100. for(t = *timeo; t != NULL; t = t->next) {
  101. timeout->time -= t->time;
  102. if (t->next == NULL || t->next->time > timeout->time) {
  103. if (t->next != NULL) {
  104. t->next->time -= timeout->time;
  105. }
  106. timeout->next = t->next;
  107. t->next = timeout;
  108. break;
  109. }
  110. }
  111. }
  112. }
  113. /**
  114. * @brief Go through timeout list (for this task only) and remove the first
  115. * matching entry, even though the timeout has not triggered yet
  116. *
  117. * @param[in] timeo_assigned timer NO. by assigned
  118. * @param[in] handler callback function that would be called by the timeout
  119. * @param[in] *arg callback argument that would be passed to handler
  120. *
  121. * @return None
  122. *
  123. * @note None
  124. */
  125. void tls_untimeout_p(u8 timeo_assigned, tls_timeout_handler handler, void *arg)
  126. {
  127. struct tls_timeo *prev_t, *t;
  128. struct tls_timeo **timeo = &next_timeout[timeo_assigned];
  129. if (*timeo == NULL) {
  130. return;
  131. }
  132. for (t = *timeo, prev_t = NULL; t != NULL; prev_t = t, t = t->next) {
  133. if ((t->h == handler) && (t->arg == arg)) {
  134. /* We have a match */
  135. /* Unlink from previous in list */
  136. if (prev_t == NULL) {
  137. *timeo = t->next;
  138. } else {
  139. prev_t->next = t->next;
  140. }
  141. /* If not the last one, add time of this one back to next */
  142. if (t->next != NULL) {
  143. t->next->time += t->time;
  144. }
  145. tls_mem_free(t);
  146. return;
  147. }
  148. }
  149. return;
  150. }
  151. /**
  152. * @brief timer initialized
  153. *
  154. * @param None
  155. *
  156. * @return None
  157. *
  158. * @note None
  159. */
  160. s8 tls_wl_timer_init(void)
  161. {
  162. memset(next_timeout, 0, sizeof(struct tls_timeo *) * TLS_TIMEO_ALL_COUONT);
  163. return 0;
  164. }