diff --git a/README.md b/README.md index db10dc1..f4c6239 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,8 @@ _TODO before entering Phase 2._ - [Use case: support various languages](#use-case-support-various-languages) - [Use case: support thread-local storage](#use-case-support-thread-local-storage) - [Detailed design discussion](#detailed-design-discussion) + - [Design choice: thread IDs](#design-choice-thread-ids) + - [Design choice: termination](#design-choice-termination) - [Design choice: pthreads](#design-choice-pthreads) - [Design choice: instance-per-thread](#design-choice-instance-per-thread) - [Considered alternatives](#considered-alternatives) @@ -90,9 +92,9 @@ The API consists of a single function. In pseudo-code: status wasi_thread_spawn(thread_start_arg* start_arg); ``` -where the `status` is a unique non-negative integer thread ID of the new -thread or negative number representing an error in case the thread failed to -start. +where the `status` is a unique non-negative integer thread ID (TID) of the new +thread (see [Design choice: thread IDs](#design-choice-thread-ids)) or a +negative number representing an error if the host failed to spawn the thread. The host implementing `wasi_thread_spawn` will call a predetermined function export (`wasi_thread_start`) in a new WebAssembly instance. Any necessary locking/signaling/thread-local storage will be implemented using existing @@ -127,13 +129,10 @@ TLS bookkeeping (this is not much different than how C starts threads natively). ### Detailed design discussion -Threads are tricky to implement. This proposal relies on a specific WebAssembly -convention in order to work correctly. - -When instantiating a module which is expected to run with wasi-threads, -the WASI host must: - -1. create and provide shared memories to satisfy the module's imports. +Threads are tricky to implement. This proposal relies on a specific convention +in order to work correctly. When instantiating a module which is expected to run +with `wasi-threads`, the WASI host must first allocate shared memories to +satisfy the module's imports. Upon a call to `wasi_thread_spawn`, the WASI host must: @@ -152,69 +151,32 @@ Upon a call to `wasi_thread_spawn`, the WASI host must: A WASI host that implements the above should be able to spawn threads for a variety of languages. -### TID (thread ID) - -TID is a 32-bit integer to identify threads created with `wasi_thread_spawn`. - -* TIDs are managed and provided by host. - -* TID 0 is reserved. `wasi_thread_spawn` should not return this value. - - * It's widely assumed in musl/wasi-libc. - -* The upper-most 3-bits of TID are always 0. - `wasi_thread_spawn` should not return values with these bits set. - - * The most significant bit is the sign bit. As `wasi_thread_spawn` uses - signed integer and uses negative values to indicate errors, a TID needs - to be positive. - - * The second bit need to be 0 in order to be compatible with the TID-based - locking implementation in musl/wasi-libc. - - * The third bit need to be 0 in order to make an extra room for other - reserved values in wasi-libc. - For example, it can be used to indicate the main thread, which doesn't - have a TID in the current version of this proposal. - -### Process - -* A process is a group of threads. - -* The main thread starts with a process which only contains - the main thread. - -* Threads created by a thread in a process using `wasi_thread_spawn` - are added to the process. - -* When a thread is terminated, it's removed from the process. - -### Voluntary thread termination - -A thread can terminate itself voluntarily by returning from -`wasi_thread_start`. - -### Changes to WASI `proc_exit` - -With this proposal, the `proc_exit` function takes extra responsibility -to terminate all threads in the process, not only the calling one. - -Any of the threads in the process can call `proc_exit`. +#### Design choice: thread IDs -### Traps +When `wasi_thread_spawn` successfully spawns a thread, it returns a thread ID +(TID) — 32-bit integer with several restrictions. TIDs are managed and +provided by the WASI host. To avoid leaking information, the host may choose to +return arbitrary TIDs (as opposed to leaking OS TIDs). -When a trap occurs in any thread, the entire process is terminated. +Valid TIDs fall in the range $[1, 2^{29})$. Some considerations apply: +- `0` is reserved for compatibility reasons with existing libraries (e.g., + wasi-libc) and must not be returned by `wasi_thread_spawn` +- the uppermost three bits of a valid TID must always be `0`. The most + significant bit is the sign bit and recall that `wasi_thread_spawn` uses + negative values to indicate errors. The remaining bits are reserved for + compatibility with existing language implementations. -### Process exit status +#### Design choice: termination -If one or more threads call WASI `proc_exit` or raise a trap, -one of them is chosen by the runtime to represent the exit status -of the process. -It's non deterministic which one is chosen. +A `wasi-threads` module initially executes a single thread — the main +thread. As `wasi_thread_spawn` is called, more threads begin to execute. Threads +terminate in the following ways: -If all the threads in the process have been terminated without calling -`proc_exit` or raising a trap, it's treated as if the last thread called -`proc_exit` with exit code 0. +- __upon return__ from `wasi_thread_start`, and other threads continue to + execute +- __upon a trap__ in any thread; all threads are immediately terminated +- __upon a `proc_exit` call__ in any thread; all threads are immediately + terminated. #### Design choice: pthreads