Open4
WasmLinux: ユーザーランドバイナリモジュールの設計
今のところ、WasmLinuxはユーザランドのバイナリを1つしか持てない。流石にそれでは実用性に欠けるので、複数のユーザーランドモジュールを1つに纏めるための仕様を考える。
ランタイム
WasmLinuxのカーネルから見たランタイムAPIは以下のようにする:
void* wasmlinux_user_loader_ctx_new_w2c(void); /* => ctx */
void* wasmlinux_user_module_load(void* ctx, unsigned char* modid, size_t len); /* => handle */
void* wasmlinux_user_module_instantiate32(void* handle, uint32_t dataptr,
uint32_t initial_stack); /* => instance */
void wasmlinux_user_module_destroy(void* handle);
void wasmlinux_user_ctx_new32(void* uctx, uint32_t stack);
uint32_t wasmlinux_user_ctx_exec32(int type,
uint32_t func,
uint32_t param0, uint32_t param1,
uint32_t param2, uint32_t param3); /* => ret */
void wasmlinux_tls_set_context(void* uctx);
void* wasmlinux_tls_get_context(void);
モジュールはロードとinstantiateを分ける。モジュールはリファレンスカウントされ、必要に応じてキャッシュされる。instantiateはモジュールのリファレンスカウントを1上げる。
instanceは実行が完了すると自動的に破棄される。 ... 明示的に回収した方が良い気がしてきた。
loaderのコンテキストを分けるのは、将来wasm2c以外のWasm処理系に対応した場合に使いたい ...が、割と難しそうなんだよな。。
モジュールは256bitsのモジュールIDで識別される。この採番は以前ビルドシステムでカバーした:
user_ctx
は、ユーザーコードを実行するためのスレッドコンテキストを確保する。 ...要するにスタックポインタが該当する。
分離した
とりあえず今まで runner.cpp
に集約されていたコードを分離して、APIを使うように変更した。まだモジュールが1つしかなく、かつ runner と同じexecutableに内包される前提なのでloader関連は無い。
モジュール名のハードコードを止める
これでbusybox以外のプログラムを動かしたい時でもrunner側を大改造する必要は無くなった。