Multi-thread, Pthread APIs And Thread Management

Note: This document describes the old pthread implementation. See Pthread implementations.

WAMR provides a built-in library to support pthread APIs. You can call pthread APIs in your application source code.

Build and run

Suppose you have written a C program calling pthread_create() to create a thread, and the file name is main.c

#include <stdio.h>
#include <pthread.h>

void *thread_routine(void *arg)
{
    printf("Enter thread\n");
    pthread_exit(NULL);
    return NULL;
}

int main(int argc, char** argv)
{
    pthread_t tid;

    if (0 != pthread_create(&tid, NULL, thread_routine, NULL)) {
        printf("Failed to create thread\n");
    }

    if (0 != pthread_join(tid, NULL)) {
        printf("Failed to join thread %d.\n", tid);
    }

    printf("Exit\n");

    return 0;
}

Build with libc-builtin

To build this C program into WebAssembly app with libc-builtin, you can use this command:

Build with libc-WASI

You can also build this program with WASI, but we need to make some changes to wasi-sysroot:

  1. disable malloc/free of wasi, as they are not atomic operations:

  2. copy the pthread.h to wasi-sysroot so the compiler can find it:

Note:

  1. Remember to back up the original sysroot files

Then build the program with this command:

Build with EMCC

Note: This document is based on emcc 2.0.26, other version may not work with these commands

EMCC's -pthread option is not compatible with standalone mode, we need to pass -mbulk-memory -matomics to the compiler and --shared-memory,--no-check-features to linker manually

EMCC provides some empty implementation for pthread related APIs, we need to remove them from emcc's libc.

Build AOT module

You can build the wasm module into AOT module with pthread support, please pass option --enable-multi-thread to wamrc:

Currently WAMR disables pthread library by default. To run the module with pthread support, please build the runtime with -DWAMR_BUILD_LIB_PTHREAD=1

Here is also a sample to show how wasm-apps use pthread APIs to create threads, and how to build it with cmake. You can build this sample and have a try:

Aux stack separation

The compiler may use some spaces in the linear memory as an auxiliary stack. When pthread is enabled, every thread should have its own aux stack space, so the total aux stack space reserved by the compiler will be divided into N + 1 parts, where N is the maximum number of threads that can be created by the user code.

The default value of N is 4, which means you can create 4 threads at most. This value can be changed by an option if you are using product-mini:

If you are going to develop your own runtime product, you can use the API wasm_runtime_set_max_thread_num or init arg init_args.max_thread_num to set the value, or you can change the macro CLUSTER_MAX_THREAD_NUM in config.h.

Note: the total size of aux stack reserved by compiler can be set with -z stack-size option during compilation. If you need to create more threads, please set a larger value, otherwise it is easy to cause aux stack overflow.

Supported APIs

Known limits

  • pthread_attr_t, pthread_mutexattr_t and pthread_condattr_t are not supported yet, so please pass NULL as the second argument of pthread_create, pthread_mutex_init and pthread_cond_init.

  • The errno.o in wasi-sysroot is not compatible with this feature, so using errno in multi-thread may cause unexpected behavior.

  • Currently struct timespec is not supported, so the prototype of pthread_cond_timedwait is different from the native one, it takes an unsigned int argument useconds to indicate the waiting time.

Last updated