main.c 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. #include "wasm_export.h"
  6. #include "bh_read_file.h"
  7. #include "pthread.h"
  8. #define THREAD_NUM 10
  9. typedef struct ThreadArgs {
  10. wasm_exec_env_t exec_env;
  11. int start;
  12. int length;
  13. } ThreadArgs;
  14. void *
  15. thread(void *arg)
  16. {
  17. ThreadArgs *thread_arg = (ThreadArgs *)arg;
  18. wasm_exec_env_t exec_env = thread_arg->exec_env;
  19. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  20. wasm_function_inst_t func;
  21. uint32 argv[2];
  22. if (!wasm_runtime_init_thread_env()) {
  23. printf("failed to initialize thread environment");
  24. return NULL;
  25. }
  26. func = wasm_runtime_lookup_function(module_inst, "sum", NULL);
  27. if (!func) {
  28. printf("failed to lookup function sum");
  29. wasm_runtime_destroy_thread_env();
  30. return NULL;
  31. }
  32. argv[0] = thread_arg->start;
  33. argv[1] = thread_arg->length;
  34. /* call the WASM function */
  35. if (!wasm_runtime_call_wasm(exec_env, func, 2, argv)) {
  36. printf("%s\n", wasm_runtime_get_exception(module_inst));
  37. wasm_runtime_destroy_thread_env();
  38. return NULL;
  39. }
  40. wasm_runtime_destroy_thread_env();
  41. return (void *)(uintptr_t)argv[0];
  42. }
  43. void *
  44. wamr_thread_cb(wasm_exec_env_t exec_env, void *arg)
  45. {
  46. ThreadArgs *thread_arg = (ThreadArgs *)arg;
  47. wasm_module_inst_t module_inst = get_module_inst(exec_env);
  48. wasm_function_inst_t func;
  49. uint32 argv[2];
  50. func = wasm_runtime_lookup_function(module_inst, "sum", NULL);
  51. if (!func) {
  52. printf("failed to lookup function sum");
  53. return NULL;
  54. }
  55. argv[0] = thread_arg->start;
  56. argv[1] = thread_arg->length;
  57. /* call the WASM function */
  58. if (!wasm_runtime_call_wasm(exec_env, func, 2, argv)) {
  59. printf("%s\n", wasm_runtime_get_exception(module_inst));
  60. return NULL;
  61. }
  62. return (void *)(uintptr_t)argv[0];
  63. }
  64. int
  65. main(int argc, char *argv[])
  66. {
  67. char *wasm_file = "wasm-apps/test.wasm";
  68. uint8 *wasm_file_buf = NULL;
  69. uint32 wasm_file_size, wasm_argv[2], i, threads_created;
  70. uint32 stack_size = 16 * 1024, heap_size = 16 * 1024;
  71. wasm_module_t wasm_module = NULL;
  72. wasm_module_inst_t wasm_module_inst = NULL;
  73. wasm_exec_env_t exec_env = NULL;
  74. RuntimeInitArgs init_args;
  75. ThreadArgs thread_arg[THREAD_NUM];
  76. pthread_t tid[THREAD_NUM];
  77. wasm_thread_t wasm_tid[THREAD_NUM];
  78. uint32 result[THREAD_NUM], sum;
  79. wasm_function_inst_t func;
  80. char error_buf[128] = { 0 };
  81. memset(thread_arg, 0, sizeof(ThreadArgs) * THREAD_NUM);
  82. memset(&init_args, 0, sizeof(RuntimeInitArgs));
  83. init_args.mem_alloc_type = Alloc_With_Allocator;
  84. init_args.mem_alloc_option.allocator.malloc_func = malloc;
  85. init_args.mem_alloc_option.allocator.realloc_func = realloc;
  86. init_args.mem_alloc_option.allocator.free_func = free;
  87. init_args.max_thread_num = THREAD_NUM;
  88. /* initialize runtime environment */
  89. if (!wasm_runtime_full_init(&init_args)) {
  90. printf("Init runtime environment failed.\n");
  91. return -1;
  92. }
  93. /* load WASM byte buffer from WASM bin file */
  94. if (!(wasm_file_buf =
  95. (uint8 *)bh_read_file_to_buffer(wasm_file, &wasm_file_size)))
  96. goto fail1;
  97. /* load WASM module */
  98. if (!(wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size,
  99. error_buf, sizeof(error_buf)))) {
  100. printf("%s\n", error_buf);
  101. goto fail2;
  102. }
  103. /* instantiate the module */
  104. if (!(wasm_module_inst =
  105. wasm_runtime_instantiate(wasm_module, stack_size, heap_size,
  106. error_buf, sizeof(error_buf)))) {
  107. printf("%s\n", error_buf);
  108. goto fail3;
  109. }
  110. /* Create the first exec_env */
  111. if (!(exec_env =
  112. wasm_runtime_create_exec_env(wasm_module_inst, stack_size))) {
  113. printf("failed to create exec_env\n");
  114. goto fail4;
  115. }
  116. func = wasm_runtime_lookup_function(wasm_module_inst, "sum", NULL);
  117. if (!func) {
  118. printf("failed to lookup function sum");
  119. goto fail5;
  120. }
  121. wasm_argv[0] = 0;
  122. wasm_argv[1] = THREAD_NUM * 10;
  123. /*
  124. * Execute the wasm function in current thread, get the expect result
  125. */
  126. if (!wasm_runtime_call_wasm(exec_env, func, 2, wasm_argv)) {
  127. printf("%s\n", wasm_runtime_get_exception(wasm_module_inst));
  128. }
  129. printf("expect result: %d\n", wasm_argv[0]);
  130. /*
  131. * Run wasm function in multiple thread created by pthread_create
  132. */
  133. memset(thread_arg, 0, sizeof(ThreadArgs) * THREAD_NUM);
  134. for (i = 0; i < THREAD_NUM; i++) {
  135. wasm_exec_env_t new_exec_env;
  136. thread_arg[i].start = 10 * i;
  137. thread_arg[i].length = 10;
  138. /* spawn a new exec_env to be executed in other threads */
  139. new_exec_env = wasm_runtime_spawn_exec_env(exec_env);
  140. if (new_exec_env)
  141. thread_arg[i].exec_env = new_exec_env;
  142. else {
  143. printf("failed to spawn exec_env\n");
  144. break;
  145. }
  146. /* If we use:
  147. thread_arg[i].exec_env = exec_env,
  148. we may get wrong result */
  149. if (0 != pthread_create(&tid[i], NULL, thread, &thread_arg[i])) {
  150. printf("failed to create thread.\n");
  151. wasm_runtime_destroy_spawned_exec_env(new_exec_env);
  152. break;
  153. }
  154. }
  155. threads_created = i;
  156. sum = 0;
  157. memset(result, 0, sizeof(uint32) * THREAD_NUM);
  158. for (i = 0; i < threads_created; i++) {
  159. pthread_join(tid[i], (void **)&result[i]);
  160. sum += result[i];
  161. /* destroy the spawned exec_env */
  162. if (thread_arg[i].exec_env)
  163. wasm_runtime_destroy_spawned_exec_env(thread_arg[i].exec_env);
  164. }
  165. printf("[pthread]sum result: %d\n", sum);
  166. /*
  167. * Run wasm function in multiple thread created by wamr spawn API
  168. */
  169. memset(thread_arg, 0, sizeof(ThreadArgs) * THREAD_NUM);
  170. for (i = 0; i < THREAD_NUM; i++) {
  171. thread_arg[i].start = 10 * i;
  172. thread_arg[i].length = 10;
  173. /* No need to spawn exec_env manually */
  174. if (0
  175. != wasm_runtime_spawn_thread(exec_env, &wasm_tid[i], wamr_thread_cb,
  176. &thread_arg[i])) {
  177. printf("failed to spawn thread.\n");
  178. break;
  179. }
  180. }
  181. threads_created = i;
  182. sum = 0;
  183. memset(result, 0, sizeof(uint32) * THREAD_NUM);
  184. for (i = 0; i < threads_created; i++) {
  185. wasm_runtime_join_thread(wasm_tid[i], (void **)&result[i]);
  186. sum += result[i];
  187. /* No need to destroy the spawned exec_env */
  188. }
  189. printf("[spwan_thread]sum result: %d\n", sum);
  190. fail5:
  191. wasm_runtime_destroy_exec_env(exec_env);
  192. fail4:
  193. /* destroy the module instance */
  194. wasm_runtime_deinstantiate(wasm_module_inst);
  195. fail3:
  196. /* unload the module */
  197. wasm_runtime_unload(wasm_module);
  198. fail2:
  199. /* free the file buffer */
  200. wasm_runtime_free(wasm_file_buf);
  201. fail1:
  202. /* destroy runtime environment */
  203. wasm_runtime_destroy();
  204. return 0;
  205. }