WebAssembly / wasi-sdk

WASI-enabled WebAssembly C/C++ toolchain
Apache License 2.0
1.29k stars 192 forks source link

Should WASI provide stub support for atomics/threads even in single thread mode? #22

Open zhuowei opened 5 years ago

zhuowei commented 5 years ago

Currently, WASI disables support for atomics and pthreads since WASI is single-threaded. There's no pthreads.h, and including the C++ header gives an error.

This makes it difficult to port programs that use atomics and/or thread apis: even if the program can run in single threaded mode, I still have to manually remove all uses of atomics and pthread mutexes/semaphores/etc.

Would it make sense to provide stub implementations of atomics and pthreads apis, to minimize the changes required for programs originally written for multithreaded environments to compile on WASI?

Emscripten does provide atomics for programs, even though it's also single threaded; adding this may make it easier to port programs from emscripten.

kripken commented 5 years ago

Emscripten does provide atomics for programs, even though it's also single threaded;

Side note, emscripten can run as either single-threaded or multi-threaded. But yes, it does provide atomics in both cases.

sunfishcode commented 5 years ago

WASI-targeting clang already does support the atomic builtin functions in single-threaded mode, so would it make sense to install musl's pthread.h somewhere in the install directory that you can add to the include path if you want to compile this way?

zhuowei commented 5 years ago

@sunfishcode I'm doing that temporarily here, but I would like to know whether WASI intends to offer some official support for this configuration, like how mmap is emulated with an optional define and link flag.

sunfishcode commented 5 years ago

Yes, that would make sense. How about a separate include directory in the sysroot somewhere, that you can manually add with -I, which contains <pthread.h>? Would anyone be interested in submitting a PR for this?

zhuowei commented 5 years ago

@sunfishcode One issue with this: libcxx supports different features and generate different code depending on whether threads are enabled. Do we need to include two copies of libcxx?

sunfishcode commented 5 years ago

For full threads support, we will need separate copies of libc.a, libcxx.a, and others, because it affects a lot of things. That's something we'd like to support, but just haven't gotten to yet. If anyone is interested in helping out with this, it'd be greatly appreciated!

However, from the description above, it sounded like the issue here is just providing a <pthread.h> for use in single-threaded mode.

skyne98 commented 5 years ago

Also, what about this?

// '-pthread' sets '-target-feature +atomics' and '--shared-memory'
// RUN: %clang -### -no-canonical-prefixes -target wasm32-unknown-unknown --sysroot=/foo %s -fuse-ld=wasm-ld -pthread 2>&1 | FileCheck -check-prefix=PTHREAD %s
// PTHREAD: clang{{.*}}" "-cc1" {{.*}} "-target-feature" "+atomics"
// PTHREAD: wasm-ld{{.*}}" "-lpthread" "--shared-memory"

Does this mean that clang supports pthreads api via webworkers and shared memory buffers? If it does, then I still guess it wouldn't be useful because of the full absence of thread-like concepts on current wasmi runtimes? Again, like web workers that can share memory buffers on the web.

zatkh commented 4 years ago

I'm wondering if there is any update on this? I need c++ atomic support for porting. Any suggestions?

TerrorJack commented 4 years ago

Hi folks, I have a wasi-sdk fork that added dummy implementation for some pthread functions which seems to get C++ mutex & atomics working, see https://github.com/TerrorJack/wasi-sdk/releases/tag/201027 and the tagged commit for the changes. You're welcome to give this a try :)

sunfishcode commented 4 years ago

@TerrorJack Cool, thanks for posting this!

TerrorJack commented 4 years ago

I think in general, full pthread support with appropriate blocking behavior is possible within wasi-sdk without relying on wasm threads proposal or extending the wasi spec.

To achieve this, we can implement a binaryen pass much like the existing asyncify pass to rewrite all blocking call sites to save context and yield execution. (Or possibly at the clang level) A minimal round-robin scheduler can be implemented in C to handle the thread switching logic.

This won't be 100% safe since indirect calls to blocking api can't be handled, and since we only yield on blocking calls, each thread will likely run much longer than a typical time slice in unix kernels. But typical pthread usages should work.

Above is my shower thought of how we may improve the pthread story of wasi-sdk in the future. It surely takes a lot of work but I'd like to post early to get some critiques. Any thoughts on if this can work? @sunfishcode

sbc100 commented 4 years ago

What you are describing is more like coroutines or fibres. You can indeed achieve something like that using asyncify, but it not really a true pthread replacement as there is no pre-preemption.

I remember a project from a while back that tried to do this (fake real threads using coroutines): https://www.gnu.org/software/pth/. But its not a completely drop in replacement for real pre-preemptive threads and I think that project is inactive these days. I think its based on setcontext/getcontext so presumably one starting point would be take that GNU pth and use asyncify to implement setcontext/getcontext.

abrown commented 1 year ago

As I've noted elsewhere, work on work on the new wasm32-wasi-threads target (available in the wasi-sdk-20+threads pre-release and explained here), changes the equation a bit. I think users who want to build multi-threaded programs with wasi-sdk should look into wasm32-wasi-threads, but I suspect there are other users who just want to compile single-threaded programs that just happen to include some pthread header. For this latter case, we should still discuss whether stubbing out the pthread.h calls (e.g., to fail) makes sense. It seems like this is almost a wasi-libc issue more than a wasi-sdk issue (I get that users would come here first): if anyone is interested, take a look at the THREAD_MODEL=single parts of the wasi-libc Makefile here.