threads.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. #include <inttypes.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <pthread.h>
  6. #include <unistd.h>
  7. #include "wasm_c_api.h"
  8. #define own
  9. const int N_THREADS = 10;
  10. const int N_REPS = 3;
  11. // A function to be called from Wasm code.
  12. own wasm_trap_t *
  13. callback(const wasm_val_vec_t *args, wasm_val_vec_t *results)
  14. {
  15. assert(args->data[0].kind == WASM_I32);
  16. printf("> Thread %d running\n", args->data[0].of.i32);
  17. return NULL;
  18. }
  19. typedef struct {
  20. wasm_engine_t *engine;
  21. wasm_shared_module_t *module;
  22. int id;
  23. } thread_args;
  24. void *
  25. run(void *args_abs)
  26. {
  27. thread_args *args = (thread_args *)args_abs;
  28. // Rereate store and module.
  29. own wasm_store_t *store = wasm_store_new(args->engine);
  30. own wasm_module_t *module = wasm_module_obtain(store, args->module);
  31. // Run the example N times.
  32. for (int i = 0; i < N_REPS; ++i) {
  33. usleep(100000);
  34. // Create imports.
  35. own wasm_functype_t *func_type =
  36. wasm_functype_new_1_0(wasm_valtype_new_i32());
  37. own wasm_func_t *func = wasm_func_new(store, func_type, callback);
  38. wasm_functype_delete(func_type);
  39. wasm_val_t val = WASM_I32_VAL((int32_t)args->id);
  40. own wasm_globaltype_t *global_type =
  41. wasm_globaltype_new(wasm_valtype_new_i32(), WASM_CONST);
  42. own wasm_global_t *global = wasm_global_new(store, global_type, &val);
  43. wasm_globaltype_delete(global_type);
  44. // Instantiate.
  45. wasm_extern_t *externs[] = {
  46. wasm_func_as_extern(func),
  47. wasm_global_as_extern(global),
  48. };
  49. wasm_extern_vec_t imports = WASM_ARRAY_VEC(externs);
  50. own wasm_instance_t *instance =
  51. wasm_instance_new(store, module, &imports, NULL);
  52. if (!instance) {
  53. printf("> Error instantiating module!\n");
  54. return NULL;
  55. }
  56. wasm_func_delete(func);
  57. wasm_global_delete(global);
  58. // Extract export.
  59. own wasm_extern_vec_t exports;
  60. wasm_instance_exports(instance, &exports);
  61. if (exports.size == 0) {
  62. printf("> Error accessing exports!\n");
  63. return NULL;
  64. }
  65. const wasm_func_t *run_func = wasm_extern_as_func(exports.data[0]);
  66. if (run_func == NULL) {
  67. printf("> Error accessing export!\n");
  68. return NULL;
  69. }
  70. wasm_instance_delete(instance);
  71. // Call.
  72. wasm_val_vec_t empty = WASM_EMPTY_VEC;
  73. wasm_trap_t *trap = wasm_func_call(run_func, &empty, &empty);
  74. if (trap) {
  75. printf("> Error calling function!\n");
  76. wasm_trap_delete(trap);
  77. return NULL;
  78. }
  79. wasm_extern_vec_delete(&exports);
  80. }
  81. wasm_module_delete(module);
  82. wasm_store_delete(store);
  83. free(args_abs);
  84. return NULL;
  85. }
  86. int
  87. main(int argc, const char *argv[])
  88. {
  89. // Initialize.
  90. wasm_engine_t *engine = wasm_engine_new();
  91. // Load binary.
  92. #if WASM_ENABLE_AOT != 0 && WASM_ENABLE_INTERP == 0
  93. FILE *file = fopen("threads.aot", "rb");
  94. #else
  95. FILE *file = fopen("threads.wasm", "rb");
  96. #endif
  97. if (!file) {
  98. printf("> Error loading module!\n");
  99. return 1;
  100. }
  101. int ret = fseek(file, 0L, SEEK_END);
  102. if (ret == -1) {
  103. printf("> Error loading module!\n");
  104. fclose(file);
  105. return 1;
  106. }
  107. long file_size = ftell(file);
  108. if (file_size == -1) {
  109. printf("> Error loading module!\n");
  110. fclose(file);
  111. return 1;
  112. }
  113. ret = fseek(file, 0L, SEEK_SET);
  114. if (ret == -1) {
  115. printf("> Error loading module!\n");
  116. fclose(file);
  117. return 1;
  118. }
  119. wasm_byte_vec_t binary;
  120. wasm_byte_vec_new_uninitialized(&binary, file_size);
  121. if (fread(binary.data, file_size, 1, file) != 1) {
  122. printf("> Error loading module!\n");
  123. return 1;
  124. }
  125. fclose(file);
  126. // Compile and share.
  127. own wasm_store_t *store = wasm_store_new(engine);
  128. own wasm_module_t *module = wasm_module_new(store, &binary);
  129. if (!module) {
  130. printf("> Error compiling module!\n");
  131. return 1;
  132. }
  133. wasm_byte_vec_delete(&binary);
  134. own wasm_shared_module_t *shared = wasm_module_share(module);
  135. wasm_module_delete(module);
  136. wasm_store_delete(store);
  137. // Spawn threads.
  138. pthread_t threads[N_THREADS];
  139. for (int i = 0; i < N_THREADS; i++) {
  140. thread_args *args = malloc(sizeof(thread_args));
  141. args->id = i;
  142. args->engine = engine;
  143. args->module = shared;
  144. printf("Initializing thread %d...\n", i);
  145. pthread_create(&threads[i], NULL, &run, args);
  146. }
  147. for (int i = 0; i < N_THREADS; i++) {
  148. printf("Waiting for thread: %d\n", i);
  149. pthread_join(threads[i], NULL);
  150. }
  151. wasm_shared_module_delete(shared);
  152. wasm_engine_delete(engine);
  153. return 0;
  154. }