time_event_manager.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. #include "time_event_manager.h"
  2. #include "../../mem/mem.h"
  3. #include "../../mem/shm_mem.h"
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include "trace.h"
  7. typedef struct {
  8. time_event_manager_t *first;
  9. time_event_manager_t *last;
  10. gen_lock_t structure_mutex;
  11. } tem_info_t;
  12. static tem_info_t *tem_info = NULL;
  13. static void tem_do_step(time_event_manager_t *tem);
  14. static void tem_timer_cb(unsigned int ticks, void *param)
  15. {
  16. time_event_manager_t *e, *n;
  17. PROF_START(tem_timer_cb)
  18. if (!tem_info) return;
  19. e = tem_info->first;
  20. while (e) {
  21. n = e->next;
  22. if (--e->process_timer_counter == 0) {
  23. tem_do_step(e);
  24. e->process_timer_counter = e->atomic_time;
  25. }
  26. e = n;
  27. }
  28. PROF_STOP(tem_timer_cb)
  29. }
  30. int time_event_management_init()
  31. {
  32. if (tem_info) return 0; /* already initialized */
  33. tem_info = (tem_info_t *)mem_alloc(sizeof(tem_info_t));
  34. if (!tem_info) {
  35. LOG(L_ERR, "time_event_management_init(): can't allocate shared memory\n");
  36. return -1;
  37. }
  38. tem_info->first = NULL;
  39. tem_info->last = NULL;
  40. lock_init(&tem_info->structure_mutex);
  41. /* register a SER timer */
  42. if (register_timer(tem_timer_cb, NULL, 1) < 0) {
  43. LOG(L_ERR, "time_event_management_init(): can't register timer\n");
  44. return -1;
  45. }
  46. return 0;
  47. }
  48. void time_event_management_destroy()
  49. {
  50. time_event_manager_t *e, *n;
  51. tem_info_t *ti = tem_info;
  52. tem_info = NULL;
  53. /* F I X M E: unregister SER timer ? */
  54. if (!ti) return;
  55. e = ti->first;
  56. while (e) {
  57. n = e->next;
  58. tem_destroy(n);
  59. e = n;
  60. }
  61. mem_free(ti);
  62. }
  63. int tem_init(time_event_manager_t *tm, unsigned int atomic_time,
  64. unsigned int slot_cnt, int enable_delay, gen_lock_t *mutex)
  65. {
  66. if (!tm) return -1;
  67. tm->tick_counter = 0;
  68. tm->atomic_time = atomic_time;
  69. tm->slot_cnt = slot_cnt;
  70. tm->enable_delay = enable_delay;
  71. tm->mutex = mutex;
  72. tm->time_slots = (time_event_slot_t *)mem_alloc(slot_cnt * sizeof(time_event_slot_t));
  73. if (!tm->time_slots) {
  74. LOG(L_ERR, "can't initialize time event manager slots\n");
  75. return -1;
  76. }
  77. memset(tm->time_slots, 0, slot_cnt * sizeof(time_event_slot_t));
  78. tm->next = NULL;
  79. tm->process_timer_counter = atomic_time;
  80. lock_get(&tem_info->structure_mutex);
  81. tm->prev = tem_info->last;
  82. if (tem_info->last) tem_info->last->next = tm;
  83. else tem_info->first = tm;
  84. tem_info->last = tm;
  85. lock_release(&tem_info->structure_mutex);
  86. return 0;
  87. }
  88. time_event_manager_t *tem_create(unsigned int atomic_time, unsigned int slot_cnt, int enable_delay, gen_lock_t *mutex)
  89. {
  90. time_event_manager_t *tm;
  91. tm = (time_event_manager_t*)mem_alloc(sizeof(time_event_manager_t));
  92. if (!tm) {
  93. LOG(L_ERR, "can't allocate time event manager\n");
  94. return tm;
  95. }
  96. if (tem_init(tm, atomic_time, slot_cnt, enable_delay, mutex) != 0) {
  97. mem_free(tm);
  98. return NULL;
  99. }
  100. return tm;
  101. }
  102. void tem_destroy(time_event_manager_t *tem)
  103. {
  104. if (tem) {
  105. lock_get(&tem_info->structure_mutex);
  106. if (tem->prev) tem->prev->next = tem->next;
  107. else tem_info->first = tem->next;
  108. if (tem->next) tem->next->prev = tem->prev;
  109. else tem_info->last = tem->prev;
  110. lock_release(&tem_info->structure_mutex);
  111. if (tem->time_slots) mem_free(tem->time_slots);
  112. mem_free(tem);
  113. }
  114. }
  115. void tem_add_event(time_event_manager_t *tem, unsigned int action_time, time_event_data_t *te)
  116. {
  117. if (tem->mutex) lock_get(tem->mutex);
  118. tem_add_event_nolock(tem, action_time, te);
  119. if (tem->mutex) lock_release(tem->mutex);
  120. }
  121. void tem_remove_event(time_event_manager_t *tem, time_event_data_t *te)
  122. {
  123. if (tem->mutex) lock_get(tem->mutex);
  124. tem_remove_event_nolock(tem, te);
  125. if (tem->mutex) lock_release(tem->mutex);
  126. }
  127. void tem_add_event_nolock(time_event_manager_t *tem, unsigned int action_time, time_event_data_t *te)
  128. {
  129. unsigned int tick, s;
  130. PROF_START(tem_add_event)
  131. if (!te) return;
  132. tick = action_time / tem->atomic_time;
  133. if ((tem->enable_delay) && (action_time % tem->atomic_time > 0)) {
  134. /* rather call the action later than before */
  135. tick++;
  136. }
  137. if (tick <= 0) tick = 1; /* never add to current slot (? only if not processing ?)*/
  138. tick += tem->tick_counter;
  139. s = tick % tem->slot_cnt;
  140. te->next = NULL;
  141. te->prev = tem->time_slots[s].last;
  142. if (tem->time_slots[s].last)
  143. tem->time_slots[s].last->next = te;
  144. else
  145. tem->time_slots[s].first = te;
  146. tem->time_slots[s].last = te;
  147. te->tick_time = tick;
  148. PROF_STOP(tem_add_event)
  149. }
  150. void tem_remove_event_nolock(time_event_manager_t *tem, time_event_data_t *te)
  151. {
  152. time_event_slot_t *slot;
  153. PROF_START(tem_remove_event)
  154. if (!te) return;
  155. slot = &tem->time_slots[te->tick_time % tem->slot_cnt];
  156. if (te->prev) te->prev->next = te->next;
  157. else slot->first = te->next;
  158. if (te->next) te->next->prev = te->prev;
  159. else slot->last = te->prev;
  160. te->next = NULL;
  161. te->prev = NULL;
  162. PROF_STOP(tem_remove_event)
  163. }
  164. static void tem_do_step(time_event_manager_t *tem)
  165. {
  166. time_event_data_t *e, *n, *unprocessed_first, *unprocessed_last;
  167. time_event_slot_t *slot;
  168. PROF_START(tem_do_step)
  169. if (tem->mutex) lock_get(tem->mutex);
  170. unprocessed_first = NULL;
  171. unprocessed_last = NULL;
  172. slot = &tem->time_slots[tem->tick_counter % tem->slot_cnt];
  173. e = slot->first;
  174. while (e) {
  175. n = e->next;
  176. if (e->tick_time == tem->tick_counter) {
  177. if (e->cb) e->cb(e);
  178. /* the pointer to this element is forgotten - it MUST be
  179. * freed in the callback function */
  180. }
  181. else {
  182. /* it is not the right time => give it into unprocessed events */
  183. e->prev = unprocessed_last;
  184. e->next = NULL;
  185. if (unprocessed_last) unprocessed_last->next = e;
  186. else unprocessed_first = e;
  187. unprocessed_last = e;
  188. }
  189. e = n;
  190. }
  191. slot->first = unprocessed_first;
  192. slot->last = unprocessed_last;
  193. tem->tick_counter++;
  194. if (tem->mutex) lock_release(tem->mutex);
  195. PROF_STOP(tem_do_step)
  196. }