Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Emscripten support #134

Open
pixelblender opened this issue Jun 20, 2021 · 8 comments
Open

Emscripten support #134

pixelblender opened this issue Jun 20, 2021 · 8 comments

Comments

@pixelblender
Copy link

Hi,

Thank you for this awesome library. Is it possible to have emscripten support using its fiber library https://emscripten.org/docs/api_reference/fiber.h.html ?

@RichieSams
Copy link
Owner

So, I did a bit of playing around with emscriptem. It could be possible to implement the Fiber class with emscriptem fiber API. Their API is basically identical to ours.

However, the biggest issue is lack of threads support: https://emscripten.org/docs/porting/pthreads.html
If I follow the guidelines there, I can get thread creation to work. But as soon as I add pthread_join(), the whole browser hangs. Hacky example:

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

void *func(void *arg)
{
    int threadId = (int)arg;

    printf("I'm a thread - %d!\n", threadId);

    return nullptr;
}

int main()
{
    printf("Hello World\n");

    pthread_t test1;
    pthread_t test2;
    pthread_t test3;

    if (pthread_create(&test1, nullptr, func, (void *)1) != 0)
    {
        printf("Failed to create thread\n");
        return -1;
    }
    if (pthread_create(&test2, nullptr, func, (void *)2) != 0)
    {
        printf("Failed to create thread\n");
        return -1;
    }
    if (pthread_create(&test3, nullptr, func, (void *)3) != 0)
    {
        printf("Failed to create thread\n");
        return -1;
    }

    if (pthread_join(test1, nullptr) != 0)
    {
        printf("Failed to join thread\n");
        return -1;
    }
    if (pthread_join(test2, nullptr) != 0)
    {
        printf("Failed to join thread\n");
        return -1;
    }
    if (pthread_join(test3, nullptr) != 0)
    {
        printf("Failed to join thread\n");
        return -1;
    }

    return 0;
}

If I remove the joins, the prints all work. If I leave them in, the browser hangs trying to compile the WASM to native.

So, it could be possible in future for FTL to compile to WASM via Emscripten. But, atm, it's blocked by the lack of full threads support.
A workaround would be to fork FTL and remove all worker threads. Just the main thread and fibers.

@pixelblender
Copy link
Author

pixelblender commented Jun 23, 2021

I tried you code and it works on my end. Did you compile it with -pthread -s PTHREAD_POOL_SIZE=4 ? PTHREAD_POOL_SIZE can be any number as long as it's bigger than 1 I think.

@RichieSams RichieSams reopened this Jun 23, 2021
@RichieSams
Copy link
Owner

RichieSams commented Jun 23, 2021

Ah. I didn't try PTHREAD_POOL_SIZE. Thanks for following up. I was using -s USE_PTHREADS=1. I think that may be old though

@pixelblender
Copy link
Author

pixelblender commented Jun 23, 2021

Thank you for looking into this. Per the emscripten Pthreads page that you linked, for testing Firefox won't work unless your web server explicitly write header responses related to COOP and COEP Cross-Origin Policies. Chrome should be fine I think.

@RichieSams
Copy link
Owner

RichieSams commented Jun 23, 2021

I got it to compile, but when I try to run the triangle_num example in Chrome, it throws an exception: exception thrown: Please compile your program with async support in order to use asynchronous operations like emscripten_fiber_init

https://github.com/RichieSams/FiberTaskingLib/tree/add_wasm_support

Any ideas? I'm passing -s ASYNCIFY, but that doesn't seem to do anything. My googling isn't finding anything either. The only "real" example usage of the fiber api I was able to find was this: https://github.com/Wizcorp/byuu-web/blob/master/libco/emscripten_fiber.c

But my brief searching through the project source code, I wasn't able to find any reference to compiler / linker args.

@RichieSams
Copy link
Owner

Hmm. I was able to run https://github.com/emscripten-core/emscripten/blob/4d864df0a57024d667e8db171aab2c3385d04c30/tests/test_fibers.cpp

With

cmake_minimum_required(VERSION 3.8)
project(wasm_test CXX)

find_package(Threads REQUIRED)
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread -s PTHREAD_POOL_SIZE=8 -s ASYNCIFY")

set (CMAKE_CXX_STANDARD 11)

SET(CMAKE_EXECUTABLE_SUFFIX .html)
add_executable(wasm-test main.cpp)

@RichieSams
Copy link
Owner

Ah ha!

It looks like I need

SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread -s PTHREAD_POOL_SIZE=8 -s ASYNCIFY")

When compiling the example / tests as well. Not just the lib.

It now fails with some malloc size exceptions. But debugging for another day. Time for bed for me.

@pixelblender
Copy link
Author

pixelblender commented Jun 24, 2021

Tested test_fibers.cpp on my end and it doesn't says anything about malloc size exception. Maybe try with -s WASM=1 ? My flags are -s WASM=1 -pthread -s PTHREAD_POOL_SIZE=4 -s ASYNCIFY. To compile, after sourcing the emsdk_env.sh I called emcmake cmake followed by emmake make.

Yes you need to use the flags for compiling AND linking. I passed it to CMAKE_CXX_FLAGS, CMAKE_C_FLAGS and CMAKE_EXE_LINKER_FLAGS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants