From 684ae6554d9597ff027fa8e5ca797da1fa052375 Mon Sep 17 00:00:00 2001
From: Marcin Kolny
Date: Tue, 6 Dec 2022 13:11:27 +0000
Subject: [PATCH] Create a placeholder for WASI threads implementation (#1783)
This a simpler version of the PR: https://github.com/bytecodealliance/wasm-micro-runtime/pull/1638
---
CMakeLists.txt | 5 ++
build-scripts/runtime_lib.cmake | 8 ++
core/config.h | 4 +
core/iwasm/common/wasm_native.c | 17 +++-
.../lib-wasi-threads/lib_wasi_threads.cmake | 11 +++
.../lib_wasi_threads_wrapper.c | 35 ++++++++
product-mini/platforms/linux/CMakeLists.txt | 6 ++
samples/wasi-threads/CMakeLists.txt | 87 +++++++++++++++++++
samples/wasi-threads/README.md | 1 +
samples/wasi-threads/wasm-apps/CMakeLists.txt | 29 +++++++
samples/wasi-threads/wasm-apps/no_pthread.c | 55 ++++++++++++
11 files changed, 256 insertions(+), 2 deletions(-)
create mode 100644 core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads.cmake
create mode 100644 core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c
create mode 100644 samples/wasi-threads/CMakeLists.txt
create mode 100644 samples/wasi-threads/README.md
create mode 100644 samples/wasi-threads/wasm-apps/CMakeLists.txt
create mode 100644 samples/wasi-threads/wasm-apps/no_pthread.c
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f683868f2d..d6466ba5a9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -83,6 +83,11 @@ if (NOT DEFINED WAMR_BUILD_LIB_PTHREAD)
set (WAMR_BUILD_LIB_PTHREAD 0)
endif ()
+if (NOT DEFINED WAMR_BUILD_LIB_WASI_THREADS)
+ # Disable wasi threads library by default
+ set (WAMR_BUILD_LIB_WASI_THREADS 0)
+endif ()
+
if (NOT DEFINED WAMR_BUILD_MINI_LOADER)
# Disable wasm mini loader by default
set (WAMR_BUILD_MINI_LOADER 0)
diff --git a/build-scripts/runtime_lib.cmake b/build-scripts/runtime_lib.cmake
index 439a7c6384..b6e6cd06b1 100644
--- a/build-scripts/runtime_lib.cmake
+++ b/build-scripts/runtime_lib.cmake
@@ -124,6 +124,13 @@ if (WAMR_BUILD_LIB_PTHREAD EQUAL 1)
set (WAMR_BUILD_SHARED_MEMORY 1)
endif ()
+if (WAMR_BUILD_LIB_WASI_THREADS EQUAL 1)
+ include (${IWASM_DIR}/libraries/lib-wasi-threads/lib_wasi_threads.cmake)
+ # Enable the dependent feature if lib wasi threads is enabled
+ set (WAMR_BUILD_BULK_MEMORY 1)
+ set (WAMR_BUILD_SHARED_MEMORY 1)
+endif ()
+
if (WAMR_BUILD_DEBUG_INTERP EQUAL 1)
set (WAMR_BUILD_THREAD_MGR 1)
include (${IWASM_DIR}/libraries/debug-engine/debug_engine.cmake)
@@ -186,6 +193,7 @@ set (source_all
${WASM_APP_LIB_SOURCE_ALL}
${NATIVE_INTERFACE_SOURCE}
${APP_MGR_SOURCE}
+ ${LIB_WASI_THREADS_SOURCE}
${LIB_PTHREAD_SOURCE}
${THREAD_MGR_SOURCE}
${LIBC_EMCC_SOURCE}
diff --git a/core/config.h b/core/config.h
index 5d6438384e..2b6846e4f9 100644
--- a/core/config.h
+++ b/core/config.h
@@ -161,6 +161,10 @@
#define WASM_ENABLE_LIB_PTHREAD_SEMAPHORE 0
#endif
+#ifndef WASM_ENABLE_LIB_WASI_THREADS
+#define WASM_ENABLE_LIB_WASI_THREADS 0
+#endif
+
#ifndef WASM_ENABLE_BASE_LIB
#define WASM_ENABLE_BASE_LIB 0
#endif
diff --git a/core/iwasm/common/wasm_native.c b/core/iwasm/common/wasm_native.c
index 0fa5962771..8c324cdc83 100644
--- a/core/iwasm/common/wasm_native.c
+++ b/core/iwasm/common/wasm_native.c
@@ -53,6 +53,11 @@ uint32
get_lib_pthread_export_apis(NativeSymbol **p_lib_pthread_apis);
#endif
+#if WASM_ENABLE_LIB_WASI_THREADS != 0
+uint32
+get_lib_wasi_threads_export_apis(NativeSymbol **p_lib_wasi_threads_apis);
+#endif
+
uint32
get_libc_emcc_export_apis(NativeSymbol **p_libc_emcc_apis);
@@ -383,7 +388,7 @@ wasm_native_init()
|| WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \
|| WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0 \
|| WASM_ENABLE_APP_FRAMEWORK != 0 || WASM_ENABLE_LIBC_WASI != 0 \
- || WASM_ENABLE_LIB_PTHREAD != 0
+ || WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_WASI_THREADS != 0
NativeSymbol *native_symbols;
uint32 n_native_symbols;
#endif
@@ -438,6 +443,14 @@ wasm_native_init()
goto fail;
#endif
+#if WASM_ENABLE_LIB_WASI_THREADS != 0
+ n_native_symbols = get_lib_wasi_threads_export_apis(&native_symbols);
+ if (n_native_symbols > 0
+ && !wasm_native_register_natives("wasi", native_symbols,
+ n_native_symbols))
+ goto fail;
+#endif
+
#if WASM_ENABLE_LIBC_EMCC != 0
n_native_symbols = get_libc_emcc_export_apis(&native_symbols);
if (n_native_symbols > 0
@@ -466,7 +479,7 @@ wasm_native_init()
|| WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0 \
|| WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0 \
|| WASM_ENABLE_APP_FRAMEWORK != 0 || WASM_ENABLE_LIBC_WASI != 0 \
- || WASM_ENABLE_LIB_PTHREAD != 0
+ || WASM_ENABLE_LIB_PTHREAD != 0 || WASM_ENABLE_LIB_WASI_THREADS != 0
fail:
wasm_native_destroy();
return false;
diff --git a/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads.cmake b/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads.cmake
new file mode 100644
index 0000000000..2f300be522
--- /dev/null
+++ b/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads.cmake
@@ -0,0 +1,11 @@
+# Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+set (LIB_WASI_THREADS_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+add_definitions (-DWASM_ENABLE_LIB_WASI_THREADS=1)
+
+include_directories(${LIB_WASI_THREADS_DIR})
+
+set (LIB_WASI_THREADS_SOURCE
+ ${LIB_WASI_THREADS_DIR}/lib_wasi_threads_wrapper.c)
\ No newline at end of file
diff --git a/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c b/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c
new file mode 100644
index 0000000000..4412a5bed4
--- /dev/null
+++ b/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "wasmtime_ssp.h"
+
+#if WASM_ENABLE_INTERP != 0
+#include "wasm_runtime.h"
+#endif
+
+#if WASM_ENABLE_AOT != 0
+#include "aot_runtime.h"
+#endif
+
+static __wasi_errno_t
+thread_spawn_wrapper(wasm_exec_env_t exec_env, void *start_arg)
+{
+ return __WASI_ENOSYS;
+}
+
+/* clang-format off */
+#define REG_NATIVE_FUNC(func_name, signature) \
+ { #func_name, func_name##_wrapper, signature, NULL }
+/* clang-format on */
+
+static NativeSymbol native_symbols_lib_wasi_threads[] = { REG_NATIVE_FUNC(
+ thread_spawn, "(*)i") };
+
+uint32
+get_lib_wasi_threads_export_apis(NativeSymbol **p_lib_wasi_threads_apis)
+{
+ *p_lib_wasi_threads_apis = native_symbols_lib_wasi_threads;
+ return sizeof(native_symbols_lib_wasi_threads) / sizeof(NativeSymbol);
+}
diff --git a/product-mini/platforms/linux/CMakeLists.txt b/product-mini/platforms/linux/CMakeLists.txt
index d3285be19e..7f84630859 100644
--- a/product-mini/platforms/linux/CMakeLists.txt
+++ b/product-mini/platforms/linux/CMakeLists.txt
@@ -85,6 +85,12 @@ if (NOT DEFINED WAMR_BUILD_LIB_PTHREAD)
set (WAMR_BUILD_LIB_PTHREAD 0)
endif ()
+if (NOT DEFINED WAMR_BUILD_LIB_WASI_THREADS)
+ # Disable wasi threads library by default
+ set (WAMR_BUILD_LIB_WASI_THREADS 0)
+endif()
+
+
if (NOT DEFINED WAMR_BUILD_MINI_LOADER)
# Disable wasm mini loader by default
set (WAMR_BUILD_MINI_LOADER 0)
diff --git a/samples/wasi-threads/CMakeLists.txt b/samples/wasi-threads/CMakeLists.txt
new file mode 100644
index 0000000000..93f6b33101
--- /dev/null
+++ b/samples/wasi-threads/CMakeLists.txt
@@ -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
+
+cmake_minimum_required(VERSION 3.14)
+
+include(CheckPIESupported)
+
+project(wasi_threads_sample)
+
+if (NOT DEFINED WASI_SYSROOT)
+ message (WARNING "Custom sysroot with threads enabled is required to build wasi threads samples.
+Please note that current wasi-sdk doesn't ship with threads enabled.
+Run cmake command with -DWASI_SYSROOT=/path/to/sysroot/with/threads to compile samples.")
+ return ()
+endif ()
+
+################ runtime settings ################
+string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM)
+if (APPLE)
+ add_definitions(-DBH_PLATFORM_DARWIN)
+endif ()
+
+# Resetdefault linker flags
+set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
+set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
+
+# WAMR features switch
+
+# Set WAMR_BUILD_TARGET, currently values supported:
+# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]",
+# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]"
+if (NOT DEFINED WAMR_BUILD_TARGET)
+ if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)")
+ set (WAMR_BUILD_TARGET "AARCH64")
+ elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64")
+ set (WAMR_BUILD_TARGET "RISCV64")
+ elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
+ # Build as X86_64 by default in 64-bit platform
+ set (WAMR_BUILD_TARGET "X86_64")
+ elseif (CMAKE_SIZEOF_VOID_P EQUAL 4)
+ # Build as X86_32 by default in 32-bit platform
+ set (WAMR_BUILD_TARGET "X86_32")
+ else ()
+ message(SEND_ERROR "Unsupported build target platform!")
+ endif ()
+endif ()
+
+if (NOT CMAKE_BUILD_TYPE)
+ set (CMAKE_BUILD_TYPE Release)
+endif ()
+
+set(WAMR_BUILD_INTERP 1)
+set(WAMR_BUILD_AOT 1)
+set(WAMR_BUILD_JIT 0)
+set(WAMR_BUILD_LIBC_BUILTIN 1)
+set(WAMR_BUILD_FAST_INTERP 1)
+set(WAMR_BUILD_LIBC_WASI 1)
+set(WAMR_BUILD_LIB_WASI_THREADS 1)
+
+# compiling and linking flags
+if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang"))
+ set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
+endif ()
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security")
+
+# build out vmlib
+set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
+include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
+
+add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE})
+################################################
+
+
+################ wasm application ################
+add_subdirectory(wasm-apps)
+
+################ wamr runtime ################
+include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
+
+set (RUNTIME_SOURCE_ALL
+ ${CMAKE_CURRENT_LIST_DIR}/../../product-mini/platforms/linux/main.c
+ ${UNCOMMON_SHARED_SOURCE}
+)
+add_executable (iwasm ${RUNTIME_SOURCE_ALL})
+check_pie_supported()
+set_target_properties (iwasm PROPERTIES POSITION_INDEPENDENT_CODE ON)
+target_link_libraries(iwasm vmlib -lpthread -lm -ldl)
diff --git a/samples/wasi-threads/README.md b/samples/wasi-threads/README.md
new file mode 100644
index 0000000000..d7450af936
--- /dev/null
+++ b/samples/wasi-threads/README.md
@@ -0,0 +1 @@
+# "WASI threads" sample introduction
\ No newline at end of file
diff --git a/samples/wasi-threads/wasm-apps/CMakeLists.txt b/samples/wasi-threads/wasm-apps/CMakeLists.txt
new file mode 100644
index 0000000000..9e3bef5a23
--- /dev/null
+++ b/samples/wasi-threads/wasm-apps/CMakeLists.txt
@@ -0,0 +1,29 @@
+# Copyright (C) 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+if (NOT DEFINED WASI_SDK_DIR)
+ set (WASI_SDK_DIR "/opt/wasi-sdk")
+endif ()
+
+set (CMAKE_SYSROOT "${WASI_SYSROOT}")
+set (CMAKE_C_COMPILER "${WASI_SDK_DIR}/bin/clang")
+set (CMAKE_C_COMPILER_TARGET "wasm32-wasi")
+
+function (compile_sample SOURCE_FILE)
+ get_filename_component (FILE_NAME ${SOURCE_FILE} NAME_WLE)
+ set (WASM_MODULE ${FILE_NAME}.wasm)
+ add_executable (${WASM_MODULE} ${SOURCE_FILE})
+
+ target_compile_options (${WASM_MODULE} PRIVATE
+ -pthread -ftls-model=local-exec)
+
+ target_link_options (${WASM_MODULE} PRIVATE
+ -z stack-size=32768
+ LINKER:--export=__heap_base
+ LINKER:--export=__data_end
+ LINKER:--shared-memory,--max-memory=1966080
+ LINKER:--export=wasi_thread_start
+ )
+endfunction ()
+
+compile_sample(no_pthread.c)
diff --git a/samples/wasi-threads/wasm-apps/no_pthread.c b/samples/wasi-threads/wasm-apps/no_pthread.c
new file mode 100644
index 0000000000..3de2a96047
--- /dev/null
+++ b/samples/wasi-threads/wasm-apps/no_pthread.c
@@ -0,0 +1,55 @@
+/*
+ * 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
+
+static const int64_t SECOND = 1000 * 1000 * 1000;
+
+typedef struct {
+ int th_ready;
+ int value;
+} shared_t;
+
+__attribute__((export_name("wasi_thread_start"))) void
+wasi_thread_start(int thread_id, int *start_arg)
+{
+ shared_t *data = (shared_t *)start_arg;
+
+ printf("New thread ID: %d, starting parameter: %d\n", thread_id,
+ data->value);
+
+ data->value += 8;
+ printf("Updated value: %d\n", data->value);
+
+ data->th_ready = 1;
+ __builtin_wasm_memory_atomic_notify(&data->th_ready, 1);
+}
+
+int
+main(int argc, char **argv)
+{
+ shared_t data = { 0, 52 };
+ __wasi_errno_t err;
+
+ err = __wasi_thread_spawn(&data);
+ if (err != __WASI_ERRNO_SUCCESS) {
+ printf("Failed to create thread: %d\n", err);
+ return EXIT_FAILURE;
+ }
+
+ if (__builtin_wasm_memory_atomic_wait32(&data.th_ready, 0, SECOND) == 2) {
+ printf("Timeout\n");
+ return EXIT_FAILURE;
+ }
+
+ printf("Thread completed, new value: %d\n", data.value);
+
+ return EXIT_SUCCESS;
+}