* Don't use sbrk(0) to determine the initial heap size
This commit changes the `try_init_allocator` function as part of
dlmalloc to not use `sbrk(0)` to determine the initial heap size. The
purpose of this function is to use the extra memory at the end of linear
memory for the initial allocation heap before `memory.grow` is used to
allocate more memory. To learn the extent of this region the code
previously would use `sbrk(0)` to find the current size of linear
memory. This does not work, however, when other systems have called
`memory.grow` before this function is called. For example if another
allocator is used or if another component of a wasm binary grows memory
for its own purposes then that memory will be incorrectly claimed to be
owned by dlmalloc.
Instead this commit rounds up the `__heap_base` address to the nearest
page size, since that must be allocatable. Otherwise anything above this
rounded address is assumed to be used by something else, even if it's
addressable.
* Use `__heap_end` if defined
* Move mstate initialization earlier
* Implement the critical part of wasi_thread_start in asm
It's fragile to set up the critical part of C environment in C.
* Specify --target for asm files as well
* wasi_thread_start: Move __tls_base initialization to asm as well
To make it easier to create a sysroot with both triples.
Eg.
```
make -j4 CC=/opt/wasi-sdk-16.0/bin/clang
make -j4 CC=/opt/wasi-sdk-16.0/bin/clang THREAD_MODEL=posix
```
When a user calls `open` with a path that does not have a corresponding
preopen, set errno to `ENOENT` rather than `ENOTCAPABLE`. This
conceptually represents an attempt to open a path which has not been
provided within the sandbox, so it's more accurately represented as
"not present" rather than "insufficient capabilities".
The current wasi-threads has no thread-exit functionality.
Thus it isn't straightforward to implement pthread_exit
without leaking thread context. This commit simply disables
pthread_exit for now.
Also, instead of abusing `wasi_proc_exit` for thread exit,
make `wasi_thread_start` return.
Note: `wasi_proc_exit` is supposed to terminate all threads
in the "process", not only the calling thread.
Note: Depending on the conclusion of the discussion about
`wasi_thread_exit`, we might revisit this change later.
References:
https://github.com/WebAssembly/wasi-threads/issues/7https://github.com/WebAssembly/wasi-threads/pull/17
When compiling with `-z stack-size` flag, only the main thread's stack
size is set to the specified value and other threads use musl's default value.
That's inconsistent with LLD's `-Wl,-stack_size`.
I think we can make it similar to MUSL's behavior, where thread's stack
size can be set via `PT_GNU_STACK` program header (via `-Wl,-z,stack-size`
flag).
Configuring stack size through `pthread_attr_t` still work as expected and
overrides the defaults ([pthread_create.c](be1ffd6a9e/libc-top-half/musl/src/thread/pthread_create.c (L362)))
default settings.
In building some `libc-test` tests, I found these functions were not
compiled in. This change adds `pthread_barrier_init`,
`pthread_barrier_wait`, and `pthread_barrier_destroy` to the
`THREAD_MODEL=posix` build. As has been done with previous pthreads PRs,
this PR skips any inter-process locking by removing any calls to
`__vm_lock` and friends. If in the future WASI gains the "process"
concept, then these locations (and the pre-existing ones) will need to
be modified.
The pthreads API exposes functions for querying the attributes of a
thread. This change allows these functions to be compiled in the
`THREAD_MODEL=posix` build. Some functions are skipped (and documented);
they can be added if/when needed. This change is motivated by a
`libc-test` test that uses these functions.
as __wasi_errno_t is uint16_t, with the current coding,
__pthread_create will never see negative return values from
wasi:thread_spawn.
eg. (int)(uint16_t)-1 == 65535.
1e4e2433bc
enabled sign-ext and mutable-globals by default, which adds
corresponding __wasm_-prefixed #defines.
9e956995db
changed the definition of __GNUC_VA_LIST to match that of GCC headers,
leaving it without a value.
I've now tested the zero-inode path on a Wasm engine specially-modified
to have `fd_readdir` set inode numbers to zero. Fix two bugs this turned up:
- Increment `buffer_processed`, as noticed by @yamt
- Don't do an `fstatat` on "..", because that references a path outside
of the directory, which gets a permission-denied error.
* test: run a subset of tests from `libc-test`
This change introduces a `test` directory that retrieves the `libc-test`
suite, compiles a subset of the tests using `wasi-libc`, and runs them
with Wasmtime.
* ci: run tests during CI
This change includes some fixups to the filesystem to place Clang's
runtime library for `wasm32-wasi` in the right location. Note that this
CI action is limited to a single OS--Linux.
* If `fd_readdir` returns a zero inode, call `fstatat` to get the inode value.
On some systems, `fd_readdir` may not implement the `d_ino` field and
may set it to zero. When this happens, have wasi-libc call `fstatat` to
get the inode number.
See the discussion in
https://github.com/WebAssembly/wasi-filesystem/issues/65 for details.
* Update the `d_type` field too, in case it changes.
We download LLVM releases built for Ubuntu 18 because LLVM doesn't
always have builds for different versions, but the builds we use
depend on libtinfo5 which isn't installed on Ubuntu 20 by default.
So install it.
This function returns the address of `errno`, which makes it easier to
access from non-C languages since `errno` is a thread-local variable
which requires a special ABI.
* threads: implement init of TLS and stack pointer
* fix: rename wasi_snapshot_preview2_thread_spawn to wasi_thread_spawn
Signed-off-by: Harald Hoyer <harald@profian.com>
* fix: change signature of wasi_thread_start
Signed-off-by: Harald Hoyer <harald@profian.com>
* fix: pthread_exit for WASI
Can't use `exit()` because it is too high level.
Have to unlock the thread list.
Signed-off-by: Harald Hoyer <harald@profian.com>
* fix: initialize struct pthread for the main thread
Signed-off-by: Harald Hoyer <harald@profian.com>
* fix: store the aligned stack minus `struct start_args`
Signed-off-by: Harald Hoyer <harald@profian.com>
Signed-off-by: Harald Hoyer <harald@profian.com>
Co-authored-by: Harald Hoyer <harald@profian.com>
- Avoid using Emscripten-specific functions
- Avoid using a constructor.
- Add support for allocating memory at `__heap_base`.
- Adjust the max-align value.
- Disable functions that wasi-libc doesn't currently publish.
- Add `__libc_` aliases.
* Add a check to command modules to ensure that they're only started once.
Wasm command modules should only be called once per instance, because
the programming model doesn't leave linear memory in a reusable state
when the program exits. As use cases arise for loading wasm modules in
environments that want to treat them like reactors, add a safety check
to ensure that command modules are used according to their
expectations.
* threads: implement `pthread_create`
As described in the [`wasi-threads`] proposal, this change implements
`pthread_create` using the new `wasi_thread_spawn(void *arg)` API. As
described there, `wasi-libc` exports the thread entry point with the
expected name, `wasi_thread_start`, and then unwraps the passed argument
`struct` to invoke the user function with the user argument `struct`.
[`wasi-threads`]: https://github.com/WebAssembly/wasi-threads/pull/5
Previously, the TID was only passed to the child thread entry point; the
parent thread was forced to wait until the child thread set the TID in
the pthread structure. With this change, the TID will be passed not only
to the child thread but also returned to the parent thread, so that
either side can make progress. The `i32.store` becomes an
`i32.atomic.store` to avoid concurrent writes.
Previously, "new-style commmands" considered every user-defined
export to be a potential command entrypoint, so wasi-libc and wasm-ld
cooperated to run the user's static constructors on each entrypoint.
This form of new-style command turned out not to be useful, and it
interferes with some use cases, so disable it.
This is done by making an explicit call to `__wasm_call_ctors`, which
tells wasm-ld that it shouldn't synthesize any calls to
`__wasm_call_ctors` on its own.
I'm not sure if the function really has to be exported. If so, we should
probably move it to a separate compilation unit, otherwise it will be defined
multiple times (e.g. in `strerror.o` and `__lctrans.o`) causing linker errors.
However, I don't see a reason (at least for now) to export this function,
therefore making it static in this PR.
The implementation is not as efficient as for native Linux platform due
to lack of FUTEX_REQUEUE-like system call in WASI.
For now we wake all the waiters which is inefficient; if that becomes
a bottleneck, I suggest we'll revisit the implementation.
[POSIX semaphores] come in two forms: named and unnamed. Roughly, named
semaphores use files to implement locking across processes; unnamed
semaphores use a shared memory region to implement locking across
threads in the same process. Since WASI currently has no process concept
(and it is relatively unclear how to map the WASI files as shared
memory), only the unnamed semaphores are supported by this changed. This
means that `sem_open`, `sem_close`, and `sem_unlink` will not available
to programs compiled with a threads-enabled `wasi-libc`.
[POSIX semaphores]: https://man7.org/linux/man-pages/man7/sem_overview.7.html
This change adds pthread's mutex support to the `THREAD_MODEL=posix`
build of wasi-libc. Some less-common features are unsupported and
documented here:
- mutex robust lists are disabled and their use will return a runtime
error; currently WASI does not support the concept of multiple
processes so maintaining robust mutexes across processes does not yet
make sense in wasi-libc
- timed locks with priority inheritance (PI) are disabled and will act
as any other mutex; this feature is related to task priorities which
is not yet relevant in the WASI ecosystem (see [priority-inheritance
futexes](https://man7.org/linux/man-pages/man2/futex.2.html))
- thread cancellation is ignored; this feature is difficult to support
and @sunfishcode would likely want to discuss this before adding it at
some later time.