From df057e09cffbd89ad41ffe071e4dee482f3b7fec Mon Sep 17 00:00:00 2001 From: Karl Fessel Date: Thu, 23 Sep 2021 00:17:43 +0200 Subject: [PATCH] example/wasm: split example, eventise and introduce wamr_run --- examples/wasm/Makefile | 9 ++- examples/wasm/README.md | 2 - examples/wasm/iwasmt.c | 117 ++++++++++++++++++++--------- examples/wasm/wasm-main.c | 31 ++++++++ examples/wasm/wasm_sample/Makefile | 111 +++++++++++++-------------- 5 files changed, 173 insertions(+), 97 deletions(-) create mode 100644 examples/wasm/wasm-main.c diff --git a/examples/wasm/Makefile b/examples/wasm/Makefile index 5afab016fc..66961b7e25 100644 --- a/examples/wasm/Makefile +++ b/examples/wasm/Makefile @@ -9,13 +9,14 @@ USEPKG += wamr USEMODULE += xtimer USEMODULE += sema +USEMODULE += event export WAMR_CONFIG := $(abspath config.cmake) WPEDANTIC := 0 WERROR := 0 -BLOBS += main.wasm +BLOBS += main.wasm hello.wasm # Comment this out to disable code in RIOT that does safety checking # which is not needed in a production environment but helps in the @@ -25,8 +26,8 @@ DEVELHELP ?= 1 # Change this to 0 show compiler invocation lines by default: QUIET ?= 1 -###################################################### -# Load the rest of the usual RIOT make infastructure # -###################################################### +####################################################### +# Load the rest of the usual RIOT make infrastructure # +####################################################### include $(RIOTBASE)/Makefile.include diff --git a/examples/wasm/README.md b/examples/wasm/README.md index d95393de86..5cfa4dc633 100644 --- a/examples/wasm/README.md +++ b/examples/wasm/README.md @@ -4,5 +4,3 @@ The source for main.wasm can be found in /build/pkg/wamr/product-mini/app-samples/hello-world/ https://github.com/bytecodealliance/wasm-micro-runtime/tree/main/product-mini/app-samples/hello-world - - diff --git a/examples/wasm/iwasmt.c b/examples/wasm/iwasmt.c index 0069ea08a0..4e8895a18b 100644 --- a/examples/wasm/iwasmt.c +++ b/examples/wasm/iwasmt.c @@ -8,6 +8,7 @@ #include #include #include +#include #include @@ -18,18 +19,16 @@ #include -/*provide some test program*/ -#include "blob/main.wasm.h" + #define DEFAULT_THREAD_STACKSIZE (6 * 1024) #define DEFAULT_THREAD_PRIORITY 50 -static int app_argc; -static char **app_argv; /* execs the main function in an instantiated module */ static int iwasm_instance_exec_main(wasm_module_inst_t module_inst, int argc, char **argv) { + /* exception memory is part of instance -> no buffer need */ const char *exception = 0; int ret = 0; wasm_application_execute_main(module_inst, argc, argv); @@ -45,14 +44,15 @@ static int iwasm_instance_exec_main(wasm_module_inst_t module_inst, int argc, ch int iwasm_module_exec_main(wasm_module_t wasm_module , int argc, char **argv) { wasm_module_inst_t wasm_module_inst = NULL; - char error_buf[128]; int ret = 0; - /* instantiate the module */ - if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module, 8 * 1024, - 8 * 1024, error_buf, sizeof(error_buf)))) { - puts(error_buf); - return -1; + { /* instantiate the module */ + char error_buf[128]; + if (!(wasm_module_inst = wasm_runtime_instantiate(wasm_module, 8 * 1024, + 8 * 1024, error_buf, sizeof(error_buf)))) { + puts(error_buf); + return -1; + } } ret = iwasm_instance_exec_main(wasm_module_inst, argc, argv); /* destroy the module instance */ @@ -61,14 +61,13 @@ int iwasm_module_exec_main(wasm_module_t wasm_module , int argc, char **argv) } /* bytecode needs to be writeable*/ -int iwasm_bytecode_exec_main(void *bytecode, size_t bytecode_len, int argc, char **argv){ -// (uint8_t *) bytecode; +int iwasm_bytecode_exec_main(uint8_t * bytecode, size_t bytecode_len, int argc, char **argv){ int ret = 0; wasm_module_t wasm_module = NULL; { /* load WASM module */ char error_buf[128]; - if (!(wasm_module = wasm_runtime_load((uint8_t * )bytecode, bytecode_len, + if (!(wasm_module = wasm_runtime_load(bytecode, bytecode_len, error_buf, sizeof(error_buf)))) { puts(error_buf); return -1; @@ -116,27 +115,20 @@ bool iwasm_runtime_init(void) return true; } +#include "event.h" +event_queue_t iwasm_q = EVENT_QUEUE_INIT_DETACHED; + void * iwasm_thread(void *arg1) { (void) arg1; /*unused*/ - uint8_t *wasm_buf = NULL; - unsigned wasm_buf_size = 0; if(!iwasm_runtime_init()) return (void *)-1; - /* we need the bytecode to be writable while loading - * loading adds size information to stack POPs */ - //static uint8_t wasm_test_file[] = main_wasm; - wasm_buf = malloc(main_wasm_len); - memcpy(wasm_buf, main_wasm, main_wasm_len); - /* no copy need if architecture has const in writable mem */ - /* wasm_buf = (uint8_t *) main_wasm; */ - wasm_buf_size = main_wasm_len; + event_queue_claim(&iwasm_q); + event_loop(&iwasm_q); - iwasm_bytecode_exec_main(wasm_buf, wasm_buf_size, app_argc, app_argv); - - free(wasm_buf); + /*next lines should not be reached*/ wasm_runtime_destroy(); return NULL; } @@ -159,20 +151,77 @@ bool iwasm_start_thread(void) .arg = NULL, .name = "simple_wamr" }; - + event_queue_init_detached(&iwasm_q); b.stack=malloc(b.stacksize); kernel_pid_t tpid = thread_create (b.stack, b.stacksize, b.priority, b.flags, b.task_func, b.arg, b.name); return tpid != 0 ? true : false;; } -/* this seems to be a very direct interpretation of i like to have a wamr_run */ -int wamr_run(void *bytecode, size_t bytecode_len, int argc, char **argv){ - return iwasm_bytecode_exec_main(bytecode, bytecode_len, argc, argv); +#include "mutex.h" + +typedef struct run_bytecode_event { event_t super; + void *bytecode; + size_t bytecode_len; + int argc; + char **argv; + mutex_t finish; +} run_bytecode_event_t; + +void _wamr_run_call(event_t *event){ + run_bytecode_event_t * e = (run_bytecode_event_t *) event; + e->argc = iwasm_bytecode_exec_main((uint8_t * )e->bytecode, e->bytecode_len, e->argc, e->argv); + mutex_unlock(&e->finish); } -#define telltruth(X) ((X) ? "true" : "false") -int main(void) -{ - printf("iwasm_thread_initilised: %s\n",telltruth(iwasm_start_thread())); +/* this seems to be a very direct interpretation of "i like to have a wamr_run" */ +int wamr_run(void *bytecode, size_t bytecode_len, int argc, char **argv){ + run_bytecode_event_t * e = malloc(sizeof(run_bytecode_event_t)); + if (!e) return -1; + + *e = (run_bytecode_event_t){ .super.handler = _wamr_run_call, + .bytecode = bytecode, + .bytecode_len = bytecode_len, + .argc = argc, .argv = argv, + .finish = MUTEX_INIT_LOCKED}; + event_post(&iwasm_q, (event_t*) e); + + mutex_lock(&e->finish); + + int ret = e->argc; + free(e); + return ret; +} + + +int wamr_run_cp(const void *bytecode, size_t bytecode_len, int argc, char *argv[]){ + /* we need the bytecode to be writable while loading + * loading adds size information to stack POPs */ + uint8_t * wasm_buf = malloc(bytecode_len); + if (!wasm_buf) return -1; + + memcpy(wasm_buf, bytecode, bytecode_len); + /* no copy need if architecture has const in writable mem */ + /* wasm_buf = (uint8_t *) main_wasm; */ + + unsigned wasm_buf_size = bytecode_len; + + /* iwasm uses argv[0] casted to an int to store mains return value */ + static char * empty = ""; + char ** parv; + if(argc > 0){ + parv = malloc(sizeof(argv[0]) * argc); + if (!parv) return -1; + memcpy(parv, argv, sizeof(argv[0]) * argc); + }else{ + argc = 1; + parv = malloc(sizeof(argv[0]) * argc); + if (!parv) return -1; + parv[0] = empty; + } + int ret = wamr_run(wasm_buf, wasm_buf_size, argc, parv); + free(parv); + free(wasm_buf); + + return ret; } diff --git a/examples/wasm/wasm-main.c b/examples/wasm/wasm-main.c new file mode 100644 index 0000000000..45a5c7f344 --- /dev/null +++ b/examples/wasm/wasm-main.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include + +/*provide some test program*/ +#include "blob/main.wasm.h" +#include "blob/hello.wasm.h" + +bool iwasm_start_thread(void); +/* this seems to be a very direct interpretation of "i like to have a wamr_run" */ +int wamr_run(void *bytecode, size_t bytecode_len, int argc, char **argv); +/* this creates a copy bytecode and argv + * if argc is 0 it is set to 1 and argv[0] is set to "" + * to create some space for a return value */ +int wamr_run_cp(const void *bytecode, size_t bytecode_len, int argc, const char **argv); + +#define telltruth(X) ((X) ? "true" : "false") + +int main(void) +{ + printf("iwasm_thread_initilised: %s\n", telltruth(iwasm_start_thread())); + + int app_argc = 0; + const char *app_argv1 = "test"; + const char **app_argv = 0; + int ret = wamr_run_cp(main_wasm, main_wasm_len, app_argc, app_argv); + printf("ret = %d\n", ret); + ret = wamr_run_cp(hello_wasm, hello_wasm_len, app_argc, app_argv); + printf("ret = %d\n", ret); +} diff --git a/examples/wasm/wasm_sample/Makefile b/examples/wasm/wasm_sample/Makefile index d1f2f9bc5d..badc880096 100644 --- a/examples/wasm/wasm_sample/Makefile +++ b/examples/wasm/wasm_sample/Makefile @@ -1,69 +1,60 @@ -LLVM_VERSION = 11 +#sometimes there might not be a wasm-ld (Ubuntu:focal) +#lets check if we can find a specific version -#LINK_FLAGS_bak =\ -# -nostartfiles \ -# --nostdlib \ -# --nostdinc \ -# --print-map\ -# --initial-memory= \ -# --allow-undefined-file= -# --initial-memory=65536 +ifneq ($(shell (command -v wasm-ld)),) + WASM-LD ?= wasm-ld + else + ifneq ($(shell (command -v wasm-ld-11)),) + LLVM_VERSION = 11 + else + ifneq ($(shell (command -v wasm-ld-10)),) + LLVM_VERSION = 10 + else + ifneq ($(shell (command -v wasm-ld-9)),) + LLVM_VERSION = 9 + else + ifneq ($(shell (command -v wasm-ld-8)),) + LLVM_VERSION = 8 + endif + endif + endif + endif +endif -# --export-all Export all symbols (normally combined with --no-gc-sections) -# --export-dynamic Put symbols in the dynamic symbol table -# --export-table Export function table to the environment -# --export= Force a symbol to be exported -# --fatal-warnings Treat warnings as errors -# --import-memory Import memory from the environment -# --import-table Import function table from the environment -# --initial-memory= -# Initial size of the linear memory -# --lto-O Optimization level for LTO -# --lto-partitions= -# Number of LTO codegen partitions -# -L Add a directory to the library search path -# -l Root name of library to use -# --max-memory= Maximum size of the linear memory -# --merge-data-segments Enable merging data segments -# --mllvm Options to pass to LLVM -# --pie Create a position independent executable -# --print-gc-sections List removed unused sections -# --relocatable Create relocatable object file -# --shared-memory Use shared linear memory -# --shared Build a shared object -# --stack-first Place stack at start of linear memory rather than after data -# --strip-all Strip all symbols -# --strip-debug Strip debugging information -# -S Alias for --strip-debug -# -s Alias for --strip-all -# --thinlto-cache-dir= -# Path to ThinLTO cached object file directory -# --thinlto-cache-policy= -# Pruning policy for the ThinLTO cache -# --thinlto-jobs= Number of ThinLTO jobs -# --threads Run the linker multi-threaded -# --undefined= Force undefined symbol during linking -# --verbose Verbose mode -# --version Display the version number and exit -# -z