Skip to content

Commit 6ee1cfa

Browse files
authored
Merge pull request #715 from bytecodealliance/main
thread-mgr: Fix spread "wasi proc exit" exception and atomic.wait issues (bytecodealliance#1988)
2 parents 48d738d + 38c67b3 commit 6ee1cfa

File tree

8 files changed

+84
-19
lines changed

8 files changed

+84
-19
lines changed

core/iwasm/common/wasm_runtime_common.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1880,8 +1880,10 @@ clear_wasi_proc_exit_exception(WASMModuleInstanceCommon *module_inst_comm)
18801880
if (exception && !strcmp(exception, "Exception: wasi proc exit")) {
18811881
/* The "wasi proc exit" exception is thrown by native lib to
18821882
let wasm app exit, which is a normal behavior, we clear
1883-
the exception here. */
1884-
wasm_set_exception(module_inst, NULL);
1883+
the exception here. And just clear the exception of current
1884+
thread, don't call `wasm_set_exception(module_inst, NULL)`
1885+
which will clear the exception of all threads. */
1886+
module_inst->cur_exception[0] = '\0';
18851887
return true;
18861888
}
18871889
return false;

core/iwasm/compilation/aot_emit_function.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -999,6 +999,14 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
999999
}
10001000
#endif
10011001

1002+
#if WASM_ENABLE_THREAD_MGR != 0
1003+
/* Insert suspend check point */
1004+
if (comp_ctx->enable_thread_mgr) {
1005+
if (!check_suspend_flags(comp_ctx, func_ctx))
1006+
goto fail;
1007+
}
1008+
#endif
1009+
10021010
ret = true;
10031011
fail:
10041012
if (param_types)
@@ -1645,6 +1653,14 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
16451653
}
16461654
#endif
16471655

1656+
#if WASM_ENABLE_THREAD_MGR != 0
1657+
/* Insert suspend check point */
1658+
if (comp_ctx->enable_thread_mgr) {
1659+
if (!check_suspend_flags(comp_ctx, func_ctx))
1660+
goto fail;
1661+
}
1662+
#endif
1663+
16481664
ret = true;
16491665

16501666
fail:

core/iwasm/compilation/aot_emit_memory.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "aot_emit_exception.h"
88
#include "../aot/aot_runtime.h"
99
#include "aot_intrinsic.h"
10+
#include "aot_emit_control.h"
1011

1112
#define BUILD_ICMP(op, left, right, res, name) \
1213
do { \
@@ -1344,7 +1345,7 @@ aot_compile_op_atomic_wait(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
13441345
return false;
13451346
}
13461347

1347-
BUILD_ICMP(LLVMIntSGT, ret_value, I32_ZERO, cmp, "atomic_wait_ret");
1348+
BUILD_ICMP(LLVMIntNE, ret_value, I32_NEG_ONE, cmp, "atomic_wait_ret");
13481349

13491350
ADD_BASIC_BLOCK(wait_fail, "atomic_wait_fail");
13501351
ADD_BASIC_BLOCK(wait_success, "wait_success");
@@ -1368,6 +1369,14 @@ aot_compile_op_atomic_wait(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
13681369

13691370
PUSH_I32(ret_value);
13701371

1372+
#if WASM_ENABLE_THREAD_MGR != 0
1373+
/* Insert suspend check point */
1374+
if (comp_ctx->enable_thread_mgr) {
1375+
if (!check_suspend_flags(comp_ctx, func_ctx))
1376+
return false;
1377+
}
1378+
#endif
1379+
13711380
return true;
13721381
fail:
13731382
return false;

core/iwasm/interpreter/wasm_interp_classic.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3422,6 +3422,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
34223422
if (ret == (uint32)-1)
34233423
goto got_exception;
34243424

3425+
#if WASM_ENABLE_THREAD_MGR != 0
3426+
CHECK_SUSPEND_FLAGS();
3427+
#endif
3428+
34253429
PUSH_I32(ret);
34263430
break;
34273431
}
@@ -3442,6 +3446,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
34423446
if (ret == (uint32)-1)
34433447
goto got_exception;
34443448

3449+
#if WASM_ENABLE_THREAD_MGR != 0
3450+
CHECK_SUSPEND_FLAGS();
3451+
#endif
3452+
34453453
PUSH_I32(ret);
34463454
break;
34473455
}
@@ -3894,10 +3902,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
38943902
PUSH_CSP(LABEL_TYPE_FUNCTION, 0, cell_num, frame_ip_end - 1);
38953903

38963904
wasm_exec_env_set_cur_frame(exec_env, frame);
3905+
}
38973906
#if WASM_ENABLE_THREAD_MGR != 0
3898-
CHECK_SUSPEND_FLAGS();
3907+
CHECK_SUSPEND_FLAGS();
38993908
#endif
3900-
}
39013909
HANDLE_OP_END();
39023910
}
39033911

core/iwasm/interpreter/wasm_interp_fast.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3266,6 +3266,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
32663266
if (ret == (uint32)-1)
32673267
goto got_exception;
32683268

3269+
#if WASM_ENABLE_THREAD_MGR != 0
3270+
CHECK_SUSPEND_FLAGS();
3271+
#endif
3272+
32693273
PUSH_I32(ret);
32703274
break;
32713275
}
@@ -3286,6 +3290,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
32863290
if (ret == (uint32)-1)
32873291
goto got_exception;
32883292

3293+
#if WASM_ENABLE_THREAD_MGR != 0
3294+
CHECK_SUSPEND_FLAGS();
3295+
#endif
3296+
32893297
PUSH_I32(ret);
32903298
break;
32913299
}
@@ -3826,6 +3834,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
38263834

38273835
wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame *)frame);
38283836
}
3837+
#if WASM_ENABLE_THREAD_MGR != 0
3838+
CHECK_SUSPEND_FLAGS();
3839+
#endif
38293840
HANDLE_OP_END();
38303841
}
38313842

core/iwasm/libraries/thread-mgr/thread_manager.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,9 @@ wasm_cluster_create(WASMExecEnv *exec_env)
225225
/* Prepare the aux stack top and size for every thread */
226226
if (!wasm_exec_env_get_aux_stack(exec_env, &aux_stack_start,
227227
&aux_stack_size)) {
228+
#if WASM_ENABLE_LIB_WASI_THREADS == 0
228229
LOG_VERBOSE("No aux stack info for this module, can't create thread");
230+
#endif
229231

230232
/* If the module don't have aux stack info, don't throw error here,
231233
but remain stack_tops and stack_segment_occupied as NULL */
@@ -1131,9 +1133,14 @@ set_exception_visitor(void *node, void *user_data)
11311133
WASMModuleInstance *curr_wasm_inst =
11321134
(WASMModuleInstance *)get_module_inst(curr_exec_env);
11331135

1134-
bh_memcpy_s(curr_wasm_inst->cur_exception,
1135-
sizeof(curr_wasm_inst->cur_exception),
1136-
wasm_inst->cur_exception, sizeof(wasm_inst->cur_exception));
1136+
/* Only spread non "wasi proc exit" exception */
1137+
if (!strstr(wasm_inst->cur_exception, "wasi proc exit")) {
1138+
bh_memcpy_s(curr_wasm_inst->cur_exception,
1139+
sizeof(curr_wasm_inst->cur_exception),
1140+
wasm_inst->cur_exception,
1141+
sizeof(wasm_inst->cur_exception));
1142+
}
1143+
11371144
/* Terminate the thread so it can exit from dead loops */
11381145
set_thread_cancel_flags(curr_exec_env);
11391146
}
@@ -1203,4 +1210,4 @@ bool
12031210
wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env)
12041211
{
12051212
return (exec_env->suspend_flags.flags & 0x01) ? true : false;
1206-
}
1213+
}

samples/wasi-threads/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ $ ./iwasm wasm-apps/exception_propagation.wasm
2626
## Run samples in AOT mode
2727
```shell
2828
$ ../../../wamr-compiler/build/wamrc \
29+
--enable-multi-thread \
2930
-o wasm-apps/no_pthread.aot wasm-apps/no_pthread.wasm
3031
$ ./iwasm wasm-apps/no_pthread.aot
3132
```

samples/wasi-threads/wasm-apps/thread_termination.c

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,14 @@
1515

1616
#include "wasi_thread_start.h"
1717

18-
#define TEST_TERMINATION_BY_TRAP 0 // Otherwise test `proc_exit` termination
19-
#define TEST_TERMINATION_IN_MAIN_THREAD 1
18+
#define BUSY_WAIT 0
19+
#define ATOMIC_WAIT 1
20+
#define POLL_ONEOFF 2
21+
22+
/* Change parameters here to modify the sample behavior */
23+
#define TEST_TERMINATION_BY_TRAP 0 /* Otherwise `proc_exit` termination */
24+
#define TEST_TERMINATION_IN_MAIN_THREAD 1 /* Otherwise in spawn thread */
25+
#define LONG_TASK_IMPL ATOMIC_WAIT
2026

2127
#define TIMEOUT_SECONDS 10
2228
#define NUM_THREADS 3
@@ -30,23 +36,28 @@ typedef struct {
3036
void
3137
run_long_task()
3238
{
33-
// Busy waiting to be interruptible by trap or `proc_exit`
39+
#if LONG_TASK_IMPL == BUSY_WAIT
3440
for (int i = 0; i < TIMEOUT_SECONDS; i++)
3541
sleep(1);
42+
#elif LONG_TASK_IMPL == ATOMIC_WAIT
43+
__builtin_wasm_memory_atomic_wait32(0, 0, -1);
44+
#else
45+
sleep(TIMEOUT_SECONDS);
46+
#endif
3647
}
3748

3849
void
3950
start_job()
4051
{
4152
sem_post(&sem);
42-
run_long_task(); // Wait to be interrupted
53+
run_long_task(); /* Wait to be interrupted */
4354
assert(false && "Unreachable");
4455
}
4556

4657
void
4758
terminate_process()
4859
{
49-
// Wait for all other threads (including main thread) to be ready
60+
/* Wait for all other threads (including main thread) to be ready */
5061
printf("Waiting before terminating\n");
5162
for (int i = 0; i < NUM_THREADS; i++)
5263
sem_wait(&sem);
@@ -55,7 +66,7 @@ terminate_process()
5566
#if TEST_TERMINATION_BY_TRAP == 1
5667
__builtin_trap();
5768
#else
58-
__wasi_proc_exit(1);
69+
__wasi_proc_exit(33);
5970
#endif
6071
}
6172

@@ -86,14 +97,14 @@ main(int argc, char **argv)
8697
}
8798

8899
for (i = 0; i < NUM_THREADS; i++) {
89-
// No graceful memory free to simplify the example
100+
/* No graceful memory free to simplify the example */
90101
if (!start_args_init(&data[i].base)) {
91102
printf("Failed to allocate thread's stack\n");
92103
return EXIT_FAILURE;
93104
}
94105
}
95106

96-
// Create a thread that forces termination through trap or `proc_exit`
107+
/* Create a thread that forces termination through trap or `proc_exit` */
97108
#if TEST_TERMINATION_IN_MAIN_THREAD == 1
98109
data[0].throw_exception = false;
99110
#else
@@ -105,7 +116,7 @@ main(int argc, char **argv)
105116
return EXIT_FAILURE;
106117
}
107118

108-
// Create two additional threads to test exception propagation
119+
/* Create two additional threads to test exception propagation */
109120
data[1].throw_exception = false;
110121
thread_id = __wasi_thread_spawn(&data[1]);
111122
if (thread_id < 0) {
@@ -128,4 +139,4 @@ main(int argc, char **argv)
128139
start_job();
129140
#endif /* TEST_TERMINATION_IN_MAIN_THREAD */
130141
return EXIT_SUCCESS;
131-
}
142+
}

0 commit comments

Comments
 (0)