sverker / webasm-test

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

wasm_runtime_nif

An Erlang module with a NIF implementation to load and call web-assembly code to run within the Erlang runtime VM.

Prerequisite

Get WebAssembly Micro Runtime

git clone https://github.com/bytecodealliance/wasm-micro-runtime
cd wasm-micro-runtime
export WASM_DIR=`pwd`

and build it with thread support

cd $WASM_DIR/product-mini/platforms/linux
mkdir build-thr-mng
cd build-thr-mng
cmake .. -DWAMR_BUILD_LIB_PTHREAD=1
make

An Erlang/OTP installation

export ERL_DIR=...

Build this repo

First set WASM_DIR and ERL_DIR like above. Then just run make in the root of this repo.

make

Run it

$ERL_DIR/bin/erl
1> wasm_runtime_nif:init("./test.wasm").

then create an instance of the wasm module

2> M = wasm_runtime_nif:new().

Function call_raw/3 is used to call functions that use plain integer and float types for arguments and return value. For example the add_I32 function in test.c:

int32_t add_I32(int32_t first, int32_t second)
{
  return first + second;
}

can be called with call_raw like this

2> wasm_runtime_nif:call_raw(M, add_I32, [4,7]).
11

Function call/3 is used to call functions that use the erl_nif_wasm.h interface to read and create Erlang terms. For example function add_terms in test.c

ERL_NIF_TERM add_terms(ErlNifEnv env, ERL_NIF_TERM arg1, ERL_NIF_TERM arg2)
{
  int32_t a1, a2;

  if (!enif_wasm_get_int32(env, arg1, &a1) ||
      !enif_wasm_get_int32(env, arg2, &a2))
      return enif_wasm_make_badarg(env);

  return enif_wasm_make_int32(env, a1+a2);
}

can be called with call like this

3> wasm_runtime_nif:call(M, add_terms, [4,7]).
11

More complex data structures can be passed as Erlang terms using the erl_nif_wasm.h interface:

4> wasm_runtime_nif:call(M, add_list_terms, [[4,6,3,7,5]]).
25
4> wasm_runtime_nif:call(M, binary_reverse, [<<1,2,3,4,5>>]).
<<5,4,3,2,1>>

Multi threading limitations

Only one Erlang process (VM thread) at a time can call functions in a wasm module instance. This is by default enforced by a mutex lock (like above) or by binding the module instance to the calling Erlang process:

5> Mb = wasm_runtime_nif:new([process_bound]).

6> wasm_runtime_nif:call(Mb, add_terms, [4,7]).
11
7> self().
<0.96.0>

now crash the shell to get a new shell process

8> 1=2.
** exception error: no match of right hand side value 2
9> self().
<0.99.0>
10> wasm_runtime_nif:call(Mb, add_terms, [4,7]).
** exception error: "called by wrong process"

Different wasm module instancess can be called concurrently, but they will not share any data with each other. The only way to run purely multi-threaded wasm code is to spawn threads within the wasm code (not tested).

About

License:Apache License 2.0


Languages

Language:C 94.8%Language:Makefile 2.9%Language:Erlang 2.3%