compilers/mixins/emscripten: Implement thread support

Emscripten has pthread support (as well as C++ threads), but we don't
currently implement them. This fixes that by adding the necessary code.
The one thing I'm not sure about is setting the pool size. The docs
suggest that you really want to do this to ensure that your code works
correctly, but the number should really be configurable, not sure how to
set that.

Fixes #6684
pull/6688/head
Dylan Baker 5 years ago
parent b2f86c461b
commit 771b0d3ffb
  1. 34
      docs/markdown/Builtin-options.md
  2. 6
      docs/markdown/snippets/emscripten_threads.md
  3. 2
      mesonbuild/compilers/c.py
  4. 2
      mesonbuild/compilers/cpp.py
  5. 26
      mesonbuild/compilers/mixins/emscripten.py
  6. 10
      test cases/wasm/2 threads/meson.build
  7. 21
      test cases/wasm/2 threads/threads.c
  8. 13
      test cases/wasm/2 threads/threads.cpp

@ -134,20 +134,22 @@ The following options are available. Note that both the options themselves and
the possible values they can take will depend on the target platform or
compiler being used:
| Option | Default value | Possible values | Description |
| ------ | ------------- | --------------- | ----------- |
| c_args | | free-form comma-separated list | C compile arguments to use |
| c_link_args | | free-form comma-separated list | C link arguments to use |
| c_std | none | none, c89, c99, c11, c17, c18, gnu89, gnu99, gnu11, gnu17, gnu18 | C language standard to use |
| c_winlibs | see below | free-form comma-separated list | Standard Windows libs to link against |
| cpp_args | | free-form comma-separated list | C++ compile arguments to use |
| cpp_link_args| | free-form comma-separated list | C++ link arguments to use |
| cpp_std | none | none, c++98, c++03, c++11, c++14, c++17, <br/>c++1z, gnu++03, gnu++11, gnu++14, gnu++17, gnu++1z, <br/> vc++14, vc++17, vc++latest | C++ language standard to use |
| cpp_debugstl | false | true, false | C++ STL debug mode |
| cpp_eh | default | none, default, a, s, sc | C++ exception handling type |
| cpp_rtti | true | true, false | Whether to enable RTTI (runtime type identification) |
| cpp_winlibs | see below | free-form comma-separated list | Standard Windows libs to link against |
| fortran_std | none | [none, legacy, f95, f2003, f2008, f2018] | Fortran language standard to use |
| Option | Default value | Possible values | Description |
| ------ | ------------- | --------------- | ----------- |
| c_args | | free-form comma-separated list | C compile arguments to use |
| c_link_args | | free-form comma-separated list | C link arguments to use |
| c_std | none | none, c89, c99, c11, c17, c18, gnu89, gnu99, gnu11, gnu17, gnu18 | C language standard to use |
| c_winlibs | see below | free-form comma-separated list | Standard Windows libs to link against |
| c_thread_count | 4 | integer value ≥ 0 | Number of threads to use with emcc when using threads |
| cpp_args | | free-form comma-separated list | C++ compile arguments to use |
| cpp_link_args | | free-form comma-separated list | C++ link arguments to use |
| cpp_std | none | none, c++98, c++03, c++11, c++14, c++17, <br/>c++1z, gnu++03, gnu++11, gnu++14, gnu++17, gnu++1z, <br/> vc++14, vc++17, vc++latest | C++ language standard to use |
| cpp_debugstl | false | true, false | C++ STL debug mode |
| cpp_eh | default | none, default, a, s, sc | C++ exception handling type |
| cpp_rtti | true | true, false | Whether to enable RTTI (runtime type identification) |
| cpp_thread_count | 4 | integer value ≥ 0 | Number of threads to use with emcc when using threads |
| cpp_winlibs | see below | free-form comma-separated list | Standard Windows libs to link against |
| fortran_std | none | [none, legacy, f95, f2003, f2008, f2018] | Fortran language standard to use |
The default values of `c_winlibs` and `cpp_winlibs` are in compiler-specific
argument forms, but the libraries are: kernel32, user32, gdi32, winspool,
@ -162,3 +164,7 @@ while the `cpp_eh=[value]` will result in `/EH[value]`.
Since *0.51.0* `cpp_eh=default` will result in `/EHsc` on MSVC. When using
gcc-style compilers, nothing is passed (allowing exceptions to work), while
`cpp_eh=none` passes `-fno-exceptions`.
Since *0.54.0* The `<lang>_thread_count` option can be used to control the
value passed to `-s PTHREAD_POOL_SIZE` when using emcc. No other c/c++
compiler supports this option.

@ -0,0 +1,6 @@
## Emscripten (emcc) now supports threads
In addition to properly setting the compile and linker arguments, a new meson
builtin has been added to control the PTHREAD_POOL_SIZE option,
`-D<lang>_thread_count`, which may be set to any integer value greater than 0.
If it set to 0 then the PTHREAD_POOL_SIZE option will not be passed.

@ -133,7 +133,7 @@ class AppleClangCCompiler(ClangCCompiler):
_C18_VERSION = '>=11.0.0'
class EmscriptenCCompiler(BasicLinkerIsCompilerMixin, LinkerEnvVarsMixin, EmscriptenMixin, ClangCCompiler):
class EmscriptenCCompiler(EmscriptenMixin, BasicLinkerIsCompilerMixin, LinkerEnvVarsMixin, ClangCCompiler):
def __init__(self, exelist, version, for_machine: MachineChoice,
is_cross: bool, info: 'MachineInfo', exe_wrapper=None, **kwargs):
if not is_cross:

@ -201,7 +201,7 @@ class AppleClangCPPCompiler(ClangCPPCompiler):
pass
class EmscriptenCPPCompiler(BasicLinkerIsCompilerMixin, LinkerEnvVarsMixin, EmscriptenMixin, ClangCPPCompiler):
class EmscriptenCPPCompiler(EmscriptenMixin, BasicLinkerIsCompilerMixin, LinkerEnvVarsMixin, ClangCPPCompiler):
def __init__(self, exelist, version, for_machine: MachineChoice,
is_cross: bool, info: 'MachineInfo', exe_wrapper=None, **kwargs):
if not is_cross:

@ -17,8 +17,13 @@
import os.path
import typing as T
from ... import coredata
from ...mesonlib import MesonException
if T.TYPE_CHECKING:
from ..environment import Environment
class EmscriptenMixin:
def get_option_link_args(self, options):
@ -45,3 +50,24 @@ class EmscriptenMixin:
else:
suffix = 'wasm'
return os.path.join(dirname, 'output.' + suffix)
def thread_flags(self, env: 'Environment') -> T.List[str]:
return ['-s', 'USE_PTHREADS=1']
def thread_link_flags(self, env: 'Environment') -> T.List[str]:
args = ['-s', 'USE_PTHREADS=1']
count = env.coredata.compiler_options[self.for_machine]['{}_thread_count'.format(self.language)].value # type: int
if count:
args.extend(['-s', 'PTHREAD_POOL_SIZE={}'.format(count)])
return args
def get_options(self):
opts = super().get_options()
opts.update({
'{}_thread_count'.format(self.language): coredata.UserIntegerOption(
'Number of threads to use in web assembly, set to 0 to disable',
(0, None, 4), # Default was picked at random
),
})
return opts

@ -0,0 +1,10 @@
project(
'threads',
'c', 'cpp',
default_options : ['cpp_std=c++11'],
)
dep_threads = dependency('threads')
executable('threads-c', 'threads.c', dependencies : dep_threads)
executable('threads-c++', 'threads.cpp', dependencies : dep_threads)

@ -0,0 +1,21 @@
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
void inthread(void * args) {
sleep(1);
printf("In thread\n");
}
int main() {
#ifdef __EMSCRIPTEN_PTHREADS__
pthread_t thread_id;
printf("Before Thread\n");
pthread_create(&thread_id, NULL, (void *)*inthread, NULL);
pthread_join(thread_id, NULL);
printf("After Thread\n");
return 0;
#else
# error "threads not enabled\n"
#endif
}

@ -0,0 +1,13 @@
#include <unistd.h>
#include <iostream>
#include <thread>
int main(void) {
std::cout << "Before thread" << std::endl;
std::thread t([]() {
sleep(1);
std::cout << "In a thread." << std::endl;
});
t.join();
std::cout << "After thread" << std::endl;
}
Loading…
Cancel
Save