This source file includes following definitions.
- do_init_thrd_with_exitcode_key
- init_thrd_with_exitcode_key
- thrd_main_func
- rpl_thrd_create
- rpl_thrd_current
- rpl_thrd_equal
- rpl_thrd_detach
- rpl_thrd_join
- rpl_thrd_join
- pthread_main_func
- thrd_create
- thrd_current
- thrd_equal
- thrd_yield
- thrd_detach
- thrd_join
- thrd_exit
- thrd_create
- thrd_current
- thrd_equal
- thrd_yield
- thrd_detach
- thrd_join
- thrd_exit
- thrd_sleep
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 #include <config.h>
21
22 #include <threads.h>
23
24 #include <stdlib.h>
25
26 #if HAVE_THREADS_H
27
28
29 # if BROKEN_THRD_START_T
30
31 # undef thrd_t
32
33
34
35
36
37
38
39 static tss_t thrd_with_exitcode_key;
40
41
42
43 static void
44 do_init_thrd_with_exitcode_key (void)
45 {
46 if (tss_create (&thrd_with_exitcode_key, NULL) != thrd_success)
47 abort ();
48 }
49
50
51 static void
52 init_thrd_with_exitcode_key (void)
53 {
54 static once_flag once = ONCE_FLAG_INIT;
55 call_once (&once, do_init_thrd_with_exitcode_key);
56 }
57
58 typedef union
59 {
60 struct thrd_with_exitcode t;
61 struct
62 {
63 thrd_t tid;
64 int detached;
65 thrd_start_t mainfunc;
66 void *arg;
67 } a;
68 }
69 main_arg_t;
70
71 static void *
72 thrd_main_func (void *pmarg)
73 {
74
75 main_arg_t *main_arg = (main_arg_t *) pmarg;
76 thrd_start_t mainfunc = main_arg->a.mainfunc;
77 void *arg = main_arg->a.arg;
78
79 if (tss_set (thrd_with_exitcode_key, &main_arg->t) != thrd_success)
80 abort ();
81
82
83 {
84 int exitcode = mainfunc (arg);
85
86 main_arg->t.exitcode = exitcode;
87 if (main_arg->t.detached)
88 {
89
90 free (&main_arg->t);
91 }
92 return NULL;
93 }
94 }
95
96 int
97 rpl_thrd_create (rpl_thrd_t *threadp, thrd_start_t mainfunc, void *arg)
98 # undef thrd_create
99 {
100 init_thrd_with_exitcode_key ();
101 {
102
103
104
105
106 main_arg_t *main_arg = (main_arg_t *) malloc (sizeof (main_arg_t));
107 if (main_arg == NULL)
108 return thrd_nomem;
109 main_arg->a.mainfunc = mainfunc;
110 main_arg->a.arg = arg;
111 main_arg->t.detached = 0;
112 {
113 int err =
114 thrd_create ((thrd_t *) &main_arg->t.tid, thrd_main_func, main_arg);
115 if (err == thrd_success)
116 *threadp = &main_arg->t;
117 else
118 free (main_arg);
119 return err;
120 }
121 }
122 }
123
124 rpl_thrd_t
125 rpl_thrd_current (void)
126 # undef thrd_current
127 {
128 init_thrd_with_exitcode_key ();
129 {
130 rpl_thrd_t thread =
131 (struct thrd_with_exitcode *) tss_get (thrd_with_exitcode_key);
132 if (thread == NULL)
133 {
134
135
136 for (;;)
137 {
138 thread =
139 (struct thrd_with_exitcode *)
140 malloc (sizeof (struct thrd_with_exitcode));
141 if (thread != NULL)
142 break;
143
144
145 {
146 struct timespec ts;
147 ts.tv_sec = 1;
148 ts.tv_nsec = 0;
149 thrd_sleep (&ts, NULL);
150 }
151 }
152 thread->tid = thrd_current ();
153 thread->detached = 0;
154 thread->exitcode = 0;
155 if (tss_set (thrd_with_exitcode_key, thread) != thrd_success)
156 abort ();
157 }
158 return thread;
159 }
160 }
161
162 int
163 rpl_thrd_equal (rpl_thrd_t thread1, rpl_thrd_t thread2)
164 {
165 return thread1 == thread2;
166 }
167
168 int
169 rpl_thrd_detach (rpl_thrd_t thread)
170 # undef thrd_detach
171 {
172 if (thread->detached)
173 return thrd_error;
174 {
175 int err =
176 thrd_detach (thread == rpl_thrd_current ()
177 ?
178 thrd_current ()
179 : thread->tid);
180 if (err == thrd_success)
181 thread->detached = 1;
182 return err;
183 }
184 }
185
186 int
187 rpl_thrd_join (rpl_thrd_t thread, int *exitcodep)
188 # undef thrd_join
189 {
190 if (thread == rpl_thrd_current () || thread->detached)
191 return thrd_error;
192 {
193 int err = thrd_join (thread->tid, NULL);
194 if (err == thrd_success)
195 {
196 if (exitcodep != NULL)
197 *exitcodep = thread->exitcode;
198 free (thread);
199 }
200 return err;
201 }
202 }
203
204 # endif
205
206 # if BROKEN_THRD_JOIN
207
208
209 int
210 rpl_thrd_join (thrd_t thread, int *exitcodep)
211 # undef thrd_join
212 {
213 int exitcode;
214 int err = thrd_join (thread, &exitcode);
215 if (err == 0 && exitcodep != NULL)
216 *exitcodep = exitcode;
217 return err;
218 }
219
220 # endif
221
222 #else
223
224 # include <errno.h>
225 # include <stdint.h>
226
227 # if defined _WIN32 && ! defined __CYGWIN__
228
229
230 # define WIN32_LEAN_AND_MEAN
231 # include <windows.h>
232
233 # else
234
235
236 # include <pthread.h>
237 # include <sched.h>
238
239 # endif
240
241
242
243
244
245 struct pthread_main_arg_t
246 {
247 thrd_start_t mainfunc;
248 void *arg;
249 };
250
251 static void *
252 pthread_main_func (void *pmarg)
253 {
254
255 struct pthread_main_arg_t *pthread_main_arg =
256 (struct pthread_main_arg_t *) pmarg;
257 thrd_start_t mainfunc = pthread_main_arg->mainfunc;
258 void *arg = pthread_main_arg->arg;
259
260
261 free (pmarg);
262
263
264 {
265 int exitcode = mainfunc (arg);
266
267
268
269
270 return (void *) (intptr_t) exitcode;
271 }
272 }
273
274 # if defined _WIN32 && ! defined __CYGWIN__
275
276
277 int
278 thrd_create (thrd_t *threadp, thrd_start_t mainfunc, void *arg)
279 {
280
281
282
283
284 struct pthread_main_arg_t *pthread_main_arg =
285 (struct pthread_main_arg_t *) malloc (sizeof (struct pthread_main_arg_t));
286 if (pthread_main_arg == NULL)
287 return thrd_nomem;
288 pthread_main_arg->mainfunc = mainfunc;
289 pthread_main_arg->arg = arg;
290
291 {
292 int err = glwthread_thread_create (threadp, 0,
293 pthread_main_func, pthread_main_arg);
294 if (err != 0)
295 free (pthread_main_arg);
296 return (err == 0 ? thrd_success :
297 err == ENOMEM ? thrd_nomem :
298 thrd_error);
299 }
300 }
301
302 thrd_t
303 thrd_current (void)
304 {
305 return glwthread_thread_self ();
306 }
307
308 int
309 thrd_equal (thrd_t thread1, thrd_t thread2)
310 {
311 return thread1 == thread2;
312 }
313
314 void
315 thrd_yield (void)
316 {
317 Sleep (0);
318 }
319
320 int
321 thrd_detach (thrd_t thread)
322 {
323 int err = glwthread_thread_detach (thread);
324 return (err == 0 ? thrd_success : thrd_error);
325 }
326
327 int
328 thrd_join (thrd_t thread, int *exitcodep)
329 {
330 void *exitptr;
331 int err = glwthread_thread_join (thread, &exitptr);
332 if (err == 0)
333 {
334 if (exitcodep != NULL)
335 *exitcodep = (int) (intptr_t) exitptr;
336 return thrd_success;
337 }
338 else
339 return thrd_error;
340 }
341
342 _Noreturn void
343 thrd_exit (int exitcode)
344 {
345 glwthread_thread_exit ((void *) (intptr_t) exitcode);
346 }
347
348 # else
349
350
351 int
352 thrd_create (thrd_t *threadp, thrd_start_t mainfunc, void *arg)
353 {
354
355
356
357
358 struct pthread_main_arg_t *pthread_main_arg =
359 (struct pthread_main_arg_t *) malloc (sizeof (struct pthread_main_arg_t));
360 if (pthread_main_arg == NULL)
361 return thrd_nomem;
362 pthread_main_arg->mainfunc = mainfunc;
363 pthread_main_arg->arg = arg;
364
365 {
366 int err = pthread_create (threadp, NULL,
367 pthread_main_func, pthread_main_arg);
368 if (err != 0)
369 free (pthread_main_arg);
370 return (err == 0 ? thrd_success :
371 err == ENOMEM ? thrd_nomem :
372 thrd_error);
373 }
374 }
375
376 thrd_t
377 thrd_current (void)
378 {
379 return pthread_self ();
380 }
381
382 int
383 thrd_equal (thrd_t thread1, thrd_t thread2)
384 {
385 return pthread_equal (thread1, thread2);
386 }
387
388 void
389 thrd_yield (void)
390 {
391 sched_yield ();
392 }
393
394 int
395 thrd_detach (thrd_t thread)
396 {
397 int err = pthread_detach (thread);
398 return (err == 0 ? thrd_success : thrd_error);
399 }
400
401 int
402 thrd_join (thrd_t thread, int *exitcodep)
403 {
404 void *exitptr;
405 int err = pthread_join (thread, &exitptr);
406 if (err == 0)
407 {
408 if (exitcodep != NULL)
409 *exitcodep = (int) (intptr_t) exitptr;
410 return thrd_success;
411 }
412 else
413 return thrd_error;
414 }
415
416 _Noreturn void
417 thrd_exit (int exitcode)
418 {
419 pthread_exit ((void *) (intptr_t) exitcode);
420 }
421
422 # endif
423
424 int
425 thrd_sleep (const struct timespec *duration, struct timespec *remaining)
426 {
427 int ret = nanosleep (duration, remaining);
428 return (ret == 0 ? 0 : errno == EINTR ? -1 : -2);
429 }
430
431 #endif