Przeglądaj źródła

Create a placeholder for WASI threads implementation (#1783)

This a simpler version of the PR: https://github.com/bytecodealliance/wasm-micro-runtime/pull/1638
Marcin Kolny 3 lat temu
rodzic
commit
684ae6554d

+ 5 - 0
CMakeLists.txt

@@ -83,6 +83,11 @@ if (NOT DEFINED WAMR_BUILD_LIB_PTHREAD)
   set (WAMR_BUILD_LIB_PTHREAD 0)
   set (WAMR_BUILD_LIB_PTHREAD 0)
 endif ()
 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)
 if (NOT DEFINED WAMR_BUILD_MINI_LOADER)
   # Disable wasm mini loader by default
   # Disable wasm mini loader by default
   set (WAMR_BUILD_MINI_LOADER 0)
   set (WAMR_BUILD_MINI_LOADER 0)

+ 8 - 0
build-scripts/runtime_lib.cmake

@@ -124,6 +124,13 @@ if (WAMR_BUILD_LIB_PTHREAD EQUAL 1)
     set (WAMR_BUILD_SHARED_MEMORY 1)
     set (WAMR_BUILD_SHARED_MEMORY 1)
 endif ()
 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)
 if (WAMR_BUILD_DEBUG_INTERP EQUAL 1)
     set (WAMR_BUILD_THREAD_MGR 1)
     set (WAMR_BUILD_THREAD_MGR 1)
     include (${IWASM_DIR}/libraries/debug-engine/debug_engine.cmake)
     include (${IWASM_DIR}/libraries/debug-engine/debug_engine.cmake)
@@ -186,6 +193,7 @@ set (source_all
     ${WASM_APP_LIB_SOURCE_ALL}
     ${WASM_APP_LIB_SOURCE_ALL}
     ${NATIVE_INTERFACE_SOURCE}
     ${NATIVE_INTERFACE_SOURCE}
     ${APP_MGR_SOURCE}
     ${APP_MGR_SOURCE}
+    ${LIB_WASI_THREADS_SOURCE}
     ${LIB_PTHREAD_SOURCE}
     ${LIB_PTHREAD_SOURCE}
     ${THREAD_MGR_SOURCE}
     ${THREAD_MGR_SOURCE}
     ${LIBC_EMCC_SOURCE}
     ${LIBC_EMCC_SOURCE}

+ 4 - 0
core/config.h

@@ -161,6 +161,10 @@
 #define WASM_ENABLE_LIB_PTHREAD_SEMAPHORE 0
 #define WASM_ENABLE_LIB_PTHREAD_SEMAPHORE 0
 #endif
 #endif
 
 
+#ifndef WASM_ENABLE_LIB_WASI_THREADS
+#define WASM_ENABLE_LIB_WASI_THREADS 0
+#endif
+
 #ifndef WASM_ENABLE_BASE_LIB
 #ifndef WASM_ENABLE_BASE_LIB
 #define WASM_ENABLE_BASE_LIB 0
 #define WASM_ENABLE_BASE_LIB 0
 #endif
 #endif

+ 15 - 2
core/iwasm/common/wasm_native.c

@@ -53,6 +53,11 @@ uint32
 get_lib_pthread_export_apis(NativeSymbol **p_lib_pthread_apis);
 get_lib_pthread_export_apis(NativeSymbol **p_lib_pthread_apis);
 #endif
 #endif
 
 
+#if WASM_ENABLE_LIB_WASI_THREADS != 0
+uint32
+get_lib_wasi_threads_export_apis(NativeSymbol **p_lib_wasi_threads_apis);
+#endif
+
 uint32
 uint32
 get_libc_emcc_export_apis(NativeSymbol **p_libc_emcc_apis);
 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_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0      \
     || WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0        \
     || WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0        \
     || WASM_ENABLE_APP_FRAMEWORK != 0 || WASM_ENABLE_LIBC_WASI != 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;
     NativeSymbol *native_symbols;
     uint32 n_native_symbols;
     uint32 n_native_symbols;
 #endif
 #endif
@@ -438,6 +443,14 @@ wasm_native_init()
         goto fail;
         goto fail;
 #endif
 #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
 #if WASM_ENABLE_LIBC_EMCC != 0
     n_native_symbols = get_libc_emcc_export_apis(&native_symbols);
     n_native_symbols = get_libc_emcc_export_apis(&native_symbols);
     if (n_native_symbols > 0
     if (n_native_symbols > 0
@@ -466,7 +479,7 @@ wasm_native_init()
     || WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0      \
     || WASM_ENABLE_BASE_LIB != 0 || WASM_ENABLE_LIBC_EMCC != 0      \
     || WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0        \
     || WASM_ENABLE_LIB_RATS != 0 || WASM_ENABLE_WASI_NN != 0        \
     || WASM_ENABLE_APP_FRAMEWORK != 0 || WASM_ENABLE_LIBC_WASI != 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:
 fail:
     wasm_native_destroy();
     wasm_native_destroy();
     return false;
     return false;

+ 11 - 0
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)

+ 35 - 0
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);
+}

+ 6 - 0
product-mini/platforms/linux/CMakeLists.txt

@@ -85,6 +85,12 @@ if (NOT DEFINED WAMR_BUILD_LIB_PTHREAD)
   set (WAMR_BUILD_LIB_PTHREAD 0)
   set (WAMR_BUILD_LIB_PTHREAD 0)
 endif ()
 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)
 if (NOT DEFINED WAMR_BUILD_MINI_LOADER)
   # Disable wasm mini loader by default
   # Disable wasm mini loader by default
   set (WAMR_BUILD_MINI_LOADER 0)
   set (WAMR_BUILD_MINI_LOADER 0)

+ 87 - 0
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)

+ 1 - 0
samples/wasi-threads/README.md

@@ -0,0 +1 @@
+# "WASI threads" sample introduction

+ 29 - 0
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)

+ 55 - 0
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 <stdlib.h>
+#include <stdio.h>
+#include <wasi/api.h>
+
+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;
+}