mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-05-08 20:56:13 +00:00
wasm-c-api: Fix init/destroy thread env multiple times issue (#1766)
Record the store number of current thread with struct thread_local_stores or tls thread_local_stores_num to fix the issue: - Only call wasm_runtime_init_thread_env() in the first wasm_store_new of current thread - Only call wasm_runtime_destroy_thread_env() in the last wasm_store_delete of current thread And remove the unused store list in the engine.
This commit is contained in:
parent
371310fdee
commit
84a23d43ec
|
@ -5,6 +5,7 @@
|
||||||
#include "wasm_c_api_internal.h"
|
#include "wasm_c_api_internal.h"
|
||||||
|
|
||||||
#include "bh_assert.h"
|
#include "bh_assert.h"
|
||||||
|
#include "wasm_export.h"
|
||||||
#include "wasm_memory.h"
|
#include "wasm_memory.h"
|
||||||
#if WASM_ENABLE_INTERP != 0
|
#if WASM_ENABLE_INTERP != 0
|
||||||
#include "wasm_runtime.h"
|
#include "wasm_runtime.h"
|
||||||
|
@ -36,6 +37,13 @@ typedef struct wasm_module_ex_t {
|
||||||
uint32 ref_count;
|
uint32 ref_count;
|
||||||
} wasm_module_ex_t;
|
} wasm_module_ex_t;
|
||||||
|
|
||||||
|
#ifndef os_thread_local_attribute
|
||||||
|
typedef struct thread_local_stores {
|
||||||
|
korp_tid tid;
|
||||||
|
unsigned stores_num;
|
||||||
|
} thread_local_stores;
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
wasm_module_delete_internal(wasm_module_t *);
|
wasm_module_delete_internal(wasm_module_t *);
|
||||||
|
|
||||||
|
@ -281,23 +289,22 @@ static void
|
||||||
wasm_engine_delete_internal(wasm_engine_t *engine)
|
wasm_engine_delete_internal(wasm_engine_t *engine)
|
||||||
{
|
{
|
||||||
if (engine) {
|
if (engine) {
|
||||||
if (engine->stores) {
|
/* clean all created wasm_module_t and their locks */
|
||||||
bh_vector_destroy((Vector *)engine->stores);
|
unsigned i;
|
||||||
wasm_runtime_free(engine->stores);
|
|
||||||
|
for (i = 0; i < engine->modules.num_elems; i++) {
|
||||||
|
wasm_module_ex_t *module;
|
||||||
|
if (bh_vector_get(&engine->modules, i, &module)) {
|
||||||
|
os_mutex_destroy(&module->lock);
|
||||||
|
wasm_runtime_free(module);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clean all created wasm_module_t and their locks */
|
bh_vector_destroy(&engine->modules);
|
||||||
{
|
|
||||||
unsigned i;
|
#ifndef os_thread_local_attribute
|
||||||
for (i = 0; i < engine->modules.num_elems; i++) {
|
bh_vector_destroy(&engine->stores_by_tid);
|
||||||
wasm_module_ex_t *module;
|
#endif
|
||||||
if (bh_vector_get(&engine->modules, i, &module)) {
|
|
||||||
os_mutex_destroy(&module->lock);
|
|
||||||
wasm_runtime_free(module);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bh_vector_destroy(&engine->modules);
|
|
||||||
}
|
|
||||||
|
|
||||||
wasm_runtime_free(engine);
|
wasm_runtime_free(engine);
|
||||||
}
|
}
|
||||||
|
@ -360,12 +367,16 @@ wasm_engine_new_internal(mem_alloc_type_t type, const MemAllocOption *opts)
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
INIT_VEC(engine->stores, wasm_store_vec_new_uninitialized, 1);
|
|
||||||
|
|
||||||
if (!bh_vector_init(&engine->modules, DEFAULT_VECTOR_INIT_SIZE,
|
if (!bh_vector_init(&engine->modules, DEFAULT_VECTOR_INIT_SIZE,
|
||||||
sizeof(wasm_module_ex_t *), true))
|
sizeof(wasm_module_ex_t *), true))
|
||||||
goto failed;
|
goto failed;
|
||||||
|
|
||||||
|
#ifndef os_thread_local_attribute
|
||||||
|
if (!bh_vector_init(&engine->stores_by_tid, DEFAULT_VECTOR_INIT_SIZE,
|
||||||
|
sizeof(thread_local_stores), true))
|
||||||
|
goto failed;
|
||||||
|
#endif
|
||||||
|
|
||||||
engine->ref_count = 1;
|
engine->ref_count = 1;
|
||||||
|
|
||||||
WASM_C_DUMP_PROC_MEM();
|
WASM_C_DUMP_PROC_MEM();
|
||||||
|
@ -375,6 +386,10 @@ wasm_engine_new_internal(mem_alloc_type_t type, const MemAllocOption *opts)
|
||||||
|
|
||||||
/* global engine instance */
|
/* global engine instance */
|
||||||
static wasm_engine_t *singleton_engine = NULL;
|
static wasm_engine_t *singleton_engine = NULL;
|
||||||
|
#ifdef os_thread_local_attribute
|
||||||
|
/* categorize wasm_store_t as threads*/
|
||||||
|
static os_thread_local_attribute unsigned thread_local_stores_num = 0;
|
||||||
|
#endif
|
||||||
#if defined(OS_THREAD_MUTEX_INITIALIZER)
|
#if defined(OS_THREAD_MUTEX_INITIALIZER)
|
||||||
/**
|
/**
|
||||||
* lock for the singleton_engine
|
* lock for the singleton_engine
|
||||||
|
@ -449,6 +464,147 @@ wasm_engine_delete(wasm_engine_t *engine)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef os_thread_local_attribute
|
||||||
|
static bool
|
||||||
|
search_thread_local_store_num(Vector *stores_by_tid, korp_tid tid,
|
||||||
|
thread_local_stores *out_ts, unsigned *out_i)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < stores_by_tid->num_elems; i++) {
|
||||||
|
bool ret = bh_vector_get(stores_by_tid, i, out_ts);
|
||||||
|
bh_assert(ret);
|
||||||
|
(void)ret;
|
||||||
|
|
||||||
|
if (out_ts->tid == tid) {
|
||||||
|
*out_i = i;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static unsigned
|
||||||
|
retrive_thread_local_store_num(Vector *stores_by_tid, korp_tid tid)
|
||||||
|
{
|
||||||
|
#ifndef os_thread_local_attribute
|
||||||
|
unsigned i = 0;
|
||||||
|
thread_local_stores ts = { 0 };
|
||||||
|
unsigned ret = 0;
|
||||||
|
|
||||||
|
#if defined(OS_THREAD_MUTEX_INITIALIZER)
|
||||||
|
os_mutex_lock(&engine_lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (search_thread_local_store_num(stores_by_tid, tid, &ts, &i))
|
||||||
|
ret = ts.stores_num;
|
||||||
|
else
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
#if defined(OS_THREAD_MUTEX_INITIALIZER)
|
||||||
|
os_mutex_unlock(&engine_lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
|
(void)stores_by_tid;
|
||||||
|
(void)tid;
|
||||||
|
|
||||||
|
return thread_local_stores_num;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
increase_thread_local_store_num(Vector *stores_by_tid, korp_tid tid)
|
||||||
|
{
|
||||||
|
#ifndef os_thread_local_attribute
|
||||||
|
unsigned i = 0;
|
||||||
|
thread_local_stores ts = { 0 };
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
#if defined(OS_THREAD_MUTEX_INITIALIZER)
|
||||||
|
os_mutex_lock(&engine_lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (search_thread_local_store_num(stores_by_tid, tid, &ts, &i)) {
|
||||||
|
/* just in case if integer overflow */
|
||||||
|
if (ts.stores_num + 1 < ts.stores_num) {
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ts.stores_num++;
|
||||||
|
ret = bh_vector_set(stores_by_tid, i, &ts);
|
||||||
|
bh_assert(ret);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ts.tid = tid;
|
||||||
|
ts.stores_num = 1;
|
||||||
|
ret = bh_vector_append(stores_by_tid, &ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(OS_THREAD_MUTEX_INITIALIZER)
|
||||||
|
os_mutex_unlock(&engine_lock);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
|
(void)stores_by_tid;
|
||||||
|
(void)tid;
|
||||||
|
|
||||||
|
/* just in case if integer overflow */
|
||||||
|
if (thread_local_stores_num + 1 < thread_local_stores_num)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
thread_local_stores_num++;
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
decrease_thread_local_store_num(Vector *stores_by_tid, korp_tid tid)
|
||||||
|
{
|
||||||
|
#ifndef os_thread_local_attribute
|
||||||
|
unsigned i = 0;
|
||||||
|
thread_local_stores ts = { 0 };
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
#if defined(OS_THREAD_MUTEX_INITIALIZER)
|
||||||
|
os_mutex_lock(&engine_lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ret = search_thread_local_store_num(stores_by_tid, tid, &ts, &i);
|
||||||
|
bh_assert(ret);
|
||||||
|
|
||||||
|
/* just in case if integer overflow */
|
||||||
|
if (ts.stores_num - 1 > ts.stores_num) {
|
||||||
|
ret = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ts.stores_num--;
|
||||||
|
ret = bh_vector_set(stores_by_tid, i, &ts);
|
||||||
|
bh_assert(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(OS_THREAD_MUTEX_INITIALIZER)
|
||||||
|
os_mutex_unlock(&engine_lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
#else
|
||||||
|
(void)stores_by_tid;
|
||||||
|
(void)tid;
|
||||||
|
|
||||||
|
/* just in case if integer overflow */
|
||||||
|
if (thread_local_stores_num - 1 > thread_local_stores_num)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
thread_local_stores_num--;
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
wasm_store_t *
|
wasm_store_t *
|
||||||
wasm_store_new(wasm_engine_t *engine)
|
wasm_store_new(wasm_engine_t *engine)
|
||||||
{
|
{
|
||||||
|
@ -456,18 +612,39 @@ wasm_store_new(wasm_engine_t *engine)
|
||||||
|
|
||||||
WASM_C_DUMP_PROC_MEM();
|
WASM_C_DUMP_PROC_MEM();
|
||||||
|
|
||||||
if (!engine || singleton_engine != engine) {
|
if (!engine || singleton_engine != engine)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
if (!wasm_runtime_init_thread_env()) {
|
if (!retrive_thread_local_store_num(&engine->stores_by_tid,
|
||||||
LOG_ERROR("init thread environment failed");
|
os_self_thread())) {
|
||||||
return NULL;
|
if (!wasm_runtime_init_thread_env()) {
|
||||||
}
|
LOG_ERROR("init thread environment failed");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(store = malloc_internal(sizeof(wasm_store_t)))) {
|
if (!increase_thread_local_store_num(&engine->stores_by_tid,
|
||||||
wasm_runtime_destroy_thread_env();
|
os_self_thread())) {
|
||||||
return NULL;
|
wasm_runtime_destroy_thread_env();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(store = malloc_internal(sizeof(wasm_store_t)))) {
|
||||||
|
decrease_thread_local_store_num(&singleton_engine->stores_by_tid,
|
||||||
|
os_self_thread());
|
||||||
|
wasm_runtime_destroy_thread_env();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!increase_thread_local_store_num(&engine->stores_by_tid,
|
||||||
|
os_self_thread()))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!(store = malloc_internal(sizeof(wasm_store_t)))) {
|
||||||
|
decrease_thread_local_store_num(&singleton_engine->stores_by_tid,
|
||||||
|
os_self_thread());
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* new a vector, and new its data */
|
/* new a vector, and new its data */
|
||||||
|
@ -482,12 +659,6 @@ wasm_store_new(wasm_engine_t *engine)
|
||||||
goto failed;
|
goto failed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* append to a store list of engine */
|
|
||||||
if (!bh_vector_append((Vector *)singleton_engine->stores, &store)) {
|
|
||||||
LOG_DEBUG("bh_vector_append failed");
|
|
||||||
goto failed;
|
|
||||||
}
|
|
||||||
|
|
||||||
WASM_C_DUMP_PROC_MEM();
|
WASM_C_DUMP_PROC_MEM();
|
||||||
|
|
||||||
return store;
|
return store;
|
||||||
|
@ -511,7 +682,14 @@ wasm_store_delete(wasm_store_t *store)
|
||||||
}
|
}
|
||||||
|
|
||||||
wasm_runtime_free(store);
|
wasm_runtime_free(store);
|
||||||
wasm_runtime_destroy_thread_env();
|
|
||||||
|
if (decrease_thread_local_store_num(&singleton_engine->stores_by_tid,
|
||||||
|
os_self_thread())) {
|
||||||
|
if (!retrive_thread_local_store_num(&singleton_engine->stores_by_tid,
|
||||||
|
os_self_thread())) {
|
||||||
|
wasm_runtime_destroy_thread_env();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Type Representations */
|
/* Type Representations */
|
||||||
|
@ -1681,10 +1859,8 @@ wasm_trap_new_internal(wasm_store_t *store,
|
||||||
uint32 i;
|
uint32 i;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!singleton_engine || !singleton_engine->stores
|
if (!singleton_engine)
|
||||||
|| !singleton_engine->stores->num_elems) {
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
if (!(trap = malloc_internal(sizeof(wasm_trap_t)))) {
|
if (!(trap = malloc_internal(sizeof(wasm_trap_t)))) {
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -25,10 +25,11 @@ WASM_DECLARE_VEC(store, *)
|
||||||
|
|
||||||
/* Runtime Environment */
|
/* Runtime Environment */
|
||||||
struct wasm_engine_t {
|
struct wasm_engine_t {
|
||||||
wasm_store_vec_t *stores;
|
|
||||||
uint32 ref_count;
|
uint32 ref_count;
|
||||||
/* list of wasm_module_ex_t */
|
/* list of wasm_module_ex_t */
|
||||||
Vector modules;
|
Vector modules;
|
||||||
|
/* list of stores which are classified according to tids */
|
||||||
|
Vector stores_by_tid;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wasm_store_t {
|
struct wasm_store_t {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user