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 index 766aeb3cf7..2502808669 100644 --- a/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c +++ b/core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c @@ -19,6 +19,14 @@ static const char *THREAD_START_FUNCTION = "wasi_thread_start"; static korp_mutex thread_id_lock; +// Stack data structure to track available thread identifiers +#define AVAIL_TIDS_INIT_SIZE CLUSTER_MAX_THREAD_NUM +typedef struct { + int32 *ids; + uint32 pos, size; +} AvailableThreadIds; +static AvailableThreadIds avail_tids; + typedef struct { /* app's entry function */ wasm_function_inst_t start_func; @@ -31,16 +39,57 @@ typedef struct { static int32 allocate_thread_id() { - static int32 thread_id = 0; - - int32 id; + int32 id = -1; os_mutex_lock(&thread_id_lock); - id = thread_id++; + if (avail_tids.pos == 0) { // Resize stack and push new thread ids + uint32 old_size = avail_tids.size; + uint32 new_size = avail_tids.size * 2; + if (new_size / 2 != avail_tids.size) { + LOG_ERROR("Overflow detected during new size calculation"); + goto return_id; + } + avail_tids.size *= 2; + + size_t realloc_size = avail_tids.size * sizeof(int32); + if (realloc_size / sizeof(int32) != avail_tids.size) { + LOG_ERROR("Overflow detected during realloc"); + goto return_id; + } + int32 *tmp = + (int32 *)wasm_runtime_realloc(avail_tids.ids, realloc_size); + if (avail_tids.ids == NULL) { + LOG_ERROR("Thread ID allocator realloc failed"); + goto return_id; + } + avail_tids.ids = tmp; + + for (uint32 i = 0; i < old_size; i++) + avail_tids.ids[i] = avail_tids.size - i; + + avail_tids.pos = old_size; + } + + // Pop available thread identifier from `avail_tids` stack + id = avail_tids.ids[--avail_tids.pos]; + +return_id: os_mutex_unlock(&thread_id_lock); return id; } +void +deallocate_thread_id(int32 thread_id) +{ + os_mutex_lock(&thread_id_lock); + + // Release thread identifier by pushing it into `avail_tids` stack + assert(avail_tids.pos < avail_tids.size); + avail_tids.ids[avail_tids.pos++] = thread_id; + + os_mutex_unlock(&thread_id_lock); +} + static void * thread_start(void *arg) { @@ -61,6 +110,7 @@ thread_start(void *arg) /* routine exit, destroy instance */ wasm_runtime_deinstantiate_internal(module_inst, true); + deallocate_thread_id(thread_arg->thread_id); wasm_runtime_free(thread_arg); exec_env->thread_arg = NULL; @@ -114,6 +164,10 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg) } thread_start_arg->thread_id = thread_id = allocate_thread_id(); + if (thread_id < 0) { + LOG_ERROR("Failed to get thread identifier"); + goto thread_spawn_fail; + } thread_start_arg->arg = start_arg; thread_start_arg->start_func = start_func; @@ -121,14 +175,17 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg) ret = wasm_cluster_create_thread(exec_env, new_module_inst, thread_start, thread_start_arg); if (ret != 0) { - os_mutex_unlock(&exec_env->wait_lock); LOG_ERROR("Failed to spawn a new thread"); - goto thread_spawn_fail; + goto tid_allocation_fail; } os_mutex_unlock(&exec_env->wait_lock); return thread_id; +tid_allocation_fail: + os_mutex_unlock(&exec_env->wait_lock); + deallocate_thread_id(thread_id); + thread_spawn_fail: if (new_module_inst) wasm_runtime_deinstantiate_internal(new_module_inst, true); @@ -160,11 +217,25 @@ lib_wasi_threads_init(void) if (0 != os_mutex_init(&thread_id_lock)) return false; + // Initialize stack to store thread identifiers + avail_tids.size = AVAIL_TIDS_INIT_SIZE; + avail_tids.pos = avail_tids.size; + avail_tids.ids = + (int32 *)wasm_runtime_malloc(avail_tids.size * sizeof(int32)); + if (avail_tids.ids == NULL) { + os_mutex_destroy(&thread_id_lock); + return false; + } + for (uint32 i = 0; i < avail_tids.size; i++) + avail_tids.ids[i] = avail_tids.size - i; + return true; } void lib_wasi_threads_destroy(void) { + wasm_runtime_free(avail_tids.ids); + avail_tids.ids = NULL; os_mutex_destroy(&thread_id_lock); } diff --git a/samples/wasi-threads/wasm-apps/CMakeLists.txt b/samples/wasi-threads/wasm-apps/CMakeLists.txt index 9e3bef5a23..0af5769021 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 ()