@@ -116,17 +116,17 @@ contain a language-specific structure with the address and (potentially) the
116116length of a TLS memory region. The host WebAssembly engine will treat this
117117argument as an opaque pointer — it should not introspect these
118118language-specific details. In C, e.g., the start function should be a static
119- trampoline-like wrapper (`wasilibc_thread_start `) that reads the actual user
120- start function out of the start argument and calls this after doing some TLS
121- bookkeeping (this is not different than how C starts threads natively).
119+ trampoline-like wrapper (exported as `wasi_thread_start `) that reads the actual
120+ user start function out of the start argument and calls this after doing some
121+ TLS bookkeeping (this is not much different than how C starts threads natively).
122122
123123
124124
125125### Detailed design discussion
126126
127127Threads are tricky to implement. This proposal relies on a specific WebAssembly
128- convention in order to work correctly. Upon a call to `thread_spawn `, the WASI
129- host must:
128+ convention in order to work correctly. Upon a call to `wasi_thread_spawn `, the
129+ WASI host must:
1301301. instantiate the module again — this child instance will be used for the
131131 new thread
1321322. in the child instance, ensure that any `shared` memories are the same ones as
@@ -136,8 +136,8 @@ host must:
1361364. optionally, spawn a new host-level thread (other spawning mechanisms are
137137 possible)
1381385. calculate a non-duplicate thread ID, `tid`
139- 6. in the new thread, call the child instance's start function with the thread ID
140- and the start argument: `start_func (tid, start_arg)`
139+ 6. in the new thread, call the child instance's exported entry function with the
140+ thread ID and the start argument: `wasi_thread_start (tid, start_arg)`
141141
142142A WASI host that implements the above should be able to spawn threads for a
143143variety of languages.
@@ -149,33 +149,34 @@ to WebAssembly. Given a WASI host that implements `thread_spawn` as described
149149above, what responsibility would the C language have (i.e., `libc`) to properly
150150implement `pthreads`?
151151
152- `pthread_create` must not only call WASI's `thread_spawn ` but is also
152+ `pthread_create` must not only call WASI's `wasi_thread_spawn ` but is also
153153responsible for setting up the new thread's stack, TLS/TSD space, and updating
154- the `pthread_t` structure. This could be implemented by (ignoring error
155- conditions):
156- 1. configure a `struct start_args` with the user's `void *(*start_func)(void
157- *)` and `void *start_arg` (as done natively) but also with `pthread_t *thread`
154+ the `pthread_t` structure. This could be implemented by the following steps
155+ (ignoring error conditions):
156+ 1. configure a `struct start_args` with the user's `void *(*start_func)(void *)`
157+ and `void *start_arg` (as done natively) but also with `pthread_t *thread`
1581582. call `malloc` (instead of `mmap`) to allocate TLS/TSD in the shared
159159 WebAssembly memory
160- 3. having defined a static `wasilibc_thread_start` function that takes as
161- parameters `int tid` and `void *start_args` , then in `pthread_create`, call
162- the WASI `thread_spawn` with this function and the configured `start_args`
163- 4. use `atomic.wait` to wait for the `start_args->thread->tid` value to change
160+ 3. define a static, exported `wasi_thread_start` function that takes as
161+ parameters `int tid` and `void *start_args`
162+ 4. in `pthread_create`, call `wasi_thread_spawn` with the configured
163+ `start_args` and use `atomic.wait` to wait for the `start_args->thread->tid`
164+ value to change
1641655. now in the child thread: once the WASI host creates the new thread instance
165- and calls `wasilibc_thread_start `, then a) set `args->thread->tid` to the
166+ and calls `wasi_thread_start `, then a) set `args->thread->tid` to the
166167 host-provided `tid`, b) set the `__wasilibc_pthread_self` global to point to
167168 `args->thread` (this is used by `pthread_self`, e.g.), c) use `atomic.notify`
168- to inform the parent thread that the child now has a `tid`, d) start executing
169- the user's `start_func` with the user's `start_arg` — at this point the
170- new instance is executing separately in its own thread
169+ to inform the parent thread that the child now has a `tid`, d) start
170+ executing the user's `start_func` with the user's `start_arg` — at this
171+ point the new instance is executing separately in its own thread
1711726. back in the parent thread: once it has been notified that the child has
172- recorded its TID, it can safely return with the `pthread_t` structure properly
173- filled out.
173+ recorded its TID, it can safely return with the `pthread_t` structure
174+ properly filled out.
174175
175176`pthread_join` has a similar `wait`/`notify` implementation, but in reverse: the
176177parent thread can `wait` on the `thread->return` address to change and the child
177178thread can `notify` it of this once the user's start function finishes (i.e., at
178- the end of the `wasilibc_thread_start ` wrapper).
179+ the end of the `wasi_thread_start ` wrapper).
179180
180181The remainder of the `pthreads` API can be split up into what can be implemented
181182and what can safely be skipped until some later date.
@@ -218,8 +219,8 @@ ways: the way chosen here, a cloned "instance-per-thread," is one option. The
218219other major option is to share the instance among many threads, as described in
219220the [Weakening WebAssembly] paper. Sharing an instance among many threads, as
220221described there, would require:
221- - WebAssembly objects (memories, tables, globals, functions) to allow a `shared`
222- attribute
222+ - WebAssembly objects (memories, tables, globals, functions) to allow a
223+ `shared` attribute
223224 - the WebAssembly specification to grow a `fork` instruction
224225
225226[Weakening WebAssembly]: https://www.researchgate.net/publication/336447205_Weakening_WebAssembly
0 commit comments