diff --git a/samples/wasi-threads/README.md b/samples/wasi-threads/README.md index d7450af9..533f687e 100644 --- a/samples/wasi-threads/README.md +++ b/samples/wasi-threads/README.md @@ -1 +1,24 @@ -# "WASI threads" sample introduction \ No newline at end of file +# "WASI threads" sample introduction + +Currently, since the `wasi-sdk` does not have thread support in the latest release, make sure to have [wasi-libc](https://github.com/WebAssembly/wasi-libc) installed. Build it with threads enabled, e.g. + +```shell +make \ + AR=/opt/wasi-sdk/bin/llvm-ar \ + NM=/opt/wasi-sdk/bin/llvm-nm \ + CC=/opt/wasi-sdk/bin/clang \ + THREAD_MODEL=posix +``` + +Build and run the samples + +```shell +$ mkdir build +$ cd build +$ cmake -DWASI_SYSROOT=/path/to/wasi-libc/sysroot .. +$ make +... +$ ./iwasm wasm-apps/no_pthread.wasm +... +$ ./iwasm wasm-apps/exception_propagation.wasm +``` diff --git a/samples/wasi-threads/wasm-apps/CMakeLists.txt b/samples/wasi-threads/wasm-apps/CMakeLists.txt index 9e3bef5a..25dba40b 100644 --- a/samples/wasi-threads/wasm-apps/CMakeLists.txt +++ b/samples/wasi-threads/wasm-apps/CMakeLists.txt @@ -1,6 +1,12 @@ # Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +if (APPLE) + set (HAVE_FLAG_SEARCH_PATHS_FIRST 0) + set (CMAKE_C_LINK_FLAGS "") + set (CMAKE_CXX_LINK_FLAGS "") +endif () + if (NOT DEFINED WASI_SDK_DIR) set (WASI_SDK_DIR "/opt/wasi-sdk") endif () @@ -27,3 +33,4 @@ function (compile_sample SOURCE_FILE) endfunction () compile_sample(no_pthread.c) +compile_sample(exception_propagation.c) diff --git a/samples/wasi-threads/wasm-apps/exception_propagation.c b/samples/wasi-threads/wasm-apps/exception_propagation.c new file mode 100644 index 00000000..91f9f356 --- /dev/null +++ b/samples/wasi-threads/wasm-apps/exception_propagation.c @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2022 Amazon.com Inc. or its affiliates. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ +#ifndef __wasi__ +#error This example only compiles to WASM/WASI target +#endif + +#include +#include +#include +#include +#include +#include +#include + +#define TIMEOUT_SECONDS 10 +#define NUM_THREADS 3 +static sem_t sem; + +void +run_long_task() +{ + // Busy waiting to be interruptible by exception + for (int i = 0; i < TIMEOUT_SECONDS; i++) + sleep(1); +} + +__attribute__((export_name("wasi_thread_start"))) void +wasi_thread_start(int thread_id, int *start_arg) +{ + bool has_to_throw_exception = (bool)start_arg; + + if (has_to_throw_exception) { + // Wait for all other threads (including main thread) to be ready + printf("Waiting before throwing exception\n"); + for (int i = 0; i < NUM_THREADS; i++) + sem_wait(&sem); + + printf("Throwing exception\n"); + __builtin_trap(); + } + else { + printf("Thread running\n"); + + sem_post(&sem); + run_long_task(); // Wait to be interrupted by exception + assert(false && "Unreachable"); + } +} + +int +main(int argc, char **argv) +{ + int thread_id = -1; + if (sem_init(&sem, 0, 0) != 0) { + printf("Failed to init semaphore\n"); + return EXIT_FAILURE; + } + + // Create a thread that throws an exception + thread_id = __wasi_thread_spawn((void *)true); + if (thread_id < 0) { + printf("Failed to create thread: %d\n", thread_id); + return EXIT_FAILURE; + } + + // Create two additional threads to test exception propagation + thread_id = __wasi_thread_spawn((void *)false); + if (thread_id < 0) { + printf("Failed to create thread: %d\n", thread_id); + return EXIT_FAILURE; + } + thread_id = __wasi_thread_spawn((void *)false); + if (thread_id < 0) { + printf("Failed to create thread: %d\n", thread_id); + return EXIT_FAILURE; + } + + printf("Main thread running\n"); + + sem_post(&sem); + run_long_task(); // Wait to be interrupted by exception + assert(false && "Unreachable"); + + return EXIT_SUCCESS; +} \ No newline at end of file