Skip to content

Commit 84a23d4

Browse files
authored
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.
1 parent 371310f commit 84a23d4

2 files changed

Lines changed: 212 additions & 35 deletions

File tree

core/iwasm/common/wasm_c_api.c

Lines changed: 210 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "wasm_c_api_internal.h"
66

77
#include "bh_assert.h"
8+
#include "wasm_export.h"
89
#include "wasm_memory.h"
910
#if WASM_ENABLE_INTERP != 0
1011
#include "wasm_runtime.h"
@@ -36,6 +37,13 @@ typedef struct wasm_module_ex_t {
3637
uint32 ref_count;
3738
} wasm_module_ex_t;
3839

40+
#ifndef os_thread_local_attribute
41+
typedef struct thread_local_stores {
42+
korp_tid tid;
43+
unsigned stores_num;
44+
} thread_local_stores;
45+
#endif
46+
3947
static void
4048
wasm_module_delete_internal(wasm_module_t *);
4149

@@ -281,24 +289,23 @@ static void
281289
wasm_engine_delete_internal(wasm_engine_t *engine)
282290
{
283291
if (engine) {
284-
if (engine->stores) {
285-
bh_vector_destroy((Vector *)engine->stores);
286-
wasm_runtime_free(engine->stores);
287-
}
288-
289292
/* clean all created wasm_module_t and their locks */
290-
{
291-
unsigned i;
292-
for (i = 0; i < engine->modules.num_elems; i++) {
293-
wasm_module_ex_t *module;
294-
if (bh_vector_get(&engine->modules, i, &module)) {
295-
os_mutex_destroy(&module->lock);
296-
wasm_runtime_free(module);
297-
}
293+
unsigned i;
294+
295+
for (i = 0; i < engine->modules.num_elems; i++) {
296+
wasm_module_ex_t *module;
297+
if (bh_vector_get(&engine->modules, i, &module)) {
298+
os_mutex_destroy(&module->lock);
299+
wasm_runtime_free(module);
298300
}
299-
bh_vector_destroy(&engine->modules);
300301
}
301302

303+
bh_vector_destroy(&engine->modules);
304+
305+
#ifndef os_thread_local_attribute
306+
bh_vector_destroy(&engine->stores_by_tid);
307+
#endif
308+
302309
wasm_runtime_free(engine);
303310
}
304311

@@ -360,12 +367,16 @@ wasm_engine_new_internal(mem_alloc_type_t type, const MemAllocOption *opts)
360367
goto failed;
361368
}
362369

363-
INIT_VEC(engine->stores, wasm_store_vec_new_uninitialized, 1);
364-
365370
if (!bh_vector_init(&engine->modules, DEFAULT_VECTOR_INIT_SIZE,
366371
sizeof(wasm_module_ex_t *), true))
367372
goto failed;
368373

374+
#ifndef os_thread_local_attribute
375+
if (!bh_vector_init(&engine->stores_by_tid, DEFAULT_VECTOR_INIT_SIZE,
376+
sizeof(thread_local_stores), true))
377+
goto failed;
378+
#endif
379+
369380
engine->ref_count = 1;
370381

371382
WASM_C_DUMP_PROC_MEM();
@@ -375,6 +386,10 @@ wasm_engine_new_internal(mem_alloc_type_t type, const MemAllocOption *opts)
375386

376387
/* global engine instance */
377388
static wasm_engine_t *singleton_engine = NULL;
389+
#ifdef os_thread_local_attribute
390+
/* categorize wasm_store_t as threads*/
391+
static os_thread_local_attribute unsigned thread_local_stores_num = 0;
392+
#endif
378393
#if defined(OS_THREAD_MUTEX_INITIALIZER)
379394
/**
380395
* lock for the singleton_engine
@@ -449,25 +464,187 @@ wasm_engine_delete(wasm_engine_t *engine)
449464
#endif
450465
}
451466

467+
#ifndef os_thread_local_attribute
468+
static bool
469+
search_thread_local_store_num(Vector *stores_by_tid, korp_tid tid,
470+
thread_local_stores *out_ts, unsigned *out_i)
471+
{
472+
unsigned i;
473+
474+
for (i = 0; i < stores_by_tid->num_elems; i++) {
475+
bool ret = bh_vector_get(stores_by_tid, i, out_ts);
476+
bh_assert(ret);
477+
(void)ret;
478+
479+
if (out_ts->tid == tid) {
480+
*out_i = i;
481+
return true;
482+
}
483+
}
484+
485+
return false;
486+
}
487+
#endif
488+
489+
static unsigned
490+
retrive_thread_local_store_num(Vector *stores_by_tid, korp_tid tid)
491+
{
492+
#ifndef os_thread_local_attribute
493+
unsigned i = 0;
494+
thread_local_stores ts = { 0 };
495+
unsigned ret = 0;
496+
497+
#if defined(OS_THREAD_MUTEX_INITIALIZER)
498+
os_mutex_lock(&engine_lock);
499+
#endif
500+
501+
if (search_thread_local_store_num(stores_by_tid, tid, &ts, &i))
502+
ret = ts.stores_num;
503+
else
504+
ret = 0;
505+
506+
#if defined(OS_THREAD_MUTEX_INITIALIZER)
507+
os_mutex_unlock(&engine_lock);
508+
#endif
509+
510+
return ret;
511+
#else
512+
(void)stores_by_tid;
513+
(void)tid;
514+
515+
return thread_local_stores_num;
516+
#endif
517+
}
518+
519+
static bool
520+
increase_thread_local_store_num(Vector *stores_by_tid, korp_tid tid)
521+
{
522+
#ifndef os_thread_local_attribute
523+
unsigned i = 0;
524+
thread_local_stores ts = { 0 };
525+
bool ret = false;
526+
527+
#if defined(OS_THREAD_MUTEX_INITIALIZER)
528+
os_mutex_lock(&engine_lock);
529+
#endif
530+
531+
if (search_thread_local_store_num(stores_by_tid, tid, &ts, &i)) {
532+
/* just in case if integer overflow */
533+
if (ts.stores_num + 1 < ts.stores_num) {
534+
ret = false;
535+
}
536+
else {
537+
ts.stores_num++;
538+
ret = bh_vector_set(stores_by_tid, i, &ts);
539+
bh_assert(ret);
540+
}
541+
}
542+
else {
543+
ts.tid = tid;
544+
ts.stores_num = 1;
545+
ret = bh_vector_append(stores_by_tid, &ts);
546+
}
547+
548+
#if defined(OS_THREAD_MUTEX_INITIALIZER)
549+
os_mutex_unlock(&engine_lock);
550+
#endif
551+
return ret;
552+
#else
553+
(void)stores_by_tid;
554+
(void)tid;
555+
556+
/* just in case if integer overflow */
557+
if (thread_local_stores_num + 1 < thread_local_stores_num)
558+
return false;
559+
560+
thread_local_stores_num++;
561+
return true;
562+
#endif
563+
}
564+
565+
static bool
566+
decrease_thread_local_store_num(Vector *stores_by_tid, korp_tid tid)
567+
{
568+
#ifndef os_thread_local_attribute
569+
unsigned i = 0;
570+
thread_local_stores ts = { 0 };
571+
bool ret = false;
572+
573+
#if defined(OS_THREAD_MUTEX_INITIALIZER)
574+
os_mutex_lock(&engine_lock);
575+
#endif
576+
577+
ret = search_thread_local_store_num(stores_by_tid, tid, &ts, &i);
578+
bh_assert(ret);
579+
580+
/* just in case if integer overflow */
581+
if (ts.stores_num - 1 > ts.stores_num) {
582+
ret = false;
583+
}
584+
else {
585+
ts.stores_num--;
586+
ret = bh_vector_set(stores_by_tid, i, &ts);
587+
bh_assert(ret);
588+
}
589+
590+
#if defined(OS_THREAD_MUTEX_INITIALIZER)
591+
os_mutex_unlock(&engine_lock);
592+
#endif
593+
594+
return ret;
595+
#else
596+
(void)stores_by_tid;
597+
(void)tid;
598+
599+
/* just in case if integer overflow */
600+
if (thread_local_stores_num - 1 > thread_local_stores_num)
601+
return false;
602+
603+
thread_local_stores_num--;
604+
return true;
605+
#endif
606+
}
607+
452608
wasm_store_t *
453609
wasm_store_new(wasm_engine_t *engine)
454610
{
455611
wasm_store_t *store = NULL;
456612

457613
WASM_C_DUMP_PROC_MEM();
458614

459-
if (!engine || singleton_engine != engine) {
615+
if (!engine || singleton_engine != engine)
460616
return NULL;
461-
}
462617

463-
if (!wasm_runtime_init_thread_env()) {
464-
LOG_ERROR("init thread environment failed");
465-
return NULL;
618+
if (!retrive_thread_local_store_num(&engine->stores_by_tid,
619+
os_self_thread())) {
620+
if (!wasm_runtime_init_thread_env()) {
621+
LOG_ERROR("init thread environment failed");
622+
return NULL;
623+
}
624+
625+
if (!increase_thread_local_store_num(&engine->stores_by_tid,
626+
os_self_thread())) {
627+
wasm_runtime_destroy_thread_env();
628+
return NULL;
629+
}
630+
631+
if (!(store = malloc_internal(sizeof(wasm_store_t)))) {
632+
decrease_thread_local_store_num(&singleton_engine->stores_by_tid,
633+
os_self_thread());
634+
wasm_runtime_destroy_thread_env();
635+
return NULL;
636+
}
466637
}
638+
else {
639+
if (!increase_thread_local_store_num(&engine->stores_by_tid,
640+
os_self_thread()))
641+
return NULL;
467642

468-
if (!(store = malloc_internal(sizeof(wasm_store_t)))) {
469-
wasm_runtime_destroy_thread_env();
470-
return NULL;
643+
if (!(store = malloc_internal(sizeof(wasm_store_t)))) {
644+
decrease_thread_local_store_num(&singleton_engine->stores_by_tid,
645+
os_self_thread());
646+
return NULL;
647+
}
471648
}
472649

473650
/* new a vector, and new its data */
@@ -482,12 +659,6 @@ wasm_store_new(wasm_engine_t *engine)
482659
goto failed;
483660
}
484661

485-
/* append to a store list of engine */
486-
if (!bh_vector_append((Vector *)singleton_engine->stores, &store)) {
487-
LOG_DEBUG("bh_vector_append failed");
488-
goto failed;
489-
}
490-
491662
WASM_C_DUMP_PROC_MEM();
492663

493664
return store;
@@ -511,7 +682,14 @@ wasm_store_delete(wasm_store_t *store)
511682
}
512683

513684
wasm_runtime_free(store);
514-
wasm_runtime_destroy_thread_env();
685+
686+
if (decrease_thread_local_store_num(&singleton_engine->stores_by_tid,
687+
os_self_thread())) {
688+
if (!retrive_thread_local_store_num(&singleton_engine->stores_by_tid,
689+
os_self_thread())) {
690+
wasm_runtime_destroy_thread_env();
691+
}
692+
}
515693
}
516694

517695
/* Type Representations */
@@ -1681,10 +1859,8 @@ wasm_trap_new_internal(wasm_store_t *store,
16811859
uint32 i;
16821860
#endif
16831861

1684-
if (!singleton_engine || !singleton_engine->stores
1685-
|| !singleton_engine->stores->num_elems) {
1862+
if (!singleton_engine)
16861863
return NULL;
1687-
}
16881864

16891865
if (!(trap = malloc_internal(sizeof(wasm_trap_t)))) {
16901866
return NULL;

core/iwasm/common/wasm_c_api_internal.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ WASM_DECLARE_VEC(store, *)
2525

2626
/* Runtime Environment */
2727
struct wasm_engine_t {
28-
wasm_store_vec_t *stores;
2928
uint32 ref_count;
3029
/* list of wasm_module_ex_t */
3130
Vector modules;
31+
/* list of stores which are classified according to tids */
32+
Vector stores_by_tid;
3233
};
3334

3435
struct wasm_store_t {

0 commit comments

Comments
 (0)