timer_wrapper.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "runtime_timer.h"
  6. #include "app_manager_export.h"
  7. #include "module_wasm_app.h"
  8. #include "bh_list.h"
  9. #include "bh_thread.h"
  10. #include "bh_time.h"
  11. static bool timer_thread_run = true;
  12. bh_list g_timer_ctx_list;
  13. korp_cond g_timer_ctx_list_cond;
  14. korp_mutex g_timer_ctx_list_mutex;
  15. typedef struct {
  16. bh_list_link l;
  17. timer_ctx_t timer_ctx;
  18. } timer_ctx_node_t;
  19. void wasm_timer_callback(timer_id_t id, unsigned int mod_id)
  20. {
  21. module_data* module = module_data_list_lookup_id(mod_id);
  22. if (module == NULL)
  23. return;
  24. // !!! the length parameter must be 0, so the receiver will
  25. // not free the payload pointer.
  26. bh_post_msg(module->queue, TIMER_EVENT_WASM, (char *)(uintptr_t)id, 0);
  27. }
  28. ///
  29. /// why we create a separate link for module timer contexts
  30. /// rather than traverse the module list?
  31. /// It helps to reduce the lock frequency for the module list.
  32. /// Also when we lock the module list and then call the callback for
  33. /// timer expire, the callback is request the list lock again for lookup
  34. /// the module from module id. It is for avoiding that situation.
  35. void * thread_modulers_timer_check(void * arg)
  36. {
  37. int ms_to_expiry;
  38. while (timer_thread_run) {
  39. ms_to_expiry = -1;
  40. vm_mutex_lock(&g_timer_ctx_list_mutex);
  41. timer_ctx_node_t* elem = (timer_ctx_node_t*)
  42. bh_list_first_elem(&g_timer_ctx_list);
  43. while (elem) {
  44. int next = check_app_timers(elem->timer_ctx);
  45. if (next != -1) {
  46. if (ms_to_expiry == -1 || ms_to_expiry > next)
  47. ms_to_expiry = next;
  48. }
  49. elem = (timer_ctx_node_t*) bh_list_elem_next(elem);
  50. }
  51. vm_mutex_unlock(&g_timer_ctx_list_mutex);
  52. if (ms_to_expiry == -1)
  53. ms_to_expiry = 60 * 1000;
  54. vm_mutex_lock(&g_timer_ctx_list_mutex);
  55. vm_cond_reltimedwait(&g_timer_ctx_list_cond, &g_timer_ctx_list_mutex,
  56. ms_to_expiry);
  57. vm_mutex_unlock(&g_timer_ctx_list_mutex);
  58. }
  59. return NULL;
  60. }
  61. void wakeup_modules_timer_thread(timer_ctx_t ctx)
  62. {
  63. vm_mutex_lock(&g_timer_ctx_list_mutex);
  64. vm_cond_signal(&g_timer_ctx_list_cond);
  65. vm_mutex_unlock(&g_timer_ctx_list_mutex);
  66. }
  67. void init_wasm_timer()
  68. {
  69. korp_tid tm_tid;
  70. bh_list_init(&g_timer_ctx_list);
  71. vm_cond_init(&g_timer_ctx_list_cond);
  72. /* temp solution for: thread_modulers_timer_check thread would recursive lock the mutex */
  73. vm_recursive_mutex_init(&g_timer_ctx_list_mutex);
  74. vm_thread_create(&tm_tid, thread_modulers_timer_check,
  75. NULL, BH_APPLET_PRESERVED_STACK_SIZE);
  76. }
  77. void exit_wasm_timer()
  78. {
  79. timer_thread_run = false;
  80. }
  81. timer_ctx_t create_wasm_timer_ctx(unsigned int module_id, int prealloc_num)
  82. {
  83. timer_ctx_t ctx = create_timer_ctx(wasm_timer_callback,
  84. wakeup_modules_timer_thread,
  85. prealloc_num,
  86. module_id);
  87. if (ctx == NULL)
  88. return NULL;
  89. timer_ctx_node_t * node = (timer_ctx_node_t*)
  90. bh_malloc(sizeof(timer_ctx_node_t));
  91. if (node == NULL) {
  92. destroy_timer_ctx(ctx);
  93. return NULL;
  94. }
  95. memset(node, 0, sizeof(*node));
  96. node->timer_ctx = ctx;
  97. vm_mutex_lock(&g_timer_ctx_list_mutex);
  98. bh_list_insert(&g_timer_ctx_list, node);
  99. vm_mutex_unlock(&g_timer_ctx_list_mutex);
  100. return ctx;
  101. }
  102. void destroy_module_timer_ctx(unsigned int module_id)
  103. {
  104. vm_mutex_lock(&g_timer_ctx_list_mutex);
  105. timer_ctx_node_t* elem = (timer_ctx_node_t*)
  106. bh_list_first_elem(&g_timer_ctx_list);
  107. while (elem) {
  108. if (timer_ctx_get_owner(elem->timer_ctx) == module_id) {
  109. bh_list_remove(&g_timer_ctx_list, elem);
  110. destroy_timer_ctx(elem->timer_ctx);
  111. bh_free(elem);
  112. break;
  113. }
  114. elem = (timer_ctx_node_t*) bh_list_elem_next(elem);
  115. }
  116. vm_mutex_unlock(&g_timer_ctx_list_mutex);
  117. }
  118. timer_ctx_t get_wasm_timer_ctx(wasm_module_inst_t module_inst)
  119. {
  120. module_data * m = app_manager_get_module_data(Module_WASM_App,
  121. module_inst);
  122. if (m == NULL)
  123. return NULL;
  124. return m->timer_ctx;
  125. }
  126. timer_id_t
  127. wasm_create_timer(wasm_exec_env_t exec_env,
  128. int interval, bool is_period, bool auto_start)
  129. {
  130. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  131. timer_ctx_t timer_ctx = get_wasm_timer_ctx(module_inst);
  132. bh_assert(timer_ctx);
  133. return sys_create_timer(timer_ctx, interval, is_period, auto_start);
  134. }
  135. void
  136. wasm_timer_destroy(wasm_exec_env_t exec_env, timer_id_t timer_id)
  137. {
  138. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  139. timer_ctx_t timer_ctx = get_wasm_timer_ctx(module_inst);
  140. bh_assert(timer_ctx);
  141. sys_timer_destroy(timer_ctx, timer_id);
  142. }
  143. void
  144. wasm_timer_cancel(wasm_exec_env_t exec_env, timer_id_t timer_id)
  145. {
  146. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  147. timer_ctx_t timer_ctx = get_wasm_timer_ctx(module_inst);
  148. bh_assert(timer_ctx);
  149. sys_timer_cancel(timer_ctx, timer_id);
  150. }
  151. void
  152. wasm_timer_restart(wasm_exec_env_t exec_env,
  153. timer_id_t timer_id, int interval)
  154. {
  155. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  156. timer_ctx_t timer_ctx = get_wasm_timer_ctx(module_inst);
  157. bh_assert(timer_ctx);
  158. sys_timer_restart(timer_ctx, timer_id, interval);
  159. }
  160. extern uint32 get_sys_tick_ms();
  161. uint32
  162. wasm_get_sys_tick_ms(wasm_exec_env_t exec_env)
  163. {
  164. return (uint32) bh_get_tick_ms();
  165. }