]> git.draconx.ca Git - cdecl99.git/blob - src/thread-posix.h
libcdecl: Punt gnulib tls module.
[cdecl99.git] / src / thread-posix.h
1 /*
2  * Copyright © 2024 Nick Bowler
3  *
4  * Helpers for hosts using POSIX threading (pthreads) API.
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
18  */
19
20 #include <pthread.h>
21
22 #if USE_POSIX_THREADS_WEAK
23 #  pragma weak pthread_key_create
24 #  pragma weak pthread_getspecific
25 #  pragma weak pthread_setspecific
26 #endif
27
28 static struct {
29         union {
30                 pthread_key_t mt;
31 #if USE_POSIX_THREADS_WEAK
32                 void *st;
33 #endif
34         } u;
35
36 #if USE_POSIX_THREADS_WEAK
37         signed char valid;
38 #else
39         bool valid;
40 #endif
41 } tls_key;
42 #define tls_key_valid (tls_key.valid != 0)
43
44 static void tls_key_init(void)
45 {
46         if (pthread_in_use())
47                 tls_key.valid = !pthread_key_create(&tls_key.u.mt, free);
48         else
49                 tls_key.valid = -1;
50 }
51
52 static void *tls_get(void)
53 {
54 #if USE_POSIX_THREADS_WEAK
55         if (tls_key.valid < 0)
56                 return tls_key.u.st;
57 #endif
58         return pthread_getspecific(tls_key.u.mt);
59 }
60
61 static int tls_set(void *p)
62 {
63 #if USE_POSIX_THREADS_WEAK
64         if (tls_key.valid < 0)
65                 return (tls_key.u.st = p, 1);
66 #endif
67         return !pthread_setspecific(tls_key.u.mt, p);
68 }