mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-02-06 15:05:19 +00:00
Implement pthread_cond_broadcast wrapper for lib-pthread (#982)
Implement pthread_cond_broadcast wrapper for lib-pthread - support pthread_cond_broadcast wrapper for posix/linux-sgx/windows - update document for building multi-thread wasm app with emcc
This commit is contained in:
parent
5631a2aa18
commit
90a0057d33
|
@ -718,6 +718,13 @@ pthread_self_wrapper(wasm_exec_env_t exec_env)
|
||||||
return args->info_node->handle;
|
return args->info_node->handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* emcc use __pthread_self rather than pthread_self */
|
||||||
|
static int32
|
||||||
|
__pthread_self_wrapper(wasm_exec_env_t exec_env)
|
||||||
|
{
|
||||||
|
return pthread_self_wrapper(exec_env);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pthread_exit_wrapper(wasm_exec_env_t exec_env, int32 retval_offset)
|
pthread_exit_wrapper(wasm_exec_env_t exec_env, int32 retval_offset)
|
||||||
{
|
{
|
||||||
|
@ -926,6 +933,16 @@ pthread_cond_signal_wrapper(wasm_exec_env_t exec_env, uint32 *cond)
|
||||||
return os_cond_signal(info_node->u.cond);
|
return os_cond_signal(info_node->u.cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32
|
||||||
|
pthread_cond_broadcast_wrapper(wasm_exec_env_t exec_env, uint32 *cond)
|
||||||
|
{
|
||||||
|
ThreadInfoNode *info_node = get_thread_info(exec_env, *cond);
|
||||||
|
if (!info_node || info_node->type != T_COND)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return os_cond_broadcast(info_node->u.cond);
|
||||||
|
}
|
||||||
|
|
||||||
static int32
|
static int32
|
||||||
pthread_cond_destroy_wrapper(wasm_exec_env_t exec_env, uint32 *cond)
|
pthread_cond_destroy_wrapper(wasm_exec_env_t exec_env, uint32 *cond)
|
||||||
{
|
{
|
||||||
|
@ -1079,6 +1096,7 @@ static NativeSymbol native_symbols_lib_pthread[] = {
|
||||||
REG_NATIVE_FUNC(pthread_detach, "(i)i"),
|
REG_NATIVE_FUNC(pthread_detach, "(i)i"),
|
||||||
REG_NATIVE_FUNC(pthread_cancel, "(i)i"),
|
REG_NATIVE_FUNC(pthread_cancel, "(i)i"),
|
||||||
REG_NATIVE_FUNC(pthread_self, "()i"),
|
REG_NATIVE_FUNC(pthread_self, "()i"),
|
||||||
|
REG_NATIVE_FUNC(__pthread_self, "()i"),
|
||||||
REG_NATIVE_FUNC(pthread_exit, "(i)"),
|
REG_NATIVE_FUNC(pthread_exit, "(i)"),
|
||||||
REG_NATIVE_FUNC(pthread_mutex_init, "(**)i"),
|
REG_NATIVE_FUNC(pthread_mutex_init, "(**)i"),
|
||||||
REG_NATIVE_FUNC(pthread_mutex_lock, "(*)i"),
|
REG_NATIVE_FUNC(pthread_mutex_lock, "(*)i"),
|
||||||
|
@ -1088,6 +1106,7 @@ static NativeSymbol native_symbols_lib_pthread[] = {
|
||||||
REG_NATIVE_FUNC(pthread_cond_wait, "(**)i"),
|
REG_NATIVE_FUNC(pthread_cond_wait, "(**)i"),
|
||||||
REG_NATIVE_FUNC(pthread_cond_timedwait, "(**I)i"),
|
REG_NATIVE_FUNC(pthread_cond_timedwait, "(**I)i"),
|
||||||
REG_NATIVE_FUNC(pthread_cond_signal, "(*)i"),
|
REG_NATIVE_FUNC(pthread_cond_signal, "(*)i"),
|
||||||
|
REG_NATIVE_FUNC(pthread_cond_broadcast, "(*)i"),
|
||||||
REG_NATIVE_FUNC(pthread_cond_destroy, "(*)i"),
|
REG_NATIVE_FUNC(pthread_cond_destroy, "(*)i"),
|
||||||
REG_NATIVE_FUNC(pthread_key_create, "(*i)i"),
|
REG_NATIVE_FUNC(pthread_key_create, "(*i)i"),
|
||||||
REG_NATIVE_FUNC(pthread_setspecific, "(ii)i"),
|
REG_NATIVE_FUNC(pthread_setspecific, "(ii)i"),
|
||||||
|
|
|
@ -262,6 +262,17 @@ os_cond_signal(korp_cond *cond)
|
||||||
return BHT_OK;
|
return BHT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_cond_broadcast(korp_cond *cond)
|
||||||
|
{
|
||||||
|
assert(cond);
|
||||||
|
|
||||||
|
if (pthread_cond_broadcast(cond) != BHT_OK)
|
||||||
|
return BHT_ERROR;
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
os_thread_join(korp_tid thread, void **value_ptr)
|
os_thread_join(korp_tid thread, void **value_ptr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -179,6 +179,16 @@ os_cond_reltimedwait(korp_cond *cond, korp_mutex *mutex, uint64 useconds);
|
||||||
int
|
int
|
||||||
os_cond_signal(korp_cond *cond);
|
os_cond_signal(korp_cond *cond);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Broadcast the condition variable
|
||||||
|
*
|
||||||
|
* @param cond condition variable
|
||||||
|
*
|
||||||
|
* @return 0 if success
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
os_cond_broadcast(korp_cond *cond);
|
||||||
|
|
||||||
/****************************************************
|
/****************************************************
|
||||||
* Section 2 *
|
* Section 2 *
|
||||||
* Socket support *
|
* Socket support *
|
||||||
|
|
|
@ -164,6 +164,19 @@ os_cond_signal(korp_cond *cond)
|
||||||
return BHT_OK;
|
return BHT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_cond_broadcast(korp_cond *cond)
|
||||||
|
{
|
||||||
|
#ifndef SGX_DISABLE_PTHREAD
|
||||||
|
assert(cond);
|
||||||
|
|
||||||
|
if (pthread_cond_broadcast(cond) != BHT_OK)
|
||||||
|
return BHT_ERROR;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
os_thread_join(korp_tid thread, void **value_ptr)
|
os_thread_join(korp_tid thread, void **value_ptr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -567,6 +567,24 @@ os_cond_signal(korp_cond *cond)
|
||||||
return BHT_OK;
|
return BHT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_cond_broadcast(korp_cond *cond)
|
||||||
|
{
|
||||||
|
/* Signal all of the wait node of wait list */
|
||||||
|
os_mutex_lock(&cond->wait_list_lock);
|
||||||
|
if (cond->thread_wait_list) {
|
||||||
|
os_thread_wait_node *p = cond->thread_wait_list;
|
||||||
|
while (p) {
|
||||||
|
os_sem_signal(&p->sem);
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
os_mutex_unlock(&cond->wait_list_lock);
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static os_thread_local_attribute uint8 *thread_stack_boundary = NULL;
|
static os_thread_local_attribute uint8 *thread_stack_boundary = NULL;
|
||||||
|
|
||||||
static ULONG
|
static ULONG
|
||||||
|
|
|
@ -80,8 +80,17 @@ Then build the program with this command:
|
||||||
|
|
||||||
**Build with EMCC**
|
**Build with EMCC**
|
||||||
|
|
||||||
|
> Note: This document is based on `emcc 2.0.26`, other version may not work with these commands
|
||||||
|
|
||||||
EMCC's `-pthread` option is not compatible with standalone mode, we need to pass `-mbulk-memory -matomics` to the compiler and `--shared-memory,--no-check-features` to linker manually
|
EMCC's `-pthread` option is not compatible with standalone mode, we need to pass `-mbulk-memory -matomics` to the compiler and `--shared-memory,--no-check-features` to linker manually
|
||||||
|
|
||||||
|
EMCC provides some empty implementation for pthread related APIs, we need to remove them from emcc's libc.
|
||||||
|
``` bash
|
||||||
|
cd ${emsdk_dir}/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten
|
||||||
|
emar d libc.a library_pthread_stub.o
|
||||||
|
emranlib libc.a
|
||||||
|
```
|
||||||
|
|
||||||
``` bash
|
``` bash
|
||||||
emcc -O3 -mbulk-memory -matomics -s MALLOC="none" \
|
emcc -O3 -mbulk-memory -matomics -s MALLOC="none" \
|
||||||
-Wl,--export=__data_end,--export=__heap_base \
|
-Wl,--export=__data_end,--export=__heap_base \
|
||||||
|
@ -166,6 +175,8 @@ int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||||
|
|
||||||
int pthread_cond_signal(pthread_cond_t *cond);
|
int pthread_cond_signal(pthread_cond_t *cond);
|
||||||
|
|
||||||
|
int pthread_cond_broadcast(pthread_cond_t *cond);
|
||||||
|
|
||||||
int pthread_cond_destroy(pthread_cond_t *cond);
|
int pthread_cond_destroy(pthread_cond_t *cond);
|
||||||
|
|
||||||
/* Pthread key APIs */
|
/* Pthread key APIs */
|
||||||
|
|
|
@ -19,48 +19,70 @@ typedef unsigned int pthread_cond_t;
|
||||||
typedef unsigned int pthread_key_t;
|
typedef unsigned int pthread_key_t;
|
||||||
|
|
||||||
/* Thread APIs */
|
/* Thread APIs */
|
||||||
int pthread_create(pthread_t *thread, const void *attr,
|
int
|
||||||
|
pthread_create(pthread_t *thread, const void *attr,
|
||||||
void *(*start_routine)(void *), void *arg);
|
void *(*start_routine)(void *), void *arg);
|
||||||
|
|
||||||
int pthread_join(pthread_t thread, void **retval);
|
int
|
||||||
|
pthread_join(pthread_t thread, void **retval);
|
||||||
|
|
||||||
int pthread_detach(pthread_t thread);
|
int
|
||||||
|
pthread_detach(pthread_t thread);
|
||||||
|
|
||||||
int pthread_cancel(pthread_t thread);
|
int
|
||||||
|
pthread_cancel(pthread_t thread);
|
||||||
|
|
||||||
pthread_t pthread_self(void);
|
pthread_t
|
||||||
|
pthread_self(void);
|
||||||
|
|
||||||
void pthread_exit(void *retval);
|
void
|
||||||
|
pthread_exit(void *retval);
|
||||||
|
|
||||||
/* Mutex APIs */
|
/* Mutex APIs */
|
||||||
int pthread_mutex_init(pthread_mutex_t *mutex, const void *attr);
|
int
|
||||||
|
pthread_mutex_init(pthread_mutex_t *mutex, const void *attr);
|
||||||
|
|
||||||
int pthread_mutex_lock(pthread_mutex_t *mutex);
|
int
|
||||||
|
pthread_mutex_lock(pthread_mutex_t *mutex);
|
||||||
|
|
||||||
int pthread_mutex_unlock(pthread_mutex_t *mutex);
|
int
|
||||||
|
pthread_mutex_unlock(pthread_mutex_t *mutex);
|
||||||
|
|
||||||
int pthread_mutex_destroy(pthread_mutex_t *mutex);
|
int
|
||||||
|
pthread_mutex_destroy(pthread_mutex_t *mutex);
|
||||||
|
|
||||||
/* Cond APIs */
|
/* Cond APIs */
|
||||||
int pthread_cond_init(pthread_cond_t *cond, const void *attr);
|
int
|
||||||
|
pthread_cond_init(pthread_cond_t *cond, const void *attr);
|
||||||
|
|
||||||
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
|
int
|
||||||
|
pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
|
||||||
|
|
||||||
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
int
|
||||||
|
pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
|
||||||
uint64_t useconds);
|
uint64_t useconds);
|
||||||
|
|
||||||
int pthread_cond_signal(pthread_cond_t *cond);
|
int
|
||||||
|
pthread_cond_signal(pthread_cond_t *cond);
|
||||||
|
|
||||||
int pthread_cond_destroy(pthread_cond_t *cond);
|
int
|
||||||
|
pthread_cond_broadcast(pthread_cond_t *cond);
|
||||||
|
|
||||||
|
int
|
||||||
|
pthread_cond_destroy(pthread_cond_t *cond);
|
||||||
|
|
||||||
/* Pthread key APIs */
|
/* Pthread key APIs */
|
||||||
int pthread_key_create(pthread_key_t *key, void (*destructor)(void *));
|
int
|
||||||
|
pthread_key_create(pthread_key_t *key, void (*destructor)(void *));
|
||||||
|
|
||||||
int pthread_setspecific(pthread_key_t key, const void *value);
|
int
|
||||||
|
pthread_setspecific(pthread_key_t key, const void *value);
|
||||||
|
|
||||||
void *pthread_getspecific(pthread_key_t key);
|
void *
|
||||||
|
pthread_getspecific(pthread_key_t key);
|
||||||
|
|
||||||
int pthread_key_delete(pthread_key_t key);
|
int
|
||||||
|
pthread_key_delete(pthread_key_t key);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user