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