This source file includes following definitions.
- do_init_thrd_with_exitvalue_key
- init_thrd_with_exitvalue_key
- thrd_main_func
- glthread_create
- gl_thread_self
- glthread_join
- gl_thread_exit
- gl_thread_create
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
23 #include "glthread/thread.h"
24
25 #include <stdlib.h>
26 #include "glthread/lock.h"
27
28
29
30 #if USE_ISOC_THREADS
31
32 struct thrd_with_exitvalue
33 {
34 thrd_t volatile tid;
35 void * volatile exitvalue;
36 };
37
38
39
40 static tss_t thrd_with_exitvalue_key;
41
42
43
44 static void
45 do_init_thrd_with_exitvalue_key (void)
46 {
47 if (tss_create (&thrd_with_exitvalue_key, NULL) != thrd_success)
48 abort ();
49 }
50
51
52 static void
53 init_thrd_with_exitvalue_key (void)
54 {
55 static once_flag once = ONCE_FLAG_INIT;
56 call_once (&once, do_init_thrd_with_exitvalue_key);
57 }
58
59 typedef union
60 {
61 struct thrd_with_exitvalue t;
62 struct
63 {
64 thrd_t tid;
65 void *(*mainfunc) (void *);
66 void *arg;
67 } a;
68 }
69 main_arg_t;
70
71 static int
72 thrd_main_func (void *pmarg)
73 {
74
75 main_arg_t *main_arg = (main_arg_t *) pmarg;
76 void *(*mainfunc) (void *) = main_arg->a.mainfunc;
77 void *arg = main_arg->a.arg;
78
79 if (tss_set (thrd_with_exitvalue_key, &main_arg->t) != thrd_success)
80 abort ();
81
82
83 {
84 void *exitvalue = mainfunc (arg);
85
86 main_arg->t.exitvalue = exitvalue;
87 return 0;
88 }
89 }
90
91 int
92 glthread_create (gl_thread_t *threadp, void *(*mainfunc) (void *), void *arg)
93 {
94 init_thrd_with_exitvalue_key ();
95 {
96
97
98
99
100 main_arg_t *main_arg = (main_arg_t *) malloc (sizeof (main_arg_t));
101 if (main_arg == NULL)
102 return ENOMEM;
103 main_arg->a.mainfunc = mainfunc;
104 main_arg->a.arg = arg;
105 switch (thrd_create ((thrd_t *) &main_arg->t.tid, thrd_main_func, main_arg))
106 {
107 case thrd_success:
108 break;
109 case thrd_nomem:
110 free (main_arg);
111 return ENOMEM;
112 default:
113 free (main_arg);
114 return EAGAIN;
115 }
116 *threadp = &main_arg->t;
117 return 0;
118 }
119 }
120
121 gl_thread_t
122 gl_thread_self (void)
123 {
124 init_thrd_with_exitvalue_key ();
125 {
126 gl_thread_t thread =
127 (struct thrd_with_exitvalue *) tss_get (thrd_with_exitvalue_key);
128 if (thread == NULL)
129 {
130
131
132 for (;;)
133 {
134 thread =
135 (struct thrd_with_exitvalue *)
136 malloc (sizeof (struct thrd_with_exitvalue));
137 if (thread != NULL)
138 break;
139
140
141 {
142 struct timespec ts;
143 ts.tv_sec = 1;
144 ts.tv_nsec = 0;
145 thrd_sleep (&ts, NULL);
146 }
147 }
148 thread->tid = thrd_current ();
149 thread->exitvalue = NULL;
150 if (tss_set (thrd_with_exitvalue_key, thread) != thrd_success)
151 abort ();
152 }
153 return thread;
154 }
155 }
156
157 int
158 glthread_join (gl_thread_t thread, void **return_value_ptr)
159 {
160
161
162 int dummy;
163
164 if (thread == gl_thread_self ())
165 return EINVAL;
166 if (thrd_join (thread->tid, &dummy) != thrd_success)
167 return EINVAL;
168 if (return_value_ptr != NULL)
169 *return_value_ptr = thread->exitvalue;
170 free (thread);
171 return 0;
172 }
173
174 _Noreturn void
175 gl_thread_exit (void *return_value)
176 {
177 gl_thread_t thread = gl_thread_self ();
178 thread->exitvalue = return_value;
179 thrd_exit (0);
180 }
181
182 #endif
183
184
185
186 #if USE_POSIX_THREADS || USE_ISOC_AND_POSIX_THREADS
187
188 #include <pthread.h>
189
190 #if defined PTW32_VERSION || defined __MVS__
191
192 const gl_thread_t gl_null_thread ;
193
194 #endif
195
196 #endif
197
198
199
200 #if USE_WINDOWS_THREADS
201
202 #endif
203
204
205
206 gl_thread_t
207 gl_thread_create (void *(*func) (void *arg), void *arg)
208 {
209 gl_thread_t thread;
210 int ret;
211
212 ret = glthread_create (&thread, func, arg);
213 if (ret != 0)
214 abort ();
215 return thread;
216 }