mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2024-11-26 07:21:54 +00:00
Implement module instance context APIs (#2436)
Introduce module instance context APIs which can set one or more contexts created by the embedder for a wasm module instance: ```C wasm_runtime_create_context_key wasm_runtime_destroy_context_key wasm_runtime_set_context wasm_runtime_set_context_spread wasm_runtime_get_context ``` And make libc-wasi use it and set wasi context as the first context bound to the wasm module instance. Also add samples. Refer to https://github.com/bytecodealliance/wasm-micro-runtime/issues/2460.
This commit is contained in:
parent
af2f3c8759
commit
6c846acc59
|
@ -378,6 +378,10 @@ if (WAMR_BUILD_WASM_CACHE EQUAL 1)
|
|||
add_definitions (-DWASM_ENABLE_WASM_CACHE=1)
|
||||
message (" Wasm files cache enabled")
|
||||
endif ()
|
||||
if (WAMR_BUILD_MODULE_INST_CONTEXT EQUAL 1)
|
||||
add_definitions (-DWASM_ENABLE_MODULE_INST_CONTEXT=1)
|
||||
message (" Module instance context enabled")
|
||||
endif ()
|
||||
if (WAMR_BUILD_GC_HEAP_VERIFY EQUAL 1)
|
||||
add_definitions (-DWASM_ENABLE_GC_VERIFY=1)
|
||||
message (" GC heap verification enabled")
|
||||
|
|
|
@ -91,8 +91,10 @@ endif ()
|
|||
|
||||
if (WAMR_BUILD_LIBC_UVWASI EQUAL 1)
|
||||
include (${IWASM_DIR}/libraries/libc-uvwasi/libc_uvwasi.cmake)
|
||||
set (WAMR_BUILD_MODULE_INST_CONTEXT 1)
|
||||
elseif (WAMR_BUILD_LIBC_WASI EQUAL 1)
|
||||
include (${IWASM_DIR}/libraries/libc-wasi/libc_wasi.cmake)
|
||||
set (WAMR_BUILD_MODULE_INST_CONTEXT 1)
|
||||
endif ()
|
||||
|
||||
if (WAMR_BUILD_LIB_PTHREAD_SEMAPHORE EQUAL 1)
|
||||
|
|
|
@ -480,4 +480,9 @@
|
|||
#define WASM_MEM_DUAL_BUS_MIRROR 0
|
||||
#endif
|
||||
|
||||
/* The max number of module instance contexts. */
|
||||
#ifndef WASM_MAX_INSTANCE_CONTEXTS
|
||||
#define WASM_MAX_INSTANCE_CONTEXTS 8
|
||||
#endif
|
||||
|
||||
#endif /* end of _CONFIG_H_ */
|
||||
|
|
|
@ -1276,12 +1276,10 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
|
|||
->common.c_api_func_imports);
|
||||
|
||||
if (!is_sub_inst) {
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst);
|
||||
#endif
|
||||
#if WASM_ENABLE_WASI_NN != 0
|
||||
wasi_nn_destroy(module_inst);
|
||||
#endif
|
||||
wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst);
|
||||
}
|
||||
|
||||
wasm_runtime_free(module_inst);
|
||||
|
|
|
@ -6,6 +6,15 @@
|
|||
#include "wasm_native.h"
|
||||
#include "wasm_runtime_common.h"
|
||||
#include "bh_log.h"
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
#include "../interpreter/wasm_runtime.h"
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
#include "../aot/aot_runtime.h"
|
||||
#endif
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
#include "../libraries/thread-mgr/thread_manager.h"
|
||||
#endif
|
||||
|
||||
#if !defined(BH_PLATFORM_ZEPHYR) && !defined(BH_PLATFORM_ALIOS_THINGS) \
|
||||
&& !defined(BH_PLATFORM_OPENRTOS) && !defined(BH_PLATFORM_ESP_IDF)
|
||||
|
@ -22,6 +31,10 @@
|
|||
|
||||
static NativeSymbolsList g_native_symbols_list = NULL;
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
static void *g_wasi_context_key;
|
||||
#endif /* WASM_ENABLE_LIBC_WASI */
|
||||
|
||||
uint32
|
||||
get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis);
|
||||
|
||||
|
@ -394,6 +407,155 @@ wasm_native_unregister_natives(const char *module_name,
|
|||
return false;
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_MODULE_INST_CONTEXT != 0
|
||||
static uint32
|
||||
context_key_to_idx(void *key)
|
||||
{
|
||||
bh_assert(key != NULL);
|
||||
uint32 idx = (uint32)(uintptr_t)key;
|
||||
bh_assert(idx > 0);
|
||||
bh_assert(idx <= WASM_MAX_INSTANCE_CONTEXTS);
|
||||
return idx - 1;
|
||||
}
|
||||
|
||||
static void *
|
||||
context_idx_to_key(uint32 idx)
|
||||
{
|
||||
bh_assert(idx < WASM_MAX_INSTANCE_CONTEXTS);
|
||||
return (void *)(uintptr_t)(idx + 1);
|
||||
}
|
||||
|
||||
typedef void (*dtor_t)(WASMModuleInstanceCommon *, void *);
|
||||
static dtor_t g_context_dtors[WASM_MAX_INSTANCE_CONTEXTS];
|
||||
|
||||
static void
|
||||
dtor_noop(WASMModuleInstanceCommon *inst, void *ctx)
|
||||
{}
|
||||
|
||||
void *
|
||||
wasm_native_create_context_key(void (*dtor)(WASMModuleInstanceCommon *inst,
|
||||
void *ctx))
|
||||
{
|
||||
uint32 i;
|
||||
for (i = 0; i < WASM_MAX_INSTANCE_CONTEXTS; i++) {
|
||||
if (g_context_dtors[i] == NULL) {
|
||||
if (dtor == NULL) {
|
||||
dtor = dtor_noop;
|
||||
}
|
||||
g_context_dtors[i] = dtor;
|
||||
return context_idx_to_key(i);
|
||||
}
|
||||
}
|
||||
LOG_ERROR("failed to allocate instance context key");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
wasm_native_destroy_context_key(void *key)
|
||||
{
|
||||
uint32 idx = context_key_to_idx(key);
|
||||
bh_assert(g_context_dtors[idx] != NULL);
|
||||
g_context_dtors[idx] = NULL;
|
||||
}
|
||||
|
||||
static WASMModuleInstanceExtraCommon *
|
||||
wasm_module_inst_extra_common(WASMModuleInstanceCommon *inst)
|
||||
{
|
||||
#if WASM_ENABLE_INTERP != 0
|
||||
if (inst->module_type == Wasm_Module_Bytecode) {
|
||||
return &((WASMModuleInstance *)inst)->e->common;
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_AOT != 0
|
||||
if (inst->module_type == Wasm_Module_AoT) {
|
||||
return &((AOTModuleInstanceExtra *)((AOTModuleInstance *)inst)->e)
|
||||
->common;
|
||||
}
|
||||
#endif
|
||||
bh_assert(false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
wasm_native_set_context(WASMModuleInstanceCommon *inst, void *key, void *ctx)
|
||||
{
|
||||
uint32 idx = context_key_to_idx(key);
|
||||
WASMModuleInstanceExtraCommon *common = wasm_module_inst_extra_common(inst);
|
||||
common->contexts[idx] = ctx;
|
||||
}
|
||||
|
||||
void
|
||||
wasm_native_set_context_spread(WASMModuleInstanceCommon *inst, void *key,
|
||||
void *ctx)
|
||||
{
|
||||
#if WASM_ENABLE_THREAD_MGR != 0
|
||||
wasm_cluster_set_context(inst, key, ctx);
|
||||
#else
|
||||
wasm_native_set_context(inst, key, ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
void *
|
||||
wasm_native_get_context(WASMModuleInstanceCommon *inst, void *key)
|
||||
{
|
||||
uint32 idx = context_key_to_idx(key);
|
||||
WASMModuleInstanceExtraCommon *common = wasm_module_inst_extra_common(inst);
|
||||
return common->contexts[idx];
|
||||
}
|
||||
|
||||
void
|
||||
wasm_native_call_context_dtors(WASMModuleInstanceCommon *inst)
|
||||
{
|
||||
WASMModuleInstanceExtraCommon *common = wasm_module_inst_extra_common(inst);
|
||||
uint32 i;
|
||||
for (i = 0; i < WASM_MAX_INSTANCE_CONTEXTS; i++) {
|
||||
dtor_t dtor = g_context_dtors[i];
|
||||
if (dtor != NULL) {
|
||||
dtor(inst, common->contexts[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
wasm_native_inherit_contexts(WASMModuleInstanceCommon *child,
|
||||
WASMModuleInstanceCommon *parent)
|
||||
{
|
||||
WASMModuleInstanceExtraCommon *parent_common =
|
||||
wasm_module_inst_extra_common(parent);
|
||||
WASMModuleInstanceExtraCommon *child_common =
|
||||
wasm_module_inst_extra_common(child);
|
||||
bh_memcpy_s(child_common->contexts,
|
||||
sizeof(*child_common->contexts) * WASM_MAX_INSTANCE_CONTEXTS,
|
||||
parent_common->contexts,
|
||||
sizeof(*parent_common->contexts) * WASM_MAX_INSTANCE_CONTEXTS);
|
||||
}
|
||||
#endif /* WASM_ENABLE_MODULE_INST_CONTEXT != 0 */
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
WASIContext *
|
||||
wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm)
|
||||
{
|
||||
return wasm_native_get_context(module_inst_comm, g_wasi_context_key);
|
||||
}
|
||||
|
||||
void
|
||||
wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm,
|
||||
WASIContext *wasi_ctx)
|
||||
{
|
||||
return wasm_native_set_context(module_inst_comm, g_wasi_context_key,
|
||||
wasi_ctx);
|
||||
}
|
||||
|
||||
static void
|
||||
wasi_context_dtor(WASMModuleInstanceCommon *inst, void *ctx)
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
return;
|
||||
}
|
||||
wasm_runtime_destroy_wasi(inst);
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_LIBC_WASI */
|
||||
|
||||
bool
|
||||
wasm_native_init()
|
||||
{
|
||||
|
@ -420,6 +582,10 @@ wasm_native_init()
|
|||
#endif /* WASM_ENABLE_SPEC_TEST */
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
g_wasi_context_key = wasm_native_create_context_key(wasi_context_dtor);
|
||||
if (g_wasi_context_key == NULL) {
|
||||
goto fail;
|
||||
}
|
||||
n_native_symbols = get_libc_wasi_export_apis(&native_symbols);
|
||||
if (!wasm_native_register_natives("wasi_unstable", native_symbols,
|
||||
n_native_symbols))
|
||||
|
@ -507,6 +673,12 @@ wasm_native_destroy()
|
|||
{
|
||||
NativeSymbolsNode *node, *node_next;
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
if (g_wasi_context_key != NULL) {
|
||||
wasm_native_destroy_context_key(g_wasi_context_key);
|
||||
g_wasi_context_key = NULL;
|
||||
}
|
||||
#endif
|
||||
#if WASM_ENABLE_LIB_PTHREAD != 0
|
||||
lib_pthread_destroy();
|
||||
#endif
|
||||
|
|
|
@ -68,6 +68,36 @@ bool
|
|||
wasm_native_unregister_natives(const char *module_name,
|
||||
NativeSymbol *native_symbols);
|
||||
|
||||
#if WASM_ENABLE_MODULE_INST_CONTEXT != 0
|
||||
struct WASMModuleInstanceCommon;
|
||||
|
||||
void *
|
||||
wasm_native_create_context_key(
|
||||
void (*dtor)(struct WASMModuleInstanceCommon *inst, void *ctx));
|
||||
|
||||
void
|
||||
wasm_native_destroy_context_key(void *key);
|
||||
|
||||
void
|
||||
wasm_native_set_context(struct WASMModuleInstanceCommon *inst, void *key,
|
||||
void *ctx);
|
||||
void
|
||||
wasm_native_set_context_spread(struct WASMModuleInstanceCommon *inst, void *key,
|
||||
void *ctx);
|
||||
void *
|
||||
wasm_native_get_context(struct WASMModuleInstanceCommon *inst, void *key);
|
||||
|
||||
void
|
||||
wasm_native_call_context_dtors(struct WASMModuleInstanceCommon *inst);
|
||||
|
||||
void
|
||||
wasm_native_inherit_contexts(struct WASMModuleInstanceCommon *child,
|
||||
struct WASMModuleInstanceCommon *parent);
|
||||
#else /* WASM_ENABLE_MODULE_INST_CONTEXT */
|
||||
#define wasm_native_call_context_dtors(inst) (void)(inst)
|
||||
#define wasm_native_inherit_contexts(child, parent) (void)(parent)
|
||||
#endif /* WASM_ENABLE_MODULE_INST_CONTEXT */
|
||||
|
||||
bool
|
||||
wasm_native_init();
|
||||
|
||||
|
|
|
@ -3311,27 +3311,6 @@ wasm_runtime_get_wasi_exit_code(WASMModuleInstanceCommon *module_inst)
|
|||
#endif
|
||||
return wasi_ctx->exit_code;
|
||||
}
|
||||
|
||||
WASIContext *
|
||||
wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm)
|
||||
{
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
|
||||
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
return module_inst->wasi_ctx;
|
||||
}
|
||||
|
||||
void
|
||||
wasm_runtime_set_wasi_ctx(WASMModuleInstanceCommon *module_inst_comm,
|
||||
WASIContext *wasi_ctx)
|
||||
{
|
||||
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
|
||||
|
||||
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|
||||
|| module_inst_comm->module_type == Wasm_Module_AoT);
|
||||
module_inst->wasi_ctx = wasi_ctx;
|
||||
}
|
||||
#endif /* end of WASM_ENABLE_LIBC_WASI */
|
||||
|
||||
WASMModuleCommon *
|
||||
|
@ -5681,3 +5660,37 @@ wasm_runtime_is_import_global_linked(const char *module_name,
|
|||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_MODULE_INST_CONTEXT != 0
|
||||
void *
|
||||
wasm_runtime_create_context_key(void (*dtor)(WASMModuleInstanceCommon *inst,
|
||||
void *ctx))
|
||||
{
|
||||
return wasm_native_create_context_key(dtor);
|
||||
}
|
||||
|
||||
void
|
||||
wasm_runtime_destroy_context_key(void *key)
|
||||
{
|
||||
wasm_native_destroy_context_key(key);
|
||||
}
|
||||
|
||||
void
|
||||
wasm_runtime_set_context(WASMModuleInstanceCommon *inst, void *key, void *ctx)
|
||||
{
|
||||
wasm_native_set_context(inst, key, ctx);
|
||||
}
|
||||
|
||||
void
|
||||
wasm_runtime_set_context_spread(WASMModuleInstanceCommon *inst, void *key,
|
||||
void *ctx)
|
||||
{
|
||||
wasm_native_set_context_spread(inst, key, ctx);
|
||||
}
|
||||
|
||||
void *
|
||||
wasm_runtime_get_context(WASMModuleInstanceCommon *inst, void *key)
|
||||
{
|
||||
return wasm_native_get_context(inst, key);
|
||||
}
|
||||
#endif /* WASM_ENABLE_MODULE_INST_CONTEXT != 0 */
|
||||
|
|
|
@ -939,6 +939,26 @@ WASM_RUNTIME_API_EXTERN bool
|
|||
wasm_runtime_unregister_natives(const char *module_name,
|
||||
NativeSymbol *native_symbols);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN void *
|
||||
wasm_runtime_create_context_key(void (*dtor)(WASMModuleInstanceCommon *inst,
|
||||
void *ctx));
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_destroy_context_key(void *key);
|
||||
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_set_context(WASMModuleInstanceCommon *inst, void *key, void *ctx);
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_set_context_spread(WASMModuleInstanceCommon *inst, void *key,
|
||||
void *ctx);
|
||||
/* See wasm_export.h for description */
|
||||
WASM_RUNTIME_API_EXTERN void *
|
||||
wasm_runtime_get_context(WASMModuleInstanceCommon *inst, void *key);
|
||||
|
||||
bool
|
||||
wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
|
||||
const WASMType *func_type, const char *signature,
|
||||
|
|
|
@ -1456,6 +1456,74 @@ WASM_RUNTIME_API_EXTERN void
|
|||
wasm_runtime_set_enlarge_mem_error_callback(
|
||||
const enlarge_memory_error_callback_t callback);
|
||||
|
||||
/*
|
||||
* module instance context APIs
|
||||
* wasm_runtime_create_context_key
|
||||
* wasm_runtime_destroy_context_key
|
||||
* wasm_runtime_set_context
|
||||
* wasm_runtime_set_context_spread
|
||||
* wasm_runtime_get_context
|
||||
*
|
||||
* This set of APIs is intended to be used by an embedder which provides
|
||||
* extra sets of native functions, which need per module instance state
|
||||
* and are maintained outside of the WAMR tree.
|
||||
*
|
||||
* It's modelled after the pthread specific API.
|
||||
*
|
||||
* wasm_runtime_set_context_spread is similar to
|
||||
* wasm_runtime_set_context, except that
|
||||
* wasm_runtime_set_context_spread applies the change
|
||||
* to all threads in the cluster.
|
||||
* It's an undefined behavior if multiple threads in a cluster call
|
||||
* wasm_runtime_set_context_spread on the same key
|
||||
* simultaneously. It's a caller's resposibility to perform necessary
|
||||
* serialization if necessary. For example:
|
||||
*
|
||||
* if (wasm_runtime_get_context(inst, key) == NULL) {
|
||||
* newctx = alloc_and_init(...);
|
||||
* lock(some_lock);
|
||||
* if (wasm_runtime_get_context(inst, key) == NULL) {
|
||||
* // this thread won the race
|
||||
* wasm_runtime_set_context_spread(inst, key, newctx);
|
||||
* newctx = NULL;
|
||||
* }
|
||||
* unlock(some_lock);
|
||||
* if (newctx != NULL) {
|
||||
* // this thread lost the race, free it
|
||||
* cleanup_and_free(newctx);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Note: dynamic key create/destroy while instances are live is not
|
||||
* implemented as of writing this.
|
||||
* it's caller's resposibility to ensure destorying all module instances
|
||||
* before calling wasm_runtime_create_context_key or
|
||||
* wasm_runtime_destroy_context_key.
|
||||
* otherwise, it's an undefined behavior.
|
||||
*
|
||||
* Note about threads:
|
||||
* - When spawning a thread, the contexts (the pointers given to
|
||||
* wasm_runtime_set_context) are copied from the parent
|
||||
* instance.
|
||||
* - The destructor is called only on the main instance.
|
||||
*/
|
||||
|
||||
WASM_RUNTIME_API_EXTERN void *
|
||||
wasm_runtime_create_context_key(
|
||||
void (*dtor)(wasm_module_inst_t inst, void *ctx));
|
||||
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_destroy_context_key(void *key);
|
||||
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_set_context(wasm_module_inst_t inst, void *key,
|
||||
void *ctx);
|
||||
WASM_RUNTIME_API_EXTERN void
|
||||
wasm_runtime_set_context_spread(wasm_module_inst_t inst, void *key,
|
||||
void *ctx);
|
||||
WASM_RUNTIME_API_EXTERN void *
|
||||
wasm_runtime_get_context(wasm_module_inst_t inst, void *key);
|
||||
|
||||
/* clang-format on */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -2233,12 +2233,10 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
|
|||
wasm_runtime_free(module_inst->e->common.c_api_func_imports);
|
||||
|
||||
if (!is_sub_inst) {
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
wasm_runtime_destroy_wasi((WASMModuleInstanceCommon *)module_inst);
|
||||
#endif
|
||||
#if WASM_ENABLE_WASI_NN != 0
|
||||
wasi_nn_destroy(module_inst);
|
||||
#endif
|
||||
wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst);
|
||||
}
|
||||
|
||||
wasm_runtime_free(module_inst);
|
||||
|
|
|
@ -212,6 +212,7 @@ typedef struct CApiFuncImport {
|
|||
|
||||
/* The common part of WASMModuleInstanceExtra and AOTModuleInstanceExtra */
|
||||
typedef struct WASMModuleInstanceExtraCommon {
|
||||
void *contexts[WASM_MAX_INSTANCE_CONTEXTS];
|
||||
CApiFuncImport *c_api_func_imports;
|
||||
/* pointer to the exec env currently used */
|
||||
WASMExecEnv *cur_exec_env;
|
||||
|
@ -299,12 +300,8 @@ struct WASMModuleInstance {
|
|||
it denotes `AOTModule *` */
|
||||
DefPointer(WASMModule *, module);
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI
|
||||
/* WASI context */
|
||||
DefPointer(WASIContext *, wasi_ctx);
|
||||
#else
|
||||
DefPointer(void *, wasi_ctx);
|
||||
#endif
|
||||
DefPointer(void *, used_to_be_wasi_ctx); /* unused */
|
||||
|
||||
DefPointer(WASMExecEnv *, exec_env_singleton);
|
||||
/* Array of function pointers to import functions,
|
||||
not available in AOTModuleInstance */
|
||||
|
|
|
@ -559,9 +559,6 @@ pthread_create_wrapper(wasm_exec_env_t exec_env,
|
|||
uint32 thread_handle;
|
||||
uint32 stack_size = 8192;
|
||||
int32 ret = -1;
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
WASIContext *wasi_ctx;
|
||||
#endif
|
||||
|
||||
bh_assert(module);
|
||||
bh_assert(module_inst);
|
||||
|
@ -588,11 +585,7 @@ pthread_create_wrapper(wasm_exec_env_t exec_env,
|
|||
wasm_runtime_set_custom_data_internal(
|
||||
new_module_inst, wasm_runtime_get_custom_data(module_inst));
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
wasi_ctx = get_wasi_ctx(module_inst);
|
||||
if (wasi_ctx)
|
||||
wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
|
||||
#endif
|
||||
wasm_native_inherit_contexts(new_module_inst, module_inst);
|
||||
|
||||
if (!(wasm_cluster_dup_c_api_imports(new_module_inst, module_inst)))
|
||||
goto fail;
|
||||
|
|
|
@ -80,9 +80,6 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg)
|
|||
int32 thread_id;
|
||||
uint32 stack_size = 8192;
|
||||
int32 ret = -1;
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
WASIContext *wasi_ctx;
|
||||
#endif
|
||||
|
||||
bh_assert(module);
|
||||
bh_assert(module_inst);
|
||||
|
@ -99,11 +96,7 @@ thread_spawn_wrapper(wasm_exec_env_t exec_env, uint32 start_arg)
|
|||
if (!(wasm_cluster_dup_c_api_imports(new_module_inst, module_inst)))
|
||||
goto thread_preparation_fail;
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
|
||||
if (wasi_ctx)
|
||||
wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
|
||||
#endif
|
||||
wasm_native_inherit_contexts(new_module_inst, module_inst);
|
||||
|
||||
start_func = wasm_runtime_lookup_function(new_module_inst,
|
||||
THREAD_START_FUNCTION, NULL);
|
||||
|
|
|
@ -480,9 +480,6 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env)
|
|||
wasm_module_inst_t module_inst = get_module_inst(exec_env);
|
||||
wasm_module_t module;
|
||||
wasm_module_inst_t new_module_inst;
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
WASIContext *wasi_ctx;
|
||||
#endif
|
||||
WASMExecEnv *new_exec_env;
|
||||
uint32 aux_stack_start, aux_stack_size;
|
||||
uint32 stack_size = 8192;
|
||||
|
@ -520,10 +517,7 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env)
|
|||
wasm_runtime_set_custom_data_internal(
|
||||
new_module_inst, wasm_runtime_get_custom_data(module_inst));
|
||||
|
||||
#if WASM_ENABLE_LIBC_WASI != 0
|
||||
wasi_ctx = wasm_runtime_get_wasi_ctx(module_inst);
|
||||
wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
|
||||
#endif
|
||||
wasm_native_inherit_contexts(new_module_inst, module_inst);
|
||||
|
||||
new_exec_env = wasm_exec_env_create_internal(new_module_inst,
|
||||
exec_env->wasm_stack_size);
|
||||
|
@ -1324,6 +1318,48 @@ wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst,
|
|||
}
|
||||
}
|
||||
|
||||
#if WASM_ENABLE_MODULE_INST_CONTEXT != 0
|
||||
struct inst_set_context_data {
|
||||
void *key;
|
||||
void *ctx;
|
||||
};
|
||||
|
||||
static void
|
||||
set_context_visitor(void *node, void *user_data)
|
||||
{
|
||||
WASMExecEnv *curr_exec_env = (WASMExecEnv *)node;
|
||||
WASMModuleInstanceCommon *module_inst = get_module_inst(curr_exec_env);
|
||||
const struct inst_set_context_data *data = user_data;
|
||||
|
||||
wasm_runtime_set_context(module_inst, data->key, data->ctx);
|
||||
}
|
||||
|
||||
void
|
||||
wasm_cluster_set_context(WASMModuleInstanceCommon *module_inst, void *key,
|
||||
void *ctx)
|
||||
{
|
||||
WASMExecEnv *exec_env = wasm_clusters_search_exec_env(module_inst);
|
||||
|
||||
if (exec_env == NULL) {
|
||||
/* Maybe threads have not been started yet. */
|
||||
wasm_runtime_set_context(module_inst, key, ctx);
|
||||
}
|
||||
else {
|
||||
WASMCluster *cluster;
|
||||
struct inst_set_context_data data;
|
||||
data.key = key;
|
||||
data.ctx = ctx;
|
||||
|
||||
cluster = wasm_exec_env_get_cluster(exec_env);
|
||||
bh_assert(cluster);
|
||||
|
||||
os_mutex_lock(&cluster->lock);
|
||||
traverse_list(&cluster->exec_env_list, set_context_visitor, &data);
|
||||
os_mutex_unlock(&cluster->lock);
|
||||
}
|
||||
}
|
||||
#endif /* WASM_ENABLE_MODULE_INST_CONTEXT != 0 */
|
||||
|
||||
bool
|
||||
wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env)
|
||||
{
|
||||
|
|
|
@ -151,6 +151,10 @@ void
|
|||
wasm_cluster_spread_custom_data(WASMModuleInstanceCommon *module_inst,
|
||||
void *custom_data);
|
||||
|
||||
void
|
||||
wasm_cluster_set_context(WASMModuleInstanceCommon *module_inst, void *key,
|
||||
void *ctx);
|
||||
|
||||
bool
|
||||
wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env);
|
||||
|
||||
|
|
|
@ -253,10 +253,18 @@ CSRCS += posix.c
|
|||
CSRCS += random.c
|
||||
CSRCS += str.c
|
||||
VPATH += $(IWASM_ROOT)/libraries/libc-wasi/sandboxed-system-primitives/src
|
||||
# todo: use Kconfig select instead
|
||||
CONFIG_INTERPRETERS_WAMR_MODULE_INSTANCE_CONTEXT = y
|
||||
else
|
||||
CFLAGS += -DWASM_ENABLE_LIBC_WASI=0
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_INTERPRETERS_WAMR_MODULE_INSTANCE_CONTEXT),y)
|
||||
CFLAGS += -DWASM_ENABLE_MODULE_INST_CONTEXT=1
|
||||
else
|
||||
CFLAGS += -DWASM_ENABLE_MODULE_INST_CONTEXT=0
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_INTERPRETERS_WAMR_MULTI_MODULE),y)
|
||||
CFLAGS += -DWASM_ENABLE_MULTI_MODULE=1
|
||||
else
|
||||
|
|
1
samples/inst-context-threads/.gitignore
vendored
Normal file
1
samples/inst-context-threads/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/out/
|
92
samples/inst-context-threads/CMakeLists.txt
Normal file
92
samples/inst-context-threads/CMakeLists.txt
Normal file
|
@ -0,0 +1,92 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
cmake_minimum_required (VERSION 3.14)
|
||||
|
||||
include(CheckPIESupported)
|
||||
|
||||
if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows")
|
||||
project (inst-context)
|
||||
else()
|
||||
project (inst-context C ASM)
|
||||
enable_language (ASM_MASM)
|
||||
endif()
|
||||
|
||||
################ runtime settings ################
|
||||
string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM)
|
||||
if (APPLE)
|
||||
add_definitions(-DBH_PLATFORM_DARWIN)
|
||||
endif ()
|
||||
|
||||
# Reset default linker flags
|
||||
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
|
||||
set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
|
||||
|
||||
# WAMR features switch
|
||||
|
||||
# Set WAMR_BUILD_TARGET, currently values supported:
|
||||
# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]",
|
||||
# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]"
|
||||
if (NOT DEFINED WAMR_BUILD_TARGET)
|
||||
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)")
|
||||
set (WAMR_BUILD_TARGET "AARCH64")
|
||||
elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64")
|
||||
set (WAMR_BUILD_TARGET "RISCV64")
|
||||
elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
# Build as X86_64 by default in 64-bit platform
|
||||
set (WAMR_BUILD_TARGET "X86_64")
|
||||
elseif (CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
# Build as X86_32 by default in 32-bit platform
|
||||
set (WAMR_BUILD_TARGET "X86_32")
|
||||
else ()
|
||||
message(SEND_ERROR "Unsupported build target platform!")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set (CMAKE_BUILD_TYPE Debug)
|
||||
endif ()
|
||||
|
||||
set (WAMR_BUILD_INTERP 1)
|
||||
set (WAMR_BUILD_AOT 1)
|
||||
set (WAMR_BUILD_JIT 0)
|
||||
set (WAMR_BUILD_LIBC_BUILTIN 0)
|
||||
set (WAMR_BUILD_LIB_WASI_THREADS 1)
|
||||
|
||||
if (NOT MSVC)
|
||||
set (WAMR_BUILD_LIBC_WASI 1)
|
||||
endif ()
|
||||
|
||||
if (NOT MSVC)
|
||||
# linker flags
|
||||
if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang"))
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
|
||||
endif ()
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security")
|
||||
if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
|
||||
if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang"))
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register")
|
||||
endif ()
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# build out vmlib
|
||||
set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
|
||||
include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
|
||||
|
||||
add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE})
|
||||
|
||||
################ application related ################
|
||||
include_directories(${CMAKE_CURRENT_LIST_DIR}/src)
|
||||
include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
|
||||
|
||||
add_executable (inst-context src/main.c src/native_impl.c ${UNCOMMON_SHARED_SOURCE})
|
||||
|
||||
check_pie_supported()
|
||||
set_target_properties (inst-context PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
if (APPLE)
|
||||
target_link_libraries (inst-context vmlib -lm -ldl -lpthread)
|
||||
else ()
|
||||
target_link_libraries (inst-context vmlib -lm -ldl -lpthread -lrt)
|
||||
endif ()
|
4
samples/inst-context-threads/README.md
Normal file
4
samples/inst-context-threads/README.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
The "inst-context" sample project
|
||||
=================================
|
||||
|
||||
This sample demonstrates module instance context API.
|
61
samples/inst-context-threads/build.sh
Executable file
61
samples/inst-context-threads/build.sh
Executable file
|
@ -0,0 +1,61 @@
|
|||
#
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
CURR_DIR=$PWD
|
||||
WAMR_DIR=${PWD}/../..
|
||||
OUT_DIR=${PWD}/out
|
||||
|
||||
WASM_APPS=${PWD}/wasm-apps
|
||||
|
||||
|
||||
rm -rf ${OUT_DIR}
|
||||
mkdir ${OUT_DIR}
|
||||
mkdir ${OUT_DIR}/wasm-apps
|
||||
|
||||
|
||||
echo "#####################build inst-context project"
|
||||
cd ${CURR_DIR}
|
||||
mkdir -p cmake_build
|
||||
cd cmake_build
|
||||
cmake ..
|
||||
make -j ${nproc}
|
||||
if [ $? != 0 ];then
|
||||
echo "BUILD_FAIL inst-context exit as $?\n"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
cp -a inst-context ${OUT_DIR}
|
||||
|
||||
echo -e "\n"
|
||||
|
||||
echo "#####################build wasm apps"
|
||||
|
||||
cd ${WASM_APPS}
|
||||
|
||||
for i in `ls *.c`
|
||||
do
|
||||
APP_SRC="$i"
|
||||
OUT_FILE=${i%.*}.wasm
|
||||
|
||||
# use WAMR SDK to build out the .wasm binary
|
||||
# require wasi-sdk with wasi-threads support. (wasi-sdk-20.0 or later)
|
||||
/opt/wasi-sdk/bin/clang \
|
||||
--target=wasm32-wasi-threads \
|
||||
-pthread \
|
||||
-Wl,--import-memory \
|
||||
-Wl,--export-memory \
|
||||
-Wl,--max-memory=655360 \
|
||||
-o ${OUT_DIR}/wasm-apps/${OUT_FILE} ${APP_SRC}
|
||||
|
||||
|
||||
if [ -f ${OUT_DIR}/wasm-apps/${OUT_FILE} ]; then
|
||||
echo "build ${OUT_FILE} success"
|
||||
else
|
||||
echo "build ${OUT_FILE} fail"
|
||||
fi
|
||||
done
|
||||
echo "####################build wasm apps done"
|
3
samples/inst-context-threads/run.sh
Executable file
3
samples/inst-context-threads/run.sh
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
out/inst-context -f out/wasm-apps/testapp.wasm
|
151
samples/inst-context-threads/src/main.c
Normal file
151
samples/inst-context-threads/src/main.c
Normal file
|
@ -0,0 +1,151 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "wasm_export.h"
|
||||
#include "bh_read_file.h"
|
||||
#include "bh_getopt.h"
|
||||
#include "my_context.h"
|
||||
|
||||
void
|
||||
set_context(wasm_exec_env_t exec_env, int32_t n);
|
||||
int32_t
|
||||
get_context(wasm_exec_env_t exec_env);
|
||||
|
||||
void *my_context_key;
|
||||
struct my_context my_context;
|
||||
int my_dtor_called;
|
||||
|
||||
wasm_module_inst_t module_inst = NULL;
|
||||
|
||||
void
|
||||
print_usage(void)
|
||||
{
|
||||
fprintf(stdout, "Options:\r\n");
|
||||
fprintf(stdout, " -f [path of wasm file] \n");
|
||||
}
|
||||
|
||||
void
|
||||
my_context_dtor(wasm_module_inst_t inst, void *ctx)
|
||||
{
|
||||
printf("%s called\n", __func__);
|
||||
my_dtor_called++;
|
||||
bh_assert(ctx == &my_context);
|
||||
bh_assert(inst == module_inst);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv_main[])
|
||||
{
|
||||
static char global_heap_buf[512 * 1024];
|
||||
char *buffer;
|
||||
char error_buf[128];
|
||||
int opt;
|
||||
char *wasm_path = NULL;
|
||||
int exit_code = 1;
|
||||
|
||||
wasm_module_t module = NULL;
|
||||
uint32 buf_size, stack_size = 8092, heap_size = 8092;
|
||||
|
||||
RuntimeInitArgs init_args;
|
||||
memset(&init_args, 0, sizeof(RuntimeInitArgs));
|
||||
|
||||
while ((opt = getopt(argc, argv_main, "hf:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'f':
|
||||
wasm_path = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
print_usage();
|
||||
return 0;
|
||||
case '?':
|
||||
print_usage();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (optind == 1) {
|
||||
print_usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Define an array of NativeSymbol for the APIs to be exported.
|
||||
// Note: the array must be static defined since runtime
|
||||
// will keep it after registration
|
||||
// For the function signature specifications, goto the link:
|
||||
// https://github.com/bytecodealliance/wasm-micro-runtime/blob/main/doc/export_native_api.md
|
||||
|
||||
static NativeSymbol native_symbols[] = {
|
||||
{ "set_context", set_context, "(i)", NULL },
|
||||
{ "get_context", get_context, "()i", NULL },
|
||||
};
|
||||
|
||||
init_args.mem_alloc_type = Alloc_With_Pool;
|
||||
init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
|
||||
init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
|
||||
|
||||
// Native symbols need below registration phase
|
||||
init_args.n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol);
|
||||
init_args.native_module_name = "env";
|
||||
init_args.native_symbols = native_symbols;
|
||||
|
||||
if (!wasm_runtime_full_init(&init_args)) {
|
||||
printf("Init runtime environment failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
my_context_key = wasm_runtime_create_context_key(my_context_dtor);
|
||||
if (!my_context_key) {
|
||||
printf("wasm_runtime_create_context_key failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer = bh_read_file_to_buffer(wasm_path, &buf_size);
|
||||
|
||||
if (!buffer) {
|
||||
printf("Open wasm app file [%s] failed.\n", wasm_path);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
module = wasm_runtime_load((uint8 *)buffer, buf_size, error_buf,
|
||||
sizeof(error_buf));
|
||||
if (!module) {
|
||||
printf("Load wasm module failed. error: %s\n", error_buf);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
module_inst = wasm_runtime_instantiate(module, stack_size, heap_size,
|
||||
error_buf, sizeof(error_buf));
|
||||
|
||||
if (!module_inst) {
|
||||
printf("Instantiate wasm module failed. error: %s\n", error_buf);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
char *args[] = {
|
||||
"testapp",
|
||||
};
|
||||
wasm_application_execute_main(module_inst, 1, args);
|
||||
const char *exc = wasm_runtime_get_exception(module_inst);
|
||||
if (exc != NULL) {
|
||||
printf("call wasm function calculate failed. error: %s\n", exc);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
exit_code = 0;
|
||||
fail:
|
||||
if (module_inst) {
|
||||
bh_assert(my_dtor_called == 0);
|
||||
wasm_runtime_deinstantiate(module_inst);
|
||||
bh_assert(my_dtor_called == 1);
|
||||
}
|
||||
if (module)
|
||||
wasm_runtime_unload(module);
|
||||
if (buffer)
|
||||
BH_FREE(buffer);
|
||||
if (my_context_key)
|
||||
wasm_runtime_destroy_context_key(my_context_key);
|
||||
wasm_runtime_destroy();
|
||||
return exit_code;
|
||||
}
|
11
samples/inst-context-threads/src/my_context.h
Normal file
11
samples/inst-context-threads/src/my_context.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* Copyright (C) 2023 Midokura Japan KK. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
struct my_context {
|
||||
int x;
|
||||
};
|
||||
|
||||
extern void *my_context_key;
|
||||
extern struct my_context my_context;
|
32
samples/inst-context-threads/src/native_impl.c
Normal file
32
samples/inst-context-threads/src/native_impl.c
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (C) 2023 Midokura Japan KK. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "wasm_export.h"
|
||||
#include "my_context.h"
|
||||
|
||||
void
|
||||
set_context(wasm_exec_env_t exec_env, int32_t n)
|
||||
{
|
||||
wasm_module_inst_t inst = wasm_runtime_get_module_inst(exec_env);
|
||||
printf("%s called on module inst %p\n", __func__, inst);
|
||||
struct my_context *ctx = &my_context;
|
||||
ctx->x = n;
|
||||
wasm_runtime_set_context_spread(inst, my_context_key, ctx);
|
||||
}
|
||||
|
||||
int32_t
|
||||
get_context(wasm_exec_env_t exec_env)
|
||||
{
|
||||
wasm_module_inst_t inst = wasm_runtime_get_module_inst(exec_env);
|
||||
printf("%s called on module inst %p\n", __func__, inst);
|
||||
struct my_context *ctx = wasm_runtime_get_context(inst, my_context_key);
|
||||
if (ctx == NULL) {
|
||||
return -1;
|
||||
}
|
||||
return ctx->x;
|
||||
}
|
65
samples/inst-context-threads/wasm-apps/testapp.c
Normal file
65
samples/inst-context-threads/wasm-apps/testapp.c
Normal file
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (C) 2023 Midokura Japan KK. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void
|
||||
set_context(int32_t n) __attribute__((import_module("env")))
|
||||
__attribute__((import_name("set_context")));
|
||||
|
||||
int32_t
|
||||
get_context() __attribute__((import_module("env")))
|
||||
__attribute__((import_name("get_context")));
|
||||
|
||||
void *
|
||||
start(void *vp)
|
||||
{
|
||||
int32_t v;
|
||||
|
||||
printf("thread started\n");
|
||||
|
||||
printf("confirming the initial state on thread\n");
|
||||
v = get_context();
|
||||
assert(v == -1);
|
||||
|
||||
printf("setting the context on thread\n");
|
||||
set_context(1234);
|
||||
|
||||
printf("confirming the context on thread\n");
|
||||
v = get_context();
|
||||
assert(v == 1234);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
main()
|
||||
{
|
||||
pthread_t t1;
|
||||
int32_t v;
|
||||
int ret;
|
||||
|
||||
printf("confirming the initial state on main\n");
|
||||
v = get_context();
|
||||
assert(v == -1);
|
||||
|
||||
printf("creating a thread\n");
|
||||
ret = pthread_create(&t1, NULL, start, NULL);
|
||||
assert(ret == 0);
|
||||
void *val;
|
||||
ret = pthread_join(t1, &val);
|
||||
assert(ret == 0);
|
||||
printf("joined the thread\n");
|
||||
|
||||
printf("confirming the context propagated from the thread on main\n");
|
||||
v = get_context();
|
||||
assert(v == 1234);
|
||||
|
||||
printf("success\n");
|
||||
return 0;
|
||||
}
|
1
samples/inst-context/.gitignore
vendored
Normal file
1
samples/inst-context/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/out/
|
91
samples/inst-context/CMakeLists.txt
Normal file
91
samples/inst-context/CMakeLists.txt
Normal file
|
@ -0,0 +1,91 @@
|
|||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
cmake_minimum_required (VERSION 3.14)
|
||||
|
||||
include(CheckPIESupported)
|
||||
|
||||
if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows")
|
||||
project (inst-context)
|
||||
else()
|
||||
project (inst-context C ASM)
|
||||
enable_language (ASM_MASM)
|
||||
endif()
|
||||
|
||||
################ runtime settings ################
|
||||
string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM)
|
||||
if (APPLE)
|
||||
add_definitions(-DBH_PLATFORM_DARWIN)
|
||||
endif ()
|
||||
|
||||
# Reset default linker flags
|
||||
set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
|
||||
set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
|
||||
|
||||
# WAMR features switch
|
||||
|
||||
# Set WAMR_BUILD_TARGET, currently values supported:
|
||||
# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]",
|
||||
# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]"
|
||||
if (NOT DEFINED WAMR_BUILD_TARGET)
|
||||
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^(arm64|aarch64)")
|
||||
set (WAMR_BUILD_TARGET "AARCH64")
|
||||
elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64")
|
||||
set (WAMR_BUILD_TARGET "RISCV64")
|
||||
elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
|
||||
# Build as X86_64 by default in 64-bit platform
|
||||
set (WAMR_BUILD_TARGET "X86_64")
|
||||
elseif (CMAKE_SIZEOF_VOID_P EQUAL 4)
|
||||
# Build as X86_32 by default in 32-bit platform
|
||||
set (WAMR_BUILD_TARGET "X86_32")
|
||||
else ()
|
||||
message(SEND_ERROR "Unsupported build target platform!")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set (CMAKE_BUILD_TYPE Debug)
|
||||
endif ()
|
||||
|
||||
set (WAMR_BUILD_INTERP 1)
|
||||
set (WAMR_BUILD_AOT 1)
|
||||
set (WAMR_BUILD_JIT 0)
|
||||
set (WAMR_BUILD_LIBC_BUILTIN 1)
|
||||
|
||||
if (NOT MSVC)
|
||||
set (WAMR_BUILD_LIBC_WASI 1)
|
||||
endif ()
|
||||
|
||||
if (NOT MSVC)
|
||||
# linker flags
|
||||
if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang"))
|
||||
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
|
||||
endif ()
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security")
|
||||
if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
|
||||
if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang"))
|
||||
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register")
|
||||
endif ()
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
# build out vmlib
|
||||
set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
|
||||
include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
|
||||
|
||||
add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE})
|
||||
|
||||
################ application related ################
|
||||
include_directories(${CMAKE_CURRENT_LIST_DIR}/src)
|
||||
include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
|
||||
|
||||
add_executable (inst-context src/main.c src/native_impl.c ${UNCOMMON_SHARED_SOURCE})
|
||||
|
||||
check_pie_supported()
|
||||
set_target_properties (inst-context PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
if (APPLE)
|
||||
target_link_libraries (inst-context vmlib -lm -ldl -lpthread)
|
||||
else ()
|
||||
target_link_libraries (inst-context vmlib -lm -ldl -lpthread -lrt)
|
||||
endif ()
|
4
samples/inst-context/README.md
Normal file
4
samples/inst-context/README.md
Normal file
|
@ -0,0 +1,4 @@
|
|||
The "inst-context" sample project
|
||||
=================================
|
||||
|
||||
This sample demonstrates module instance context API.
|
63
samples/inst-context/build.sh
Executable file
63
samples/inst-context/build.sh
Executable file
|
@ -0,0 +1,63 @@
|
|||
#
|
||||
# Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
#
|
||||
|
||||
#!/bin/bash
|
||||
|
||||
CURR_DIR=$PWD
|
||||
WAMR_DIR=${PWD}/../..
|
||||
OUT_DIR=${PWD}/out
|
||||
|
||||
WASM_APPS=${PWD}/wasm-apps
|
||||
|
||||
|
||||
rm -rf ${OUT_DIR}
|
||||
mkdir ${OUT_DIR}
|
||||
mkdir ${OUT_DIR}/wasm-apps
|
||||
|
||||
|
||||
echo "#####################build inst-context project"
|
||||
cd ${CURR_DIR}
|
||||
mkdir -p cmake_build
|
||||
cd cmake_build
|
||||
cmake ..
|
||||
make -j ${nproc}
|
||||
if [ $? != 0 ];then
|
||||
echo "BUILD_FAIL inst-context exit as $?\n"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
cp -a inst-context ${OUT_DIR}
|
||||
|
||||
echo -e "\n"
|
||||
|
||||
echo "#####################build wasm apps"
|
||||
|
||||
cd ${WASM_APPS}
|
||||
|
||||
for i in `ls *.c`
|
||||
do
|
||||
APP_SRC="$i"
|
||||
OUT_FILE=${i%.*}.wasm
|
||||
|
||||
# use WAMR SDK to build out the .wasm binary
|
||||
/opt/wasi-sdk/bin/clang \
|
||||
--target=wasm32 -O0 -z stack-size=4096 -Wl,--initial-memory=65536 \
|
||||
--sysroot=${WAMR_DIR}/wamr-sdk/app/libc-builtin-sysroot \
|
||||
-Wl,--allow-undefined-file=${WAMR_DIR}/wamr-sdk/app/libc-builtin-sysroot/share/defined-symbols.txt \
|
||||
-Wl,--strip-all,--no-entry -nostdlib \
|
||||
-Wl,--export=generate_float \
|
||||
-Wl,--export=float_to_string \
|
||||
-Wl,--export=calculate\
|
||||
-Wl,--allow-undefined \
|
||||
-o ${OUT_DIR}/wasm-apps/${OUT_FILE} ${APP_SRC}
|
||||
|
||||
|
||||
if [ -f ${OUT_DIR}/wasm-apps/${OUT_FILE} ]; then
|
||||
echo "build ${OUT_FILE} success"
|
||||
else
|
||||
echo "build ${OUT_FILE} fail"
|
||||
fi
|
||||
done
|
||||
echo "####################build wasm apps done"
|
3
samples/inst-context/run.sh
Executable file
3
samples/inst-context/run.sh
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/bash
|
||||
|
||||
out/inst-context -f out/wasm-apps/testapp.wasm
|
166
samples/inst-context/src/main.c
Normal file
166
samples/inst-context/src/main.c
Normal file
|
@ -0,0 +1,166 @@
|
|||
|
||||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "wasm_export.h"
|
||||
#include "bh_read_file.h"
|
||||
#include "bh_getopt.h"
|
||||
#include "my_context.h"
|
||||
|
||||
int32_t
|
||||
add_native(int32_t n);
|
||||
void *my_context_key;
|
||||
struct my_context my_context;
|
||||
int my_dtor_called;
|
||||
|
||||
wasm_module_inst_t module_inst = NULL;
|
||||
|
||||
void
|
||||
print_usage(void)
|
||||
{
|
||||
fprintf(stdout, "Options:\r\n");
|
||||
fprintf(stdout, " -f [path of wasm file] \n");
|
||||
}
|
||||
|
||||
void
|
||||
my_context_dtor(wasm_module_inst_t inst, void *ctx)
|
||||
{
|
||||
printf("%s called\n", __func__);
|
||||
my_dtor_called++;
|
||||
bh_assert(ctx == &my_context);
|
||||
bh_assert(inst == module_inst);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv_main[])
|
||||
{
|
||||
static char global_heap_buf[512 * 1024];
|
||||
char *buffer;
|
||||
char error_buf[128];
|
||||
int opt;
|
||||
char *wasm_path = NULL;
|
||||
|
||||
wasm_module_t module = NULL;
|
||||
wasm_exec_env_t exec_env = NULL;
|
||||
uint32 buf_size, stack_size = 8092, heap_size = 8092;
|
||||
|
||||
RuntimeInitArgs init_args;
|
||||
memset(&init_args, 0, sizeof(RuntimeInitArgs));
|
||||
|
||||
while ((opt = getopt(argc, argv_main, "hf:")) != -1) {
|
||||
switch (opt) {
|
||||
case 'f':
|
||||
wasm_path = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
print_usage();
|
||||
return 0;
|
||||
case '?':
|
||||
print_usage();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (optind == 1) {
|
||||
print_usage();
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Define an array of NativeSymbol for the APIs to be exported.
|
||||
// Note: the array must be static defined since runtime
|
||||
// will keep it after registration
|
||||
// For the function signature specifications, goto the link:
|
||||
// https://github.com/bytecodealliance/wasm-micro-runtime/blob/main/doc/export_native_api.md
|
||||
|
||||
static NativeSymbol native_symbols[] = { { "add_native", add_native, "(i)i",
|
||||
NULL } };
|
||||
|
||||
init_args.mem_alloc_type = Alloc_With_Pool;
|
||||
init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
|
||||
init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
|
||||
|
||||
// Native symbols need below registration phase
|
||||
init_args.n_native_symbols = sizeof(native_symbols) / sizeof(NativeSymbol);
|
||||
init_args.native_module_name = "env";
|
||||
init_args.native_symbols = native_symbols;
|
||||
|
||||
if (!wasm_runtime_full_init(&init_args)) {
|
||||
printf("Init runtime environment failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
my_context_key = wasm_runtime_create_context_key(my_context_dtor);
|
||||
if (!my_context_key) {
|
||||
printf("wasm_runtime_create_context_key failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer = bh_read_file_to_buffer(wasm_path, &buf_size);
|
||||
|
||||
if (!buffer) {
|
||||
printf("Open wasm app file [%s] failed.\n", wasm_path);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
module = wasm_runtime_load((uint8 *)buffer, buf_size, error_buf,
|
||||
sizeof(error_buf));
|
||||
if (!module) {
|
||||
printf("Load wasm module failed. error: %s\n", error_buf);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
module_inst = wasm_runtime_instantiate(module, stack_size, heap_size,
|
||||
error_buf, sizeof(error_buf));
|
||||
|
||||
if (!module_inst) {
|
||||
printf("Instantiate wasm module failed. error: %s\n", error_buf);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
my_context.x = 100;
|
||||
wasm_runtime_set_context(module_inst, my_context_key, &my_context);
|
||||
|
||||
exec_env = wasm_runtime_create_exec_env(module_inst, stack_size);
|
||||
if (!exec_env) {
|
||||
printf("Create wasm execution environment failed.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
wasm_function_inst_t func3 =
|
||||
wasm_runtime_lookup_function(module_inst, "calculate", NULL);
|
||||
if (!func3) {
|
||||
printf("The wasm function calculate is not found.\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
uint32_t argv3[1] = { 3 };
|
||||
if (wasm_runtime_call_wasm(exec_env, func3, 1, argv3)) {
|
||||
uint32_t result = *(uint32_t *)argv3;
|
||||
printf("Native finished calling wasm function: calculate, return: %d\n",
|
||||
result);
|
||||
bh_assert(result == 103); /* argv3[0] + my_context.x */
|
||||
}
|
||||
else {
|
||||
printf("call wasm function calculate failed. error: %s\n",
|
||||
wasm_runtime_get_exception(module_inst));
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fail:
|
||||
if (exec_env)
|
||||
wasm_runtime_destroy_exec_env(exec_env);
|
||||
if (module_inst) {
|
||||
bh_assert(my_dtor_called == 0);
|
||||
wasm_runtime_deinstantiate(module_inst);
|
||||
bh_assert(my_dtor_called == 1);
|
||||
}
|
||||
if (module)
|
||||
wasm_runtime_unload(module);
|
||||
if (buffer)
|
||||
BH_FREE(buffer);
|
||||
if (my_context_key)
|
||||
wasm_runtime_destroy_context_key(my_context_key);
|
||||
wasm_runtime_destroy();
|
||||
return 0;
|
||||
}
|
10
samples/inst-context/src/my_context.h
Normal file
10
samples/inst-context/src/my_context.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* Copyright (C) 2023 Midokura Japan KK. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
struct my_context {
|
||||
int x;
|
||||
};
|
||||
|
||||
extern void *my_context_key;
|
15
samples/inst-context/src/native_impl.c
Normal file
15
samples/inst-context/src/native_impl.c
Normal file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (C) 2023 Midokura Japan KK. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include "wasm_export.h"
|
||||
#include "my_context.h"
|
||||
|
||||
int32_t
|
||||
add_native(wasm_exec_env_t exec_env, int32_t n)
|
||||
{
|
||||
wasm_module_inst_t inst = wasm_runtime_get_module_inst(exec_env);
|
||||
struct my_context *ctx = wasm_runtime_get_context(inst, my_context_key);
|
||||
return n + ctx->x;
|
||||
}
|
19
samples/inst-context/wasm-apps/testapp.c
Normal file
19
samples/inst-context/wasm-apps/testapp.c
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
|
||||
int32_t
|
||||
add_native(int32_t n);
|
||||
|
||||
int32_t
|
||||
calculate(int32_t n)
|
||||
{
|
||||
printf("calling into WASM function: %s\n", __FUNCTION__);
|
||||
return add_native(n);
|
||||
}
|
|
@ -45,6 +45,7 @@ add_definitions(-DWASM_ENABLE_DUMP_CALL_STACK=1)
|
|||
add_definitions(-DWASM_ENABLE_PERF_PROFILING=1)
|
||||
add_definitions(-DWASM_ENABLE_LOAD_CUSTOM_SECTION=1)
|
||||
add_definitions(-DWASM_ENABLE_LIB_WASI_THREADS=1)
|
||||
add_definitions(-DWASM_ENABLE_MODULE_INST_CONTEXT=1)
|
||||
|
||||
if (WAMR_BUILD_LLVM_LEGACY_PM EQUAL 1)
|
||||
add_definitions(-DWASM_ENABLE_LLVM_LEGACY_PM=1)
|
||||
|
|
Loading…
Reference in New Issue
Block a user