Skip to content

Commit 0ab2582

Browse files
authored
Update README.md
Moved the proposal here
1 parent b7afc5f commit 0ab2582

1 file changed

Lines changed: 150 additions & 45 deletions

File tree

README.md

Lines changed: 150 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,19 @@
1-
# [Example WASI proposal]
1+
# Native Threads API
22

3-
This template can be used to start a new proposal, which can then be proposed in the WASI Subgroup meetings.
4-
5-
The sections below are recommended. However, every proposal is different, and the community can help you flesh out the proposal, so don't block on having something filled in for each one of them.
6-
7-
Thank you to the W3C Privacy CG for the [inspiration](https://github.com/privacycg/template)!
8-
9-
# [Title]
10-
11-
A proposed [WebAssembly System Interface](https://github.com/WebAssembly/WASI) API.
3+
A proposed [WebAssembly System Interface](https://github.com/WebAssembly/WASI) API to add native thread support.
124

135
### Current Phase
146

15-
[Fill in the current phase, e.g. Phase 1]
7+
Phase 1
168

179
### Champions
1810

19-
- [Champion 1]
20-
- [Champion 2]
21-
- [etc.]
11+
- [Alexandru Ene](https://github.com/AlexEne)
12+
-
2213

2314
### Phase 4 Advancement Criteria
2415

25-
TODO before entering Phase 2.
16+
_TODO before entering Phase 2._
2617

2718
## Table of Contents [if the explainer is longer than one printed page]
2819

@@ -31,69 +22,177 @@ TODO before entering Phase 2.
3122
- [Non-goals](#non-goals)
3223
- [API walk-through](#api-walk-through)
3324
- [Use case 1](#use-case-1)
34-
- [Use case 2](#use-case-2)
3525
- [Detailed design discussion](#detailed-design-discussion)
3626
- [[Tricky design choice 1]](#tricky-design-choice-1)
37-
- [[Tricky design choice 2]](#tricky-design-choice-2)
27+
- [[Tricky design choice 2 - Adding join, detatch, cancel]](#tricky-design-choice-2)
3828
- [Considered alternatives](#considered-alternatives)
3929
- [[Alternative 1]](#alternative-1)
40-
- [[Alternative 2]](#alternative-2)
4130
- [Stakeholder Interest & Feedback](#stakeholder-interest--feedback)
4231
- [References & acknowledgements](#references--acknowledgements)
4332

4433
### Introduction
34+
This proposal looks to provide a standard API that can be used for thread creation / join and the rest of the operations that are neccessary to run native threads (such as handling threadlocals, taking locks, spawning a thread).
4535

46-
[The "executive summary" or "abstract". Explain in a few sentences what the goals of the project are, and a brief overview of how the solution works. This should be no more than 1-2 paragraphs.]
36+
### Goals
37+
The goal of this proposal is to add the missing functions that are required for implementing a subset of `pthread` API. It doesn't aim to be identical to the pthreads API, but must be able to create threads that operate on the same Wasm memory, while using the atomic instrutions to synchronize on memory access.
4738

48-
### Goals [or Motivating Use Cases, or Scenarios]
39+
Standardizing on this would allow re-use of existing libraries and code and remove friction from porting projects from native execution contexts to WebAssembly & WASI environments (outside the browsers).
4940

50-
[What is the end-user need which this project aims to address?]
41+
A possible future direction for WebAssembly is towards supporting multiple-threads per instance. This isn't possible with the current memory model and instruction set. We aim to expose an API that would be compatible with this future direction.
42+
43+
For browsers, we aim to provide a way to polyfill these APIs, leaveraging web-workers, in a similar to how it works today.
5144

5245
### Non-goals
5346

54-
[If there are "adjacent" goals which may appear to be in scope but aren't, enumerate them here. This section may be fleshed out as your design progresses and you encounter necessary technical and other trade-offs.]
47+
The goal of this API is not to be 100% compatible with all functions and options described by POSIX threads standard.
48+
49+
The current proposal is limited to the WASI APIs signatures and behavior and doesn't propose changes to the Wasm instruction set.
5550

5651
### API walk-through
5752

58-
[Walk through of how someone would use this API.]
53+
The API requires the addition of a single function.
54+
The mutex/signaling/TLS could be implemented using existing instructions available in WASM:
55+
```
56+
status thread_spawn(thread_id* thread_id, const thread_attributes* attrs, thread_start_func* function, thread_args* arg);
57+
```
5958

6059
#### [Use case 1]
61-
62-
[Provide example code snippets and diagrams explaining how the API would be used to solve the given problem]
60+
Implementing standard libraries on top of this API (e.g. Rust stdlib, pthreads).
6361

6462
#### [Use case 2]
65-
66-
[etc.]
63+
Support for thread-local storage.
6764

6865
### Detailed design discussion
66+
**TODO**:
67+
* Define attributes supported.
68+
* Clarify data types to match how other WASI methods are specified
69+
* Does it need a stack_size parameter?
70+
* Does it need instructions on how to set up the stack size?
71+
72+
#### How threads start
73+
When a thread is started by `thread_spawn` the following happens:
74+
1) The module instance is is cloned.
75+
2) A native thread is created.
76+
3) On that thread we call into a `_start_thread` function from the Wasm module created above and forwards the `arg` parameter (a pointer to the shared memory.
77+
4) `_start_thread` Function then launches the target `function` with the `arg` parameter.
78+
79+
`pthread_create` can be implemented by forwarding a call to the new `thread_spawn` API.
80+
```
81+
int pthread_create(pthread_t* thread_id, const pthread_attr_t* attr, void* *(*start_routine)(void*), void* arg);
82+
```
6983

70-
[This section should mostly refer to the .wit.md file that specifies the API. This section is for any discussion of the choices made in the API which don't make sense to document in the spec file itself.]
84+
The following functions can potentially be implemented either by introducing new WASI APIs similar to, or by using WASM atomics (e.g. in the case of `pthread_join`):
85+
```
86+
int pthread_join(pthread_t thread, void **retval);
7187
72-
#### [Tricky design choice #1]
88+
// Can this work without a new WASI API?
89+
int pthread_detach(pthread_t thread);
90+
91+
// How would this work?
92+
int pthread_cancel(pthread_t thread);
7393
74-
[Talk through the tradeoffs in coming to the specific design point you want to make.]
94+
pthread_t pthread_self(void);
95+
```
96+
This is currently highlighted in [[Design choice 2]](#tricky-design-choice-2)
7597

98+
All the functions below can be implemented WASI libc with existing constructs available in the language and don't require a new WASI function:
7699
```
77-
// Illustrated with example code.
100+
101+
// This is really tricky to use right.
102+
void pthread_exit(void *retval);
103+
104+
int pthread_yield(void);
78105
```
79106

80-
[This may be an open question, in which case you should link to any active discussion threads.]
107+
Mutexes:
108+
```
109+
int pthread_mutex_init(pthread_mutex_t *mutex, const void *attr);
81110
82-
#### [Tricky design choice 2]
111+
int pthread_mutex_lock(pthread_mutex_t *mutex);
83112
84-
[etc.]
113+
int pthread_mutex_unlock(pthread_mutex_t *mutex);
85114
86-
### Considered alternatives
115+
int pthread_mutex_destroy(pthread_mutex_t *mutex);
87116
88-
[This section is not required if you already covered considered alternatives in the design discussion above.]
117+
```
89118

90-
#### [Alternative 1]
119+
RW Locks:
120+
```
121+
int pthread_rwlock_init(pthread_rwlock_t *rwlock, const pthread_rwlockattr_t *attr);
122+
123+
int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock);
124+
125+
int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock);
126+
127+
int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock);
128+
129+
int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock);
130+
131+
int pthread_rwlock_unlock();
132+
133+
int pthread_rwlock_destroy(pthread_rwlock_t *rwlock);
134+
```
91135

92-
[Describe an alternative which was considered, and why you decided against it.]
136+
Conditionals:
137+
```
138+
int pthread_cond_init(pthread_cond_t *cond, const void *attr);
139+
140+
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex);
141+
142+
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, unsigned int useconds);
143+
144+
int pthread_cond_signal(pthread_cond_t *cond);
145+
146+
int pthread_cond_broadcast(pthread_cond_t *cond);
147+
148+
int pthread_cond_destroy(pthread_cond_t *cond);
149+
```
150+
151+
Thread-specific data:
152+
```
153+
int pthread_key_create(pthread_key_t *key, void (*destructor)(void *));
154+
155+
int pthread_setspecific(pthread_key_t key, const void *value);
156+
157+
void *pthread_getspecific(pthread_key_t key);
158+
159+
int pthread_key_delete(pthread_key_t key);
160+
```
161+
162+
#### [Tricky design choice #1]
93163

94-
#### [Alternative 2]
164+
This could be implemented either by cloning the current Wasm instance and executing it on another thread, or by having the instance shared amonst threads. Cloning the instance means that all the WASM constructs such as: Wasm globals (not C++ globals, these live in the Wasm linear memory, not the instance data), function tables will be thread local.
95165

96-
[etc.]
166+
We consider this a good approach for the first implementation phase and aim to switch to a multiple threads per Wasm Instance once the `shared` attributes are added to the Wasm spec. Sharing the same instance right now is blocked on that attribute. More data on it can be found in this paper: [Weakening WebAssembly](https://www.researchgate.net/publication/336447205_Weakening_WebAssembly).
167+
168+
There are disadvantages to this approach of a thread gets its own module instance such as:
169+
* Memory consumption (as each instance is cloned)
170+
* Breaking behavior on non-standard functions such as `dlopen()` that require to modify the function table.
171+
* Potential breaking behaviour of existing binaries once a new instruction gets added. This is low risk because no attributes on globals/tables/etc. having the meaning of `shared` in a future wasm spec iteration isn't a likely approach. Most likely, no attributes would be interpreted as `local`/`private` as that would keep the existing behavior for binaries.
172+
173+
The API here shouldn't need to change the signature if new annotations and instructions get added to the standard (e.g. `shared` and `local` flags on `globals`, `tables`, etc.). Regardless of those, the function exposed in this proposal will still take the same arguments and have the same return types in all of the potential execution modes. The function signature and observed behavior should stay the same (except dlopen behavior that is more restricted above).
174+
175+
#### [Tricky design choice #2]
176+
While the following functions can potentially be implemented in wasm bytecode (is this true for `pthread_detatch`?), leaveraging the atomic operations available, it may be benefficial to have these functions included in the WASI proposal as this would aleviate bytecode size concerns for WASM binaries, performance concerns and can also potentially simplify some implementation details.
177+
178+
```
179+
int pthread_join(pthread_t thread, void **retval);
180+
181+
int pthread_detach(pthread_t thread);
182+
183+
int pthread_cancel(pthread_t thread);
184+
185+
pthread_t pthread_self(void);
186+
```
187+
188+
### Considered alternatives
189+
190+
#### [Alternative 1]
191+
192+
[WASI-parallel](https://github.com/WebAssembly/wasi-parallel/blob/main/docs/Explainer.md).
193+
194+
*TODO(alexene) check that this understanding is correct*
195+
The wasi-parallel proposal could be used in similar ways to [OpenMP](https://www.openmp.org/). That mode of parallelism solves a category of problems (map-reduce type algorithms are suited to such an approach), but can't be applied to other workloads that are covered in this proposal that require more fine-grained control over how threads are created/destroyed and their lifetimes.
97196

98197
### Stakeholder Interest & Feedback
99198

@@ -103,8 +202,14 @@ TODO before entering Phase 3.
103202

104203
### References & acknowledgements
105204

106-
Many thanks for valuable feedback and advice from:
107-
108-
- [Person 1]
109-
- [Person 2]
110-
- [etc.]
205+
Many thanks for valuable feedback and advice from (alphabetical order):
206+
* [Amanieu d'Antras](https://github.com/Amanieu)
207+
* [Andrew Brown](https://github.com/abrown)
208+
* [Conrad Watt](https://github.com/conrad-watt)
209+
* [George Kulakowski](https://github.com/kulakowski-wasm)
210+
* [Nathaniel McCallum](https://github.com/npmccallum)
211+
* [Petr Penzin](https://github.com/penzn)
212+
* [Sam Clegg](https://github.com/sbc100)
213+
* [Wang Xin](https://github.com/xwang98)
214+
* [Wenyong Huang](https://github.com/wenyongh)
215+
* Xu Jun

0 commit comments

Comments
 (0)