Emscripten support
pixelblender opened this issue · 8 comments
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 ?
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.
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.
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
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.
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.
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)
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.
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