Merge pull request #1392 from bytecodealliance/main
Merge main into dev/socket
This commit is contained in:
@ -5,6 +5,10 @@ set (LIB_PTHREAD_DIR ${CMAKE_CURRENT_LIST_DIR})
|
||||
|
||||
add_definitions (-DWASM_ENABLE_LIB_PTHREAD=1)
|
||||
|
||||
if (WAMR_BUILD_LIB_PTHREAD_SEMAPHORE EQUAL 1)
|
||||
add_definitions (-DWASM_ENABLE_LIB_PTHREAD_SEMAPHORE=1)
|
||||
endif()
|
||||
|
||||
include_directories(${LIB_PTHREAD_DIR})
|
||||
|
||||
file (GLOB source_all ${LIB_PTHREAD_DIR}/*.c)
|
||||
|
||||
@ -54,6 +54,7 @@ enum {
|
||||
T_THREAD,
|
||||
T_MUTEX,
|
||||
T_COND,
|
||||
T_SEM,
|
||||
};
|
||||
|
||||
enum thread_status_t {
|
||||
@ -73,6 +74,12 @@ enum cond_status_t {
|
||||
COND_DESTROYED,
|
||||
};
|
||||
|
||||
enum sem_status_t {
|
||||
SEM_CREATED,
|
||||
SEM_CLOSED,
|
||||
SEM_DESTROYED,
|
||||
};
|
||||
|
||||
typedef struct ThreadKeyValueNode {
|
||||
bh_list_link l;
|
||||
wasm_exec_env_t exec_env;
|
||||
@ -111,6 +118,9 @@ typedef struct ThreadInfoNode {
|
||||
korp_tid thread;
|
||||
korp_mutex *mutex;
|
||||
korp_cond *cond;
|
||||
#if WASM_ENABLE_LIB_PTHREAD_SEMAPHORE != 0
|
||||
korp_sem *sem;
|
||||
#endif
|
||||
/* A copy of the thread return value */
|
||||
void *ret;
|
||||
} u;
|
||||
@ -125,7 +135,15 @@ typedef struct {
|
||||
wasm_module_inst_t module_inst;
|
||||
} ThreadRoutineArgs;
|
||||
|
||||
typedef struct {
|
||||
uint32 handle;
|
||||
ThreadInfoNode *node;
|
||||
} SemCallbackArgs;
|
||||
|
||||
static bh_list cluster_info_list;
|
||||
#if WASM_ENABLE_LIB_PTHREAD_SEMAPHORE != 0
|
||||
static HashMap *sem_info_map;
|
||||
#endif
|
||||
static korp_mutex thread_global_lock;
|
||||
static uint32 handle_id = 1;
|
||||
|
||||
@ -160,6 +178,12 @@ thread_info_destroy(void *node)
|
||||
os_cond_destroy(info_node->u.cond);
|
||||
wasm_runtime_free(info_node->u.cond);
|
||||
}
|
||||
#if WASM_ENABLE_LIB_PTHREAD_SEMAPHORE != 0
|
||||
else if (info_node->type == T_SEM) {
|
||||
if (info_node->status != SEM_DESTROYED)
|
||||
os_sem_close(info_node->u.sem);
|
||||
}
|
||||
#endif
|
||||
wasm_runtime_free(info_node);
|
||||
os_mutex_unlock(&thread_global_lock);
|
||||
}
|
||||
@ -174,12 +198,23 @@ lib_pthread_init()
|
||||
os_mutex_destroy(&thread_global_lock);
|
||||
return false;
|
||||
}
|
||||
#if WASM_ENABLE_LIB_PTHREAD_SEMAPHORE != 0
|
||||
if (!(sem_info_map = bh_hash_map_create(
|
||||
32, true, (HashFunc)wasm_string_hash,
|
||||
(KeyEqualFunc)wasm_string_equal, NULL, thread_info_destroy))) {
|
||||
os_mutex_destroy(&thread_global_lock);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
lib_pthread_destroy()
|
||||
{
|
||||
#if WASM_ENABLE_LIB_PTHREAD_SEMAPHORE != 0
|
||||
bh_hash_map_destroy(sem_info_map);
|
||||
#endif
|
||||
os_mutex_destroy(&thread_global_lock);
|
||||
}
|
||||
|
||||
@ -1085,6 +1120,176 @@ posix_memalign_wrapper(wasm_exec_env_t exec_env, void **memptr, int32 align,
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_LIB_PTHREAD_SEMAPHORE != 0
|
||||
|
||||
static int32
|
||||
sem_open_wrapper(wasm_exec_env_t exec_env, const char *name, int32 oflags,
|
||||
int32 mode, int32 val)
|
||||
{
|
||||
korp_sem *psem = NULL;
|
||||
ThreadInfoNode *info_node = NULL;
|
||||
|
||||
/**
|
||||
* For RTOS, global semaphore map is safe for share the same semaphore
|
||||
* between task/pthread.
|
||||
* For Unix like system, it's dedicated for multiple processes.
|
||||
*/
|
||||
|
||||
if ((info_node = bh_hash_map_find(sem_info_map, (void *)name))) {
|
||||
return info_node->handle;
|
||||
}
|
||||
|
||||
if (!(psem = os_sem_open(name, oflags, mode, val))) {
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
if (!(info_node = wasm_runtime_malloc(sizeof(ThreadInfoNode))))
|
||||
goto fail2;
|
||||
|
||||
memset(info_node, 0, sizeof(ThreadInfoNode));
|
||||
info_node->exec_env = exec_env;
|
||||
info_node->handle = allocate_handle();
|
||||
info_node->type = T_SEM;
|
||||
info_node->u.sem = psem;
|
||||
info_node->status = SEM_CREATED;
|
||||
|
||||
if (!bh_hash_map_insert(sem_info_map, (void *)name, info_node))
|
||||
goto fail3;
|
||||
|
||||
return info_node->handle;
|
||||
|
||||
fail3:
|
||||
wasm_runtime_free(info_node);
|
||||
fail2:
|
||||
os_sem_close(psem);
|
||||
fail1:
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
sem_fetch_cb(void *key, void *value, void *user_data)
|
||||
{
|
||||
(void)key;
|
||||
SemCallbackArgs *args = user_data;
|
||||
ThreadInfoNode *info_node = value;
|
||||
if (args->handle == info_node->handle && info_node->status == SEM_CREATED) {
|
||||
args->node = info_node;
|
||||
}
|
||||
}
|
||||
|
||||
static int32
|
||||
sem_close_wrapper(wasm_exec_env_t exec_env, uint32 sem)
|
||||
{
|
||||
(void)exec_env;
|
||||
int ret = -1;
|
||||
SemCallbackArgs args = { sem, NULL };
|
||||
|
||||
bh_hash_map_traverse(sem_info_map, sem_fetch_cb, &args);
|
||||
|
||||
if (args.node) {
|
||||
ret = os_sem_close(args.node->u.sem);
|
||||
if (ret == 0) {
|
||||
args.node->status = SEM_CLOSED;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32
|
||||
sem_wait_wrapper(wasm_exec_env_t exec_env, uint32 sem)
|
||||
{
|
||||
(void)exec_env;
|
||||
SemCallbackArgs args = { sem, NULL };
|
||||
|
||||
bh_hash_map_traverse(sem_info_map, sem_fetch_cb, &args);
|
||||
|
||||
if (args.node) {
|
||||
return os_sem_wait(args.node->u.sem);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int32
|
||||
sem_trywait_wrapper(wasm_exec_env_t exec_env, uint32 sem)
|
||||
{
|
||||
(void)exec_env;
|
||||
SemCallbackArgs args = { sem, NULL };
|
||||
|
||||
bh_hash_map_traverse(sem_info_map, sem_fetch_cb, &args);
|
||||
|
||||
if (args.node) {
|
||||
return os_sem_trywait(args.node->u.sem);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int32
|
||||
sem_post_wrapper(wasm_exec_env_t exec_env, uint32 sem)
|
||||
{
|
||||
(void)exec_env;
|
||||
SemCallbackArgs args = { sem, NULL };
|
||||
|
||||
bh_hash_map_traverse(sem_info_map, sem_fetch_cb, &args);
|
||||
|
||||
if (args.node) {
|
||||
return os_sem_post(args.node->u.sem);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int32
|
||||
sem_getvalue_wrapper(wasm_exec_env_t exec_env, uint32 sem, int32 *sval)
|
||||
{
|
||||
int32 ret = -1;
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
|
||||
(void)exec_env;
|
||||
SemCallbackArgs args = { sem, NULL };
|
||||
|
||||
if (validate_native_addr(sval, sizeof(int32))) {
|
||||
|
||||
bh_hash_map_traverse(sem_info_map, sem_fetch_cb, &args);
|
||||
|
||||
if (args.node) {
|
||||
ret = os_sem_getvalue(args.node->u.sem, sval);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int32
|
||||
sem_unlink_wrapper(wasm_exec_env_t exec_env, const char *name)
|
||||
{
|
||||
(void)exec_env;
|
||||
int32 ret_val;
|
||||
|
||||
ThreadInfoNode *info_node = bh_hash_map_find(sem_info_map, (void *)name);
|
||||
if (!info_node || info_node->type != T_SEM)
|
||||
return -1;
|
||||
|
||||
if (info_node->status != SEM_CLOSED) {
|
||||
ret_val = os_sem_close(info_node->u.sem);
|
||||
if (ret_val != 0) {
|
||||
return ret_val;
|
||||
}
|
||||
}
|
||||
|
||||
ret_val = os_sem_unlink(name);
|
||||
|
||||
if (ret_val == 0) {
|
||||
bh_hash_map_remove(sem_info_map, (void *)name, NULL, NULL);
|
||||
info_node->status = SEM_DESTROYED;
|
||||
thread_info_destroy(info_node);
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* clang-format off */
|
||||
#define REG_NATIVE_FUNC(func_name, signature) \
|
||||
{ #func_name, func_name##_wrapper, signature, NULL }
|
||||
@ -1113,6 +1318,15 @@ static NativeSymbol native_symbols_lib_pthread[] = {
|
||||
REG_NATIVE_FUNC(pthread_getspecific, "(i)i"),
|
||||
REG_NATIVE_FUNC(pthread_key_delete, "(i)i"),
|
||||
REG_NATIVE_FUNC(posix_memalign, "(*ii)i"),
|
||||
#if WASM_ENABLE_LIB_PTHREAD_SEMAPHORE != 0
|
||||
REG_NATIVE_FUNC(sem_open, "($iii)i"),
|
||||
REG_NATIVE_FUNC(sem_close, "(i)i"),
|
||||
REG_NATIVE_FUNC(sem_wait, "(i)i"),
|
||||
REG_NATIVE_FUNC(sem_trywait, "(i)i"),
|
||||
REG_NATIVE_FUNC(sem_post, "(i)i"),
|
||||
REG_NATIVE_FUNC(sem_getvalue, "(i*)i"),
|
||||
REG_NATIVE_FUNC(sem_unlink, "($)i"),
|
||||
#endif
|
||||
};
|
||||
|
||||
uint32
|
||||
|
||||
@ -16,18 +16,6 @@
|
||||
void
|
||||
wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception);
|
||||
|
||||
uint32
|
||||
wasm_runtime_get_temp_ret(wasm_module_inst_t module);
|
||||
|
||||
void
|
||||
wasm_runtime_set_temp_ret(wasm_module_inst_t module, uint32 temp_ret);
|
||||
|
||||
uint32
|
||||
wasm_runtime_get_llvm_stack(wasm_module_inst_t module);
|
||||
|
||||
void
|
||||
wasm_runtime_set_llvm_stack(wasm_module_inst_t module, uint32 llvm_stack);
|
||||
|
||||
uint32
|
||||
wasm_runtime_module_realloc(wasm_module_inst_t module, uint32 ptr, uint32 size,
|
||||
void **p_native_addr);
|
||||
@ -841,87 +829,6 @@ isalnum_wrapper(wasm_exec_env_t exec_env, int32 c)
|
||||
return isalnum(c);
|
||||
}
|
||||
|
||||
static void
|
||||
setTempRet0_wrapper(wasm_exec_env_t exec_env, uint32 temp_ret)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
wasm_runtime_set_temp_ret(module_inst, temp_ret);
|
||||
}
|
||||
|
||||
static uint32
|
||||
getTempRet0_wrapper(wasm_exec_env_t exec_env)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
return wasm_runtime_get_temp_ret(module_inst);
|
||||
}
|
||||
|
||||
static uint32
|
||||
llvm_bswap_i16_wrapper(wasm_exec_env_t exec_env, uint32 data)
|
||||
{
|
||||
return (data & 0xFFFF0000) | ((data & 0xFF) << 8) | ((data & 0xFF00) >> 8);
|
||||
}
|
||||
|
||||
static uint32
|
||||
llvm_bswap_i32_wrapper(wasm_exec_env_t exec_env, uint32 data)
|
||||
{
|
||||
return ((data & 0xFF) << 24) | ((data & 0xFF00) << 8)
|
||||
| ((data & 0xFF0000) >> 8) | ((data & 0xFF000000) >> 24);
|
||||
}
|
||||
|
||||
static uint32
|
||||
bitshift64Lshr_wrapper(wasm_exec_env_t exec_env, uint32 uint64_part0,
|
||||
uint32 uint64_part1, uint32 bits)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
union {
|
||||
uint64 value;
|
||||
uint32 parts[2];
|
||||
} u;
|
||||
|
||||
u.parts[0] = uint64_part0;
|
||||
u.parts[1] = uint64_part1;
|
||||
|
||||
u.value >>= bits;
|
||||
/* return low 32bit and save high 32bit to temp ret */
|
||||
wasm_runtime_set_temp_ret(module_inst, (uint32)(u.value >> 32));
|
||||
return (uint32)u.value;
|
||||
}
|
||||
|
||||
static uint32
|
||||
bitshift64Shl_wrapper(wasm_exec_env_t exec_env, uint32 int64_part0,
|
||||
uint32 int64_part1, uint32 bits)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
union {
|
||||
int64 value;
|
||||
uint32 parts[2];
|
||||
} u;
|
||||
|
||||
u.parts[0] = int64_part0;
|
||||
u.parts[1] = int64_part1;
|
||||
|
||||
u.value <<= bits;
|
||||
/* return low 32bit and save high 32bit to temp ret */
|
||||
wasm_runtime_set_temp_ret(module_inst, (uint32)(u.value >> 32));
|
||||
return (uint32)u.value;
|
||||
}
|
||||
|
||||
static void
|
||||
llvm_stackrestore_wrapper(wasm_exec_env_t exec_env, uint32 llvm_stack)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
os_printf("_llvm_stackrestore called!\n");
|
||||
wasm_runtime_set_llvm_stack(module_inst, llvm_stack);
|
||||
}
|
||||
|
||||
static uint32
|
||||
llvm_stacksave_wrapper(wasm_exec_env_t exec_env)
|
||||
{
|
||||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
os_printf("_llvm_stacksave called!\n");
|
||||
return wasm_runtime_get_llvm_stack(module_inst);
|
||||
}
|
||||
|
||||
static uint32
|
||||
emscripten_memcpy_big_wrapper(wasm_exec_env_t exec_env, void *dst,
|
||||
const void *src, uint32 size)
|
||||
@ -1108,14 +1015,6 @@ static NativeSymbol native_symbols_libc_builtin[] = {
|
||||
REG_NATIVE_FUNC(tolower, "(i)i"),
|
||||
REG_NATIVE_FUNC(toupper, "(i)i"),
|
||||
REG_NATIVE_FUNC(isalnum, "(i)i"),
|
||||
REG_NATIVE_FUNC(setTempRet0, "(i)"),
|
||||
REG_NATIVE_FUNC(getTempRet0, "()i"),
|
||||
REG_NATIVE_FUNC(llvm_bswap_i16, "(i)i"),
|
||||
REG_NATIVE_FUNC(llvm_bswap_i32, "(i)i"),
|
||||
REG_NATIVE_FUNC(bitshift64Lshr, "(iii)i"),
|
||||
REG_NATIVE_FUNC(bitshift64Shl, "(iii)i"),
|
||||
REG_NATIVE_FUNC(llvm_stackrestore, "(i)"),
|
||||
REG_NATIVE_FUNC(llvm_stacksave, "()i"),
|
||||
REG_NATIVE_FUNC(emscripten_memcpy_big, "(**~)i"),
|
||||
REG_NATIVE_FUNC(abort, "(i)"),
|
||||
REG_NATIVE_FUNC(abortStackOverflow, "(i)"),
|
||||
|
||||
@ -25,8 +25,8 @@
|
||||
|
||||
// On Linux, prefer to use getrandom, though it isn't available in
|
||||
// GLIBC before 2.25.
|
||||
#if defined(__linux__) \
|
||||
&& (!defined(__GLIBC__) || __GLIBC__ > 2 \
|
||||
#if (defined(__linux__) || defined(ESP_PLATFORM)) \
|
||||
&& (!defined(__GLIBC__) || __GLIBC__ > 2 \
|
||||
|| (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25))
|
||||
#define CONFIG_HAS_GETRANDOM 1
|
||||
#else
|
||||
@ -39,13 +39,14 @@
|
||||
#define CONFIG_HAS_CAP_ENTER 0
|
||||
#endif
|
||||
|
||||
#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__EMSCRIPTEN__)
|
||||
#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__EMSCRIPTEN__) \
|
||||
&& !defined(ESP_PLATFORM)
|
||||
#define CONFIG_HAS_CLOCK_NANOSLEEP 1
|
||||
#else
|
||||
#define CONFIG_HAS_CLOCK_NANOSLEEP 0
|
||||
#endif
|
||||
|
||||
#if !defined(__APPLE__) && !defined(__FreeBSD__)
|
||||
#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(ESP_PLATFORM)
|
||||
#define CONFIG_HAS_FDATASYNC 1
|
||||
#else
|
||||
#define CONFIG_HAS_FDATASYNC 0
|
||||
@ -63,13 +64,13 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __APPLE__
|
||||
#if !defined(__APPLE__) && !defined(ESP_PLATFORM)
|
||||
#define CONFIG_HAS_POSIX_FALLOCATE 1
|
||||
#else
|
||||
#define CONFIG_HAS_POSIX_FALLOCATE 0
|
||||
#endif
|
||||
|
||||
#ifndef __APPLE__
|
||||
#if !defined(__APPLE__) && !defined(ESP_PLATFORM)
|
||||
#define CONFIG_HAS_PREADV 1
|
||||
#else
|
||||
#define CONFIG_HAS_PREADV 0
|
||||
@ -87,7 +88,7 @@
|
||||
#define CONFIG_HAS_PTHREAD_CONDATTR_SETCLOCK 0
|
||||
#endif
|
||||
|
||||
#ifndef __APPLE__
|
||||
#if !defined(__APPLE__) && !defined(ESP_PLATFORM)
|
||||
#define CONFIG_HAS_PWRITEV 1
|
||||
#else
|
||||
#define CONFIG_HAS_PWRITEV 0
|
||||
|
||||
Reference in New Issue
Block a user