WAMR `init_runtime`

 July 22, 2021 at 3:24 pm
static bool
init_runtime(bool alloc_with_pool, uint32_t max_thread_num)
{
    uint64_t ecall_args[2];

    ecall_args[0] = alloc_with_pool;
    ecall_args[1] = max_thread_num;
    if (SGX_SUCCESS != ecall_handle_command(g_eid, CMD_INIT_RUNTIME,
                                            (uint8_t *)ecall_args,
                                            sizeof(uint64_t) * 2)) {
        printf("Call ecall_handle_command() failed.\n");
        return false;
    }
    if (!(bool)ecall_args[0]) {
        printf("Init runtime environment failed.\n");
        return false;
    }
    return true;
}

handle_cmd_init_runtime

This function is invoked at very beginning to initiate the WASM runtime.

Create a heap buffer and pass the init_args to wasm_runtime_full_init

static void
handle_cmd_init_runtime(uint64 *args, uint32 argc)
{
    bool alloc_with_pool;
    uint32 max_thread_num;
    RuntimeInitArgs init_args;

    bh_assert(argc == 2);

    os_set_print_function(enclave_print);

#if WASM_ENABLE_SPEC_TEST == 0
    alloc_with_pool = (bool)args[0];
#else
    alloc_with_pool = true;
#endif
    max_thread_num = (uint32)args[1];

    memset(&init_args, 0, sizeof(RuntimeInitArgs));
    init_args.max_thread_num = max_thread_num;

    if (alloc_with_pool) {
        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);
    }
    else {
        init_args.mem_alloc_type = Alloc_With_System_Allocator;
    }

    /* initialize runtime environment */
    if (!wasm_runtime_full_init(&init_args)) {
        LOG_ERROR("Init runtime environment failed.\n");
        args[0] = false;
        return;
    }

    args[0] = true;

    LOG_VERBOSE("Init runtime environment success.\n");
}

wasm_runtime_full_init

bool
wasm_runtime_full_init(RuntimeInitArgs *init_args)
{
    if (!wasm_runtime_memory_init(init_args->mem_alloc_type,
                                  &init_args->mem_alloc_option))
        return false;

    if (!wasm_runtime_env_init()) {
        wasm_runtime_memory_destroy();
        return false;
    }

    if (init_args->n_native_symbols > 0
        && !wasm_runtime_register_natives(init_args->native_module_name,
                                          init_args->native_symbols,
                                          init_args->n_native_symbols)) {
        wasm_runtime_destroy();
        return false;
    }

#if WASM_ENABLE_THREAD_MGR != 0
    wasm_cluster_set_max_thread_num(init_args->max_thread_num);
#endif

    return true;
}

Initialization will be achieved by several calls.

wasm_runtime_memory_init

  • os_mutex_init in enclave???
  • What's hmu_tree? (heap mempry unit)
  • How is heap memory managed?
wasm_runtime_memory_init(mem_alloc_type_t mem_alloc_type,
                         const MemAllocOption *alloc_option)
{
    if (mem_alloc_type == Alloc_With_Pool)
        return wasm_memory_init_with_pool(alloc_option->pool.heap_buf,
                                          alloc_option->pool.heap_size);
    else if (mem_alloc_type == Alloc_With_Allocator)
        return wasm_memory_init_with_allocator(alloc_option->allocator.malloc_func,
                                               alloc_option->allocator.realloc_func,
                                               alloc_option->allocator.free_func);
    else if (mem_alloc_type == Alloc_With_System_Allocator)
        return wasm_memory_init_with_allocator(os_malloc, os_realloc, os_free);
    else
        return false;
}

wasm_runtime_env_init

static bool
wasm_runtime_env_init()
{
    if (bh_platform_init() != 0)
        return false;

    if (wasm_native_init() == false) {
        goto fail1;
    }

#if WASM_ENABLE_MULTI_MODULE
    if (BHT_OK != os_mutex_init(&registered_module_list_lock)) {
        goto fail2;
    }

    if (BHT_OK != os_mutex_init(&loading_module_list_lock)) {
        goto fail3;
    }
#endif

#if WASM_ENABLE_SHARED_MEMORY
    if (!wasm_shared_memory_init()) {
        goto fail4;
    }
#endif

#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_THREAD_MGR != 0)
    if (!thread_manager_init()) {
        goto fail5;
    }
#endif

#if WASM_ENABLE_AOT != 0
#ifdef OS_ENABLE_HW_BOUND_CHECK
    if (!aot_signal_init()) {
        goto fail6;
    }
#endif
#endif

#if WASM_ENABLE_REF_TYPES != 0
    if (!wasm_externref_map_init()) {
        goto fail7;
    }
#endif

    return true;

#if WASM_ENABLE_REF_TYPES != 0
fail7:
#endif
#if WASM_ENABLE_AOT != 0
#ifdef OS_ENABLE_HW_BOUND_CHECK
    aot_signal_destroy();
fail6:
#endif
#endif
#if (WASM_ENABLE_WAMR_COMPILER == 0) && (WASM_ENABLE_THREAD_MGR != 0)
    thread_manager_destroy();
fail5:
#endif
#if WASM_ENABLE_SHARED_MEMORY
    wasm_shared_memory_destroy();
fail4:
#endif
#if WASM_ENABLE_MULTI_MODULE
    os_mutex_destroy(&loading_module_list_lock);
fail3:
    os_mutex_destroy(&registered_module_list_lock);
fail2:
#endif
    wasm_native_destroy();
fail1:
    bh_platform_destroy();

    return false;
}
  1. bh_platform_init: Initialize the platform internal resources if needed (empty for SGX)
  2. wasm_native_init: Import symbols from precompiled libraries (determined when compiling WASM)
  3. register_natives: add a new NativeSymbolsNode (allocated during runtime) to store the imported functions
  4. When other fields of init_args are set?