Skip to content

Commit

Permalink
feat(wasi-threads): improve thread id allocator to reuse identifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
eloparco committed Dec 14, 2022
1 parent 929d594 commit 3b4ff81
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 5 deletions.
84 changes: 79 additions & 5 deletions core/iwasm/libraries/lib-wasi-threads/lib_wasi_threads_wrapper.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ 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;
int32 pos;
uint32 size;
} AvailableThreadIds;
static AvailableThreadIds avail_tids;

typedef struct {
/* app's entry function */
wasm_function_inst_t start_func;
Expand All @@ -31,14 +40,57 @@ typedef struct {
static int32
allocate_thread_id()
{
static int32 thread_id = 0;

int32 id;

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 resize_fail;
}
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 resize_fail;
}
int32 *tmp =
(int32 *)wasm_runtime_realloc(avail_tids.ids, realloc_size);
if (avail_tids.ids == NULL) {
LOG_ERROR("Thread ID allocator realloc failed");
goto resize_fail;
}
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 - 1;
}

// Pop available thread identifier from `avail_tids` stack
id = avail_tids.ids[avail_tids.pos--];
os_mutex_unlock(&thread_id_lock);
return id;

resize_fail:
os_mutex_unlock(&thread_id_lock);
return -1;
}

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 - 1);
avail_tids.ids[++avail_tids.pos] = thread_id;

os_mutex_unlock(&thread_id_lock);
}

static void *
Expand All @@ -61,6 +113,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;

Expand Down Expand Up @@ -114,21 +167,28 @@ 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;

os_mutex_lock(&exec_env->wait_lock);
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);
Expand Down Expand Up @@ -160,11 +220,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 - 1;
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);
}
6 changes: 6 additions & 0 deletions samples/wasi-threads/wasm-apps/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -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 ()
Expand Down

0 comments on commit 3b4ff81

Please sign in to comment.