Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/wapython
Path: blob/main/core/posix-wasm/src/threads.h
1067 views
1
#ifndef WASMPOSIXTHREADS
2
#define WASMPOSIXTHREADS
3
4
#include <time.h>
5
#include <stdbool.h>
6
7
#define CLOCK_THREAD_CPUTIME_ID 3
8
9
#define SCHED_OTHER 0
10
#define PTHREAD_CANCEL_ASYNCHRONOUS 1
11
#define PTHREAD_CANCEL_ENABLE 2
12
#define PTHREAD_CANCEL_DEFERRED 3
13
#define PTHREAD_CANCEL_DISABLE 4
14
#define PTHREAD_CREATE_DETACHED 5
15
#define PTHREAD_CREATE_JOINABLE 6
16
#define PTHREAD_EXPLICIT_SCHED 7
17
#define PTHREAD_INHERIT_SCHED 8
18
#define PTHREAD_MUTEX_DEFAULT 9
19
#define PTHREAD_MUTEX_ERRORCHECK 10
20
#define PTHREAD_MUTEX_NORMAL 11
21
#define PTHREAD_MUTEX_RECURSIVE 12
22
#define PTHREAD_MUTEX_ROBUST 13
23
#define PTHREAD_MUTEX_STALLED 14
24
#define PTHREAD_PRIO_INHERIT 15
25
#define PTHREAD_PRIO_NONE 16
26
#define PTHREAD_PRIO_PROTECT 17
27
#define PTHREAD_PROCESS_SHARED 18
28
#define PTHREAD_PROCESS_PRIVATE 19
29
#define PTHREAD_SCOPE_PROCESS 20
30
#define PTHREAD_SCOPE_SYSTEM 21
31
#define PTHREAD_BARRIER_SERIAL_THREAD 22
32
33
/* Data structure to describe a process' schedulability. */
34
// This struct is copied from zig's
35
// lib/libc/include/generic-glibc/bits/types/struct_sched_param.h which is
36
// copied from glibc.
37
// We do this because unthread had
38
// #include <bits/types/struct_sched_param.h>
39
// which is including something from glibc, which is NOT in musl.
40
struct sched_param {
41
int sched_priority;
42
};
43
44
// pthread_attr_t is defined as a union somewhere in some glibc header, so we
45
// pretend its a union here as well.
46
union pthread_attr_t {
47
struct {
48
int initialized;
49
int detach_state;
50
size_t guard_size;
51
int inherit_sched;
52
int scope;
53
struct sched_param sched_param;
54
int sched_policy;
55
void **stack_addr;
56
size_t stack_size;
57
} data;
58
};
59
60
typedef struct {
61
int initialized;
62
int pshared;
63
clockid_t clock_id;
64
} pthread_condattr_t;
65
66
typedef struct pthread_fiber *pthread_t;
67
68
// We would rather not expose these internals, but C does not leave us much
69
// choice unless we want to heap allocate each of these.
70
71
72
struct pthread_fiber;
73
struct pthread_list {
74
size_t len;
75
size_t cap;
76
union {
77
// Store a small list inline or a large list on the heap. Possibly an
78
// unnecessary micro-optimization, but eh.
79
struct pthread_fiber *small[4];
80
struct pthread_fiber **big;
81
} threads;
82
};
83
84
85
typedef struct {
86
int initialized;
87
struct pthread_fiber *locked_by;
88
struct pthread_list waiting;
89
int type;
90
unsigned int rec_count;
91
int prioceiling;
92
int robust;
93
} pthread_mutex_t;
94
95
96
typedef struct {
97
int initialized;
98
struct pthread_list waiting;
99
} pthread_cond_t;
100
101
#define PTHREAD_EMPTY_LIST_INITIALIZER \
102
{ \
103
.len = 0, \
104
.cap = sizeof((struct pthread_list){}.threads.small) / \
105
sizeof(*(struct pthread_list){}.threads.small), \
106
}
107
108
static const struct pthread_list pthread_empty_list =
109
PTHREAD_EMPTY_LIST_INITIALIZER;
110
111
112
113
enum thread_state {
114
RUNNING,
115
};
116
117
118
struct tls_entry {
119
size_t id;
120
void *value;
121
void (*destructor)(void *);
122
};
123
124
struct tls {
125
struct tls_entry *entries;
126
size_t cap, len;
127
};
128
129
typedef struct pthread_cleanup_t {
130
void (*routine)(void *);
131
void *arg;
132
struct pthread_cleanup_t *prev;
133
} pthread_cleanup_t;
134
135
typedef struct {
136
int initialized;
137
int prioceiling;
138
int protocol;
139
int pshared;
140
int type;
141
int robust;
142
} pthread_mutexattr_t;
143
144
typedef struct {
145
int initialized;
146
unsigned int id;
147
void (*destructor)(void *);
148
} pthread_key_t;
149
150
151
struct pthread_fiber {
152
unsigned int id;
153
154
bool detached;
155
bool owns_stack;
156
157
// The index of this thread in the lists we are currently a member of.
158
//
159
// For example, when waiting on a mutex the current thread is added to the
160
// list. Having the index in the thread itself means operations like
161
// pop_specific can be implemented in O(1) time.
162
//
163
// A thread may be a member of the threads_ready list in addition to one
164
// other list. This means there are two "slots" for indices, with 0 being for
165
// the index in the threads_ready list and 1 for the index in the other list.
166
// This is used when blocking on a timed lock, where a thread may both be
167
// ready (for the purposes of Unthread) and waiting on a lock at the same
168
// time.
169
size_t list_index[2];
170
171
// pthread_attr_t used to create this thread.
172
union pthread_attr_t attr;
173
174
enum thread_state state;
175
176
union {
177
// When blocked on pthread_join, contains the thread being joined
178
pthread_t joining;
179
180
// When blocked on pthread_cond_wait and pthread_cond_timedwait, this will
181
// be the mutex to acquire when the condition variable is signalled.
182
pthread_mutex_t *cond_mutex;
183
184
// When blocked on pthread_barrier_wait, this will be true if the thread
185
// was chosen as the serial thread of the barrier.
186
bool barrier_serial;
187
188
// When a thread is stopped, this will be the return value of the thread.
189
void *retval;
190
191
// When blocked on pthread_rwlock or pthread_rwlock_timedrdlock, this is
192
// whether the current thread has been granted reader access.
193
bool rwlock_reader;
194
} state_data;
195
196
// The thread that this thread is being joined by, or NULL if no thread is
197
// currently joining this thread.
198
pthread_t joined_by;
199
200
// Thread local storage map for this thread
201
struct tls tls;
202
203
int cancel_state;
204
int cancel_type;
205
206
// Whether a cancellation signal has been sent. Since the signal is
207
// asynchronous, we may act on them much sooner than it is sent.
208
bool canceled;
209
210
pthread_cleanup_t *cleanup;
211
212
int sched_policy;
213
struct sched_param sched_param;
214
215
__attribute__((aligned(16))) char stack[];
216
};
217
218
219
#endif
220