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