Skip to content

Commit f279ba8

Browse files
authored
Fix multi-threading issues (#2013)
- Implement atomic.fence to ensure a proper memory synchronization order - Destroy exec_env_singleton first in wasm/aot deinstantiation - Change terminate other threads to wait for other threads in wasm_exec_env_destroy - Fix detach thread in thread_manager_start_routine - Fix duplicated lock cluster->lock in wasm_cluster_cancel_thread - Add lib-pthread and lib-wasi-threads compilation to Windows CI
1 parent 7a3d2bf commit f279ba8

16 files changed

Lines changed: 167 additions & 42 deletions

File tree

.github/workflows/compilation_on_windows.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,17 @@ jobs:
118118
cmake .. -DWAMR_BUILD_DEBUG_INTERP=1
119119
cmake --build . --config Release --parallel 4
120120
cd .. && rm -force -r build
121+
- name: Build iwasm [lib pthread]
122+
run: |
123+
cd product-mini/platforms/windows
124+
mkdir build && cd build
125+
cmake .. -DWAMR_BUILD_LIB_PTHREAD=1
126+
cmake --build . --config Release --parallel 4
127+
cd .. && rm -force -r build
128+
- name: Build iwasm [lib wasi-thread]
129+
run: |
130+
cd product-mini/platforms/windows
131+
mkdir build && cd build
132+
cmake .. -DWAMR_BUILD_LIB_WASI_THREADS=1
133+
cmake --build . --config Release --parallel 4
134+
cd .. && rm -force -r build

core/iwasm/aot/aot_runtime.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1226,6 +1226,15 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, uint32 stack_size,
12261226
void
12271227
aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
12281228
{
1229+
if (module_inst->exec_env_singleton) {
1230+
/* wasm_exec_env_destroy will call
1231+
wasm_cluster_wait_for_all_except_self to wait for other
1232+
threads, so as to destroy their exec_envs and module
1233+
instances first, and avoid accessing the shared resources
1234+
of current module instance after it is deinstantiated. */
1235+
wasm_exec_env_destroy((WASMExecEnv *)module_inst->exec_env_singleton);
1236+
}
1237+
12291238
#if WASM_ENABLE_LIBC_WASI != 0
12301239
/* Destroy wasi resource before freeing app heap, since some fields of
12311240
wasi contex are allocated from app heap, and if app heap is freed,
@@ -1264,9 +1273,6 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
12641273
if (module_inst->func_type_indexes)
12651274
wasm_runtime_free(module_inst->func_type_indexes);
12661275

1267-
if (module_inst->exec_env_singleton)
1268-
wasm_exec_env_destroy((WASMExecEnv *)module_inst->exec_env_singleton);
1269-
12701276
if (((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports)
12711277
wasm_runtime_free(
12721278
((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports);

core/iwasm/common/wasm_application.c

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -203,22 +203,12 @@ wasm_application_execute_main(WASMModuleInstanceCommon *module_inst, int32 argc,
203203
char *argv[])
204204
{
205205
bool ret;
206-
#if WASM_ENABLE_THREAD_MGR != 0
207-
WASMCluster *cluster;
208-
#endif
209-
#if WASM_ENABLE_THREAD_MGR != 0 || WASM_ENABLE_MEMORY_PROFILING != 0
206+
#if WASM_ENABLE_MEMORY_PROFILING != 0
210207
WASMExecEnv *exec_env;
211208
#endif
212209

213210
ret = execute_main(module_inst, argc, argv);
214211

215-
#if WASM_ENABLE_THREAD_MGR != 0
216-
exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
217-
if (exec_env && (cluster = wasm_exec_env_get_cluster(exec_env))) {
218-
wasm_cluster_wait_for_all_except_self(cluster, exec_env);
219-
}
220-
#endif
221-
222212
#if WASM_ENABLE_MEMORY_PROFILING != 0
223213
exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
224214
if (exec_env) {
@@ -622,22 +612,12 @@ wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
622612
const char *name, int32 argc, char *argv[])
623613
{
624614
bool ret;
625-
#if WASM_ENABLE_THREAD_MGR != 0
626-
WASMCluster *cluster;
627-
#endif
628-
#if WASM_ENABLE_THREAD_MGR != 0 || WASM_ENABLE_MEMORY_PROFILING != 0
615+
#if WASM_ENABLE_MEMORY_PROFILING != 0
629616
WASMExecEnv *exec_env;
630617
#endif
631618

632619
ret = execute_func(module_inst, name, argc, argv);
633620

634-
#if WASM_ENABLE_THREAD_MGR != 0
635-
exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
636-
if (exec_env && (cluster = wasm_exec_env_get_cluster(exec_env))) {
637-
wasm_cluster_wait_for_all_except_self(cluster, exec_env);
638-
}
639-
#endif
640-
641621
#if WASM_ENABLE_MEMORY_PROFILING != 0
642622
exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
643623
if (exec_env) {

core/iwasm/common/wasm_exec_env.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,16 +172,16 @@ void
172172
wasm_exec_env_destroy(WASMExecEnv *exec_env)
173173
{
174174
#if WASM_ENABLE_THREAD_MGR != 0
175-
/* Terminate all sub-threads */
175+
/* Wait for all sub-threads */
176176
WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
177177
if (cluster) {
178-
wasm_cluster_terminate_all_except_self(cluster, exec_env);
178+
wasm_cluster_wait_for_all_except_self(cluster, exec_env);
179179
#if WASM_ENABLE_DEBUG_INTERP != 0
180180
/* Must fire exit event after other threads exits, otherwise
181181
the stopped thread will be overrided by other threads */
182182
wasm_cluster_thread_exited(exec_env);
183183
#endif
184-
/* We have terminated other threads, this is the only alive thread, so
184+
/* We have waited for other threads, this is the only alive thread, so
185185
* we don't acquire cluster->lock because the cluster will be destroyed
186186
* inside this function */
187187
wasm_cluster_del_exec_env(cluster, exec_env);

core/iwasm/compilation/aot_compiler.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1240,6 +1240,8 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
12401240
case WASM_OP_ATOMIC_FENCE:
12411241
/* Skip memory index */
12421242
frame_ip++;
1243+
if (!aot_compiler_op_atomic_fence(comp_ctx, func_ctx))
1244+
return false;
12431245
break;
12441246
case WASM_OP_ATOMIC_I32_LOAD:
12451247
bytes = 4;

core/iwasm/compilation/aot_emit_memory.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1423,4 +1423,13 @@ aot_compiler_op_atomic_notify(AOTCompContext *comp_ctx,
14231423
return false;
14241424
}
14251425

1426+
bool
1427+
aot_compiler_op_atomic_fence(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
1428+
{
1429+
return LLVMBuildFence(comp_ctx->builder,
1430+
LLVMAtomicOrderingSequentiallyConsistent, false, "")
1431+
? true
1432+
: false;
1433+
}
1434+
14261435
#endif /* end of WASM_ENABLE_SHARED_MEMORY */

core/iwasm/compilation/aot_emit_memory.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ bool
9797
aot_compiler_op_atomic_notify(AOTCompContext *comp_ctx,
9898
AOTFuncContext *func_ctx, uint32 align,
9999
uint32 offset, uint32 bytes);
100+
101+
bool
102+
aot_compiler_op_atomic_fence(AOTCompContext *comp_ctx,
103+
AOTFuncContext *func_ctx);
100104
#endif
101105

102106
#ifdef __cplusplus

core/iwasm/interpreter/wasm_interp_classic.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3467,6 +3467,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
34673467
{
34683468
/* Skip the memory index */
34693469
frame_ip++;
3470+
os_atomic_thread_fence(os_memory_order_release);
34703471
break;
34713472
}
34723473

@@ -4006,7 +4007,8 @@ fast_jit_call_func_bytecode(WASMModuleInstance *module_inst,
40064007
module_inst->fast_jit_func_ptrs[func_idx_non_import]);
40074008
bh_assert(action == JIT_INTERP_ACTION_NORMAL
40084009
|| (action == JIT_INTERP_ACTION_THROWN
4009-
&& wasm_runtime_copy_exception(exec_env->module_inst, NULL)));
4010+
&& wasm_copy_exception(
4011+
(WASMModuleInstance *)exec_env->module_inst, NULL)));
40104012

40114013
/* Get the return values form info.out.ret */
40124014
if (func_type->result_count) {

core/iwasm/interpreter/wasm_interp_fast.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3305,6 +3305,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
33053305
PUSH_I32(ret);
33063306
break;
33073307
}
3308+
case WASM_OP_ATOMIC_FENCE:
3309+
{
3310+
os_atomic_thread_fence(os_memory_order_release);
3311+
break;
3312+
}
33083313

33093314
case WASM_OP_ATOMIC_I32_LOAD:
33103315
case WASM_OP_ATOMIC_I32_LOAD8_U:

core/iwasm/interpreter/wasm_runtime.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2073,6 +2073,15 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
20732073
if (!module_inst)
20742074
return;
20752075

2076+
if (module_inst->exec_env_singleton) {
2077+
/* wasm_exec_env_destroy will call
2078+
wasm_cluster_wait_for_all_except_self to wait for other
2079+
threads, so as to destroy their exec_envs and module
2080+
instances first, and avoid accessing the shared resources
2081+
of current module instance after it is deinstantiated. */
2082+
wasm_exec_env_destroy(module_inst->exec_env_singleton);
2083+
}
2084+
20762085
#if WASM_ENABLE_DEBUG_INTERP != 0 \
20772086
|| (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
20782087
&& WASM_ENABLE_LAZY_JIT != 0)
@@ -2155,9 +2164,6 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
21552164
wasm_externref_cleanup((WASMModuleInstanceCommon *)module_inst);
21562165
#endif
21572166

2158-
if (module_inst->exec_env_singleton)
2159-
wasm_exec_env_destroy(module_inst->exec_env_singleton);
2160-
21612167
#if WASM_ENABLE_DUMP_CALL_STACK != 0
21622168
if (module_inst->frames) {
21632169
bh_vector_destroy(module_inst->frames);
@@ -2241,7 +2247,6 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst,
22412247
WASMRuntimeFrame *prev_frame = wasm_exec_env_get_cur_frame(exec_env);
22422248
uint8 *prev_top = exec_env->wasm_stack.s.top;
22432249
#ifdef BH_PLATFORM_WINDOWS
2244-
const char *exce;
22452250
int result;
22462251
bool has_exception;
22472252
char exception[EXCEPTION_BUF_LEN];

0 commit comments

Comments
 (0)