1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
/* <threads.h> — the C11 thread support library (C11 7.26).
*
* These are the platform's own threads: `thrd_create` is the C library's
* `thrd_create`, and the objects declared below are laid out the way that
* library lays them out, so a `mtx_t` an expansion of `cinrs` puts on the
* stack is a `pthread_mutex_t` the library can lock. That is the whole point
* of the header, and it is also why it is *not* one type-for-type table like
* `<stdio.h>`: two of the types are opaque blocks of bytes whose size is a
* property of the C library rather than of C, so the branches below are by
* library rather than by data model alone.
*
* # Which libraries
*
* * **Linux with glibc** (`__cinrs_glibc__`): `thrd_t` is glibc's `__thrd_t`,
* an `unsigned long`; `mtx_t` and `cnd_t` are `pthread_mutex_t`'s and
* `pthread_cond_t`'s sizes, written the way glibc writes them — a union of
* a `char` array and an alignment carrier. The functions themselves have
* been in glibc since **2.28** (2018); an older one has the `pthread_*`
* they are built on but not these names, and the link will fail.
* * **Linux with musl** (`__cinrs_musl__`): the same three objects with musl's
* own sizes and alignments — its `pthread_t` is a pointer, and its mutex is
* forty bytes on a 32-bit target where glibc's is twenty-four.
* * **Apple**: there is no `<threads.h>` in libSystem at all — no `thrd_*`
* symbols to link against — so the header refuses rather than declaring
* functions that are not there.
* * **Windows**: the Microsoft UCRT has no such header either. mingw-w64
* supplies one on top of winpthreads, whose layouts are winpthreads' rather
* than the runtime's; that is a fourth model and this header does not claim
* it.
* * **Everything else** — the BSDs, Android's bionic, uClibc, a freestanding
* target: refused with the reason. FreeBSD does have `<threads.h>`, and its
* layouts are its own; a header that guessed at one of them would corrupt
* memory rather than fail to compile.
*
* `<threads.h>` working is what decides `__STDC_NO_THREADS__`: the macro is
* predefined exactly on the targets where this header refuses, which is C11
* 6.10.8.3's way of saying the feature is not there.
*
* # What is deliberately left out
*
* `thrd_sleep`, `mtx_timedlock` and `cnd_timedwait` take a `struct timespec`,
* which is in `<time.h>` where C puts it. Nothing here declares a
* `pthread_*` type: a program that wants those wants the platform's own
* `<pthread.h>`, through `#pragma cinrs include_path`.
*/
/* Every declaration is in the branch below, so that the one diagnostic a
* refused target gets is this one and not a cascade of undeclared types. */
/* `struct timespec`, which three of the functions below take. */
/* C11 7.26.1p3: the header defines `thread_local` as `_Thread_local`. C23
* (N2934) made `thread_local` a keyword instead, so defining it there would be
* defining a keyword as a macro; glibc's own header has the same `#if`. */
/* C11 7.26.6.1p3: how many times a thread's storage is swept for values whose
* destructor set a new one. Four on glibc, musl and POSIX alike. */
/* -- the objects ---------------------------------------------------------- */
/* glibc spells `once_flag` as a one-member `struct { int __data; }` and musl
* as a plain `int`; both are four bytes holding zero to begin with, and the
* flag is only ever passed by address, so the two are the same object to a
* caller. `int` is the spelling that lets `once_flag f = ONCE_FLAG_INIT;`
* work without braces, which is what programs write. */
typedef int once_flag;
/* musl's `thrd_t` is its `pthread_t`, a pointer to an incomplete structure. */
typedef struct __cinrs_musl_thread *thrd_t;
/* glibc's `__thrd_t`. */
typedef unsigned long thrd_t;
/* glibc's `__tss_t` and musl's `pthread_key_t` are both `unsigned int`. */
typedef unsigned int tss_t;
typedef void ;
typedef int ;
/* The size of the mutex, which is the C library's `sizeof(pthread_mutex_t)`.
*
* glibc: forty bytes on a 64-bit target — five `int`s, two `short`s and a
* two-pointer list node — twenty-four on a 32-bit one, and thirty-two on the
* x32 ABI, which keeps the 64-bit `struct` with 32-bit pointers.
* musl: forty everywhere, its mutex being a union of ten `int`s and five
* pointers.
*
* The alignment carrier is glibc's own `long`, which gives eight bytes on a
* 64-bit target and four on a 32-bit one — the alignment musl's pointer union
* has as well. */
typedef union mtx_t;
/* Forty-eight bytes in both libraries and on every data model.
*
* The carrier differs: glibc aligns `pthread_cond_t` to `long long` — its
* internal counters are 64-bit even on a 32-bit machine — and musl aligns its
* to a pointer. `__extension__` because `long long` is C99's and a header may
* use it whatever entry point included it. */
typedef union cnd_t;
typedef union cnd_t;
/* -- the constants -------------------------------------------------------- */
/* C11 7.26.1p5. The values are the two libraries', which agree; a program
* that compares a return value against `thrd_success` is comparing against
* what the real function returned. */
;
/* C11 7.26.1p4: `mtx_timed` and `mtx_recursive` may be combined, which is why
* they are powers of two in some libraries — but not in these two, where the
* values are plain 0, 1 and 2 and `mtx_timed | mtx_recursive` is 3. */
;
/* -- threads (7.26.5) ----------------------------------------------------- */
int ;
int ;
thrd_t ;
int ;
void ;
__cinrs_noreturn void ;
int ;
int ;
/* -- mutexes (7.26.4) ----------------------------------------------------- */
int ;
int ;
int ;
int ;
int ;
void ;
/* -- call once (7.26.2) --------------------------------------------------- */
void ;
/* -- condition variables (7.26.3) ----------------------------------------- */
int ;
int ;
int ;
int ;
int ;
void ;
/* -- thread-specific storage (7.26.6) ------------------------------------- */
int ;
void *;
int ;
void ;
/* _CINRS_THREADS_H */