line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
/* Threads compatibility routines for libgcc2 and libobjc. */ |
2
|
|
|
|
|
|
|
/* Compile this one with gcc. */ |
3
|
|
|
|
|
|
|
/* Copyright (C) 1997-2015 Free Software Foundation, Inc. |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
This file is part of GCC. |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
GCC is free software; you can redistribute it and/or modify it under |
8
|
|
|
|
|
|
|
the terms of the GNU General Public License as published by the Free |
9
|
|
|
|
|
|
|
Software Foundation; either version 3, or (at your option) any later |
10
|
|
|
|
|
|
|
version. |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
13
|
|
|
|
|
|
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or |
14
|
|
|
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
15
|
|
|
|
|
|
|
for more details. |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
Under Section 7 of GPL version 3, you are granted additional |
18
|
|
|
|
|
|
|
permissions described in the GCC Runtime Library Exception, version |
19
|
|
|
|
|
|
|
3.1, as published by the Free Software Foundation. |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License and |
22
|
|
|
|
|
|
|
a copy of the GCC Runtime Library Exception along with this program; |
23
|
|
|
|
|
|
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
24
|
|
|
|
|
|
|
. */ |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
#ifndef _GLIBCXX_GCC_GTHR_POSIX_H |
27
|
|
|
|
|
|
|
#define _GLIBCXX_GCC_GTHR_POSIX_H |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
/* POSIX threads specific definitions. |
30
|
|
|
|
|
|
|
Easy, since the interface is just one-to-one mapping. */ |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
#define __GTHREADS 1 |
33
|
|
|
|
|
|
|
#define __GTHREADS_CXX0X 1 |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
#include |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
#if ((defined(_LIBOBJC) || defined(_LIBOBJC_WEAK)) \ |
38
|
|
|
|
|
|
|
|| !defined(_GTHREAD_USE_MUTEX_TIMEDLOCK)) |
39
|
|
|
|
|
|
|
# include |
40
|
|
|
|
|
|
|
# if defined(_POSIX_TIMEOUTS) && _POSIX_TIMEOUTS >= 0 |
41
|
|
|
|
|
|
|
# define _GTHREAD_USE_MUTEX_TIMEDLOCK 1 |
42
|
|
|
|
|
|
|
# else |
43
|
|
|
|
|
|
|
# define _GTHREAD_USE_MUTEX_TIMEDLOCK 0 |
44
|
|
|
|
|
|
|
# endif |
45
|
|
|
|
|
|
|
#endif |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
typedef pthread_t __gthread_t; |
48
|
|
|
|
|
|
|
typedef pthread_key_t __gthread_key_t; |
49
|
|
|
|
|
|
|
typedef pthread_once_t __gthread_once_t; |
50
|
|
|
|
|
|
|
typedef pthread_mutex_t __gthread_mutex_t; |
51
|
|
|
|
|
|
|
typedef pthread_mutex_t __gthread_recursive_mutex_t; |
52
|
|
|
|
|
|
|
typedef pthread_cond_t __gthread_cond_t; |
53
|
|
|
|
|
|
|
typedef struct timespec __gthread_time_t; |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
/* POSIX like conditional variables are supported. Please look at comments |
56
|
|
|
|
|
|
|
in gthr.h for details. */ |
57
|
|
|
|
|
|
|
#define __GTHREAD_HAS_COND 1 |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
#define __GTHREAD_MUTEX_INIT PTHREAD_MUTEX_INITIALIZER |
60
|
|
|
|
|
|
|
#define __GTHREAD_MUTEX_INIT_FUNCTION __gthread_mutex_init_function |
61
|
|
|
|
|
|
|
#define __GTHREAD_ONCE_INIT PTHREAD_ONCE_INIT |
62
|
|
|
|
|
|
|
#if defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER) |
63
|
|
|
|
|
|
|
#define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER |
64
|
|
|
|
|
|
|
#elif defined(PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) |
65
|
|
|
|
|
|
|
#define __GTHREAD_RECURSIVE_MUTEX_INIT PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP |
66
|
|
|
|
|
|
|
#else |
67
|
|
|
|
|
|
|
#define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function |
68
|
|
|
|
|
|
|
#endif |
69
|
|
|
|
|
|
|
#define __GTHREAD_COND_INIT PTHREAD_COND_INITIALIZER |
70
|
|
|
|
|
|
|
#define __GTHREAD_TIME_INIT {0,0} |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
#ifdef _GTHREAD_USE_MUTEX_INIT_FUNC |
73
|
|
|
|
|
|
|
# undef __GTHREAD_MUTEX_INIT |
74
|
|
|
|
|
|
|
#endif |
75
|
|
|
|
|
|
|
#ifdef _GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC |
76
|
|
|
|
|
|
|
# undef __GTHREAD_RECURSIVE_MUTEX_INIT |
77
|
|
|
|
|
|
|
# undef __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION |
78
|
|
|
|
|
|
|
# define __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION __gthread_recursive_mutex_init_function |
79
|
|
|
|
|
|
|
#endif |
80
|
|
|
|
|
|
|
#ifdef _GTHREAD_USE_COND_INIT_FUNC |
81
|
|
|
|
|
|
|
# undef __GTHREAD_COND_INIT |
82
|
|
|
|
|
|
|
# define __GTHREAD_COND_INIT_FUNCTION __gthread_cond_init_function |
83
|
|
|
|
|
|
|
#endif |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
#if __GXX_WEAK__ && _GLIBCXX_GTHREAD_USE_WEAK |
86
|
|
|
|
|
|
|
# ifndef __gthrw_pragma |
87
|
|
|
|
|
|
|
# define __gthrw_pragma(pragma) |
88
|
|
|
|
|
|
|
# endif |
89
|
|
|
|
|
|
|
# define __gthrw2(name,name2,type) \ |
90
|
|
|
|
|
|
|
static __typeof(type) name __attribute__ ((__weakref__(#name2))); \ |
91
|
|
|
|
|
|
|
__gthrw_pragma(weak type) |
92
|
|
|
|
|
|
|
# define __gthrw_(name) __gthrw_ ## name |
93
|
|
|
|
|
|
|
#else |
94
|
|
|
|
|
|
|
# define __gthrw2(name,name2,type) |
95
|
|
|
|
|
|
|
# define __gthrw_(name) name |
96
|
|
|
|
|
|
|
#endif |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
/* Typically, __gthrw_foo is a weak reference to symbol foo. */ |
99
|
|
|
|
|
|
|
#define __gthrw(name) __gthrw2(__gthrw_ ## name,name,name) |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
__gthrw(pthread_once) |
102
|
|
|
|
|
|
|
__gthrw(pthread_getspecific) |
103
|
|
|
|
|
|
|
__gthrw(pthread_setspecific) |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
__gthrw(pthread_create) |
106
|
|
|
|
|
|
|
__gthrw(pthread_join) |
107
|
|
|
|
|
|
|
__gthrw(pthread_equal) |
108
|
|
|
|
|
|
|
__gthrw(pthread_self) |
109
|
|
|
|
|
|
|
__gthrw(pthread_detach) |
110
|
|
|
|
|
|
|
#ifndef __BIONIC__ |
111
|
|
|
|
|
|
|
__gthrw(pthread_cancel) |
112
|
|
|
|
|
|
|
#endif |
113
|
|
|
|
|
|
|
__gthrw(sched_yield) |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
__gthrw(pthread_mutex_lock) |
116
|
|
|
|
|
|
|
__gthrw(pthread_mutex_trylock) |
117
|
|
|
|
|
|
|
#if _GTHREAD_USE_MUTEX_TIMEDLOCK |
118
|
|
|
|
|
|
|
__gthrw(pthread_mutex_timedlock) |
119
|
|
|
|
|
|
|
#endif |
120
|
|
|
|
|
|
|
__gthrw(pthread_mutex_unlock) |
121
|
|
|
|
|
|
|
__gthrw(pthread_mutex_init) |
122
|
|
|
|
|
|
|
__gthrw(pthread_mutex_destroy) |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
__gthrw(pthread_cond_init) |
125
|
|
|
|
|
|
|
__gthrw(pthread_cond_broadcast) |
126
|
|
|
|
|
|
|
__gthrw(pthread_cond_signal) |
127
|
|
|
|
|
|
|
__gthrw(pthread_cond_wait) |
128
|
|
|
|
|
|
|
__gthrw(pthread_cond_timedwait) |
129
|
|
|
|
|
|
|
__gthrw(pthread_cond_destroy) |
130
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
__gthrw(pthread_key_create) |
132
|
|
|
|
|
|
|
__gthrw(pthread_key_delete) |
133
|
|
|
|
|
|
|
__gthrw(pthread_mutexattr_init) |
134
|
|
|
|
|
|
|
__gthrw(pthread_mutexattr_settype) |
135
|
|
|
|
|
|
|
__gthrw(pthread_mutexattr_destroy) |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
#if defined(_LIBOBJC) || defined(_LIBOBJC_WEAK) |
139
|
|
|
|
|
|
|
/* Objective-C. */ |
140
|
|
|
|
|
|
|
__gthrw(pthread_exit) |
141
|
|
|
|
|
|
|
#ifdef _POSIX_PRIORITY_SCHEDULING |
142
|
|
|
|
|
|
|
#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING |
143
|
|
|
|
|
|
|
__gthrw(sched_get_priority_max) |
144
|
|
|
|
|
|
|
__gthrw(sched_get_priority_min) |
145
|
|
|
|
|
|
|
#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ |
146
|
|
|
|
|
|
|
#endif /* _POSIX_PRIORITY_SCHEDULING */ |
147
|
|
|
|
|
|
|
__gthrw(pthread_attr_destroy) |
148
|
|
|
|
|
|
|
__gthrw(pthread_attr_init) |
149
|
|
|
|
|
|
|
__gthrw(pthread_attr_setdetachstate) |
150
|
|
|
|
|
|
|
#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING |
151
|
|
|
|
|
|
|
__gthrw(pthread_getschedparam) |
152
|
|
|
|
|
|
|
__gthrw(pthread_setschedparam) |
153
|
|
|
|
|
|
|
#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ |
154
|
|
|
|
|
|
|
#endif /* _LIBOBJC || _LIBOBJC_WEAK */ |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
#if __GXX_WEAK__ && _GLIBCXX_GTHREAD_USE_WEAK |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
/* On Solaris 2.6 up to 9, the libc exposes a POSIX threads interface even if |
159
|
|
|
|
|
|
|
-pthreads is not specified. The functions are dummies and most return an |
160
|
|
|
|
|
|
|
error value. However pthread_once returns 0 without invoking the routine |
161
|
|
|
|
|
|
|
it is passed so we cannot pretend that the interface is active if -pthreads |
162
|
|
|
|
|
|
|
is not specified. On Solaris 2.5.1, the interface is not exposed at all so |
163
|
|
|
|
|
|
|
we need to play the usual game with weak symbols. On Solaris 10 and up, a |
164
|
|
|
|
|
|
|
working interface is always exposed. On FreeBSD 6 and later, libc also |
165
|
|
|
|
|
|
|
exposes a dummy POSIX threads interface, similar to what Solaris 2.6 up |
166
|
|
|
|
|
|
|
to 9 does. FreeBSD >= 700014 even provides a pthread_cancel stub in libc, |
167
|
|
|
|
|
|
|
which means the alternate __gthread_active_p below cannot be used there. */ |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
#if defined(__FreeBSD__) || (defined(__sun) && defined(__svr4__)) |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
static volatile int __gthread_active = -1; |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
static void |
174
|
|
|
|
|
|
|
__gthread_trigger (void) |
175
|
|
|
|
|
|
|
{ |
176
|
|
|
|
|
|
|
__gthread_active = 1; |
177
|
|
|
|
|
|
|
} |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
static inline int |
180
|
|
|
|
|
|
|
__gthread_active_p (void) |
181
|
|
|
|
|
|
|
{ |
182
|
|
|
|
|
|
|
static pthread_mutex_t __gthread_active_mutex = PTHREAD_MUTEX_INITIALIZER; |
183
|
|
|
|
|
|
|
static pthread_once_t __gthread_active_once = PTHREAD_ONCE_INIT; |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
/* Avoid reading __gthread_active twice on the main code path. */ |
186
|
|
|
|
|
|
|
int __gthread_active_latest_value = __gthread_active; |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
/* This test is not protected to avoid taking a lock on the main code |
189
|
|
|
|
|
|
|
path so every update of __gthread_active in a threaded program must |
190
|
|
|
|
|
|
|
be atomic with regard to the result of the test. */ |
191
|
|
|
|
|
|
|
if (__builtin_expect (__gthread_active_latest_value < 0, 0)) |
192
|
|
|
|
|
|
|
{ |
193
|
|
|
|
|
|
|
if (__gthrw_(pthread_once)) |
194
|
|
|
|
|
|
|
{ |
195
|
|
|
|
|
|
|
/* If this really is a threaded program, then we must ensure that |
196
|
|
|
|
|
|
|
__gthread_active has been set to 1 before exiting this block. */ |
197
|
|
|
|
|
|
|
__gthrw_(pthread_mutex_lock) (&__gthread_active_mutex); |
198
|
|
|
|
|
|
|
__gthrw_(pthread_once) (&__gthread_active_once, __gthread_trigger); |
199
|
|
|
|
|
|
|
__gthrw_(pthread_mutex_unlock) (&__gthread_active_mutex); |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
/* Make sure we'll never enter this block again. */ |
203
|
|
|
|
|
|
|
if (__gthread_active < 0) |
204
|
|
|
|
|
|
|
__gthread_active = 0; |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
__gthread_active_latest_value = __gthread_active; |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
return __gthread_active_latest_value != 0; |
210
|
|
|
|
|
|
|
} |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
#else /* neither FreeBSD nor Solaris */ |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
/* For a program to be multi-threaded the only thing that it certainly must |
215
|
|
|
|
|
|
|
be using is pthread_create. However, there may be other libraries that |
216
|
|
|
|
|
|
|
intercept pthread_create with their own definitions to wrap pthreads |
217
|
|
|
|
|
|
|
functionality for some purpose. In those cases, pthread_create being |
218
|
|
|
|
|
|
|
defined might not necessarily mean that libpthread is actually linked |
219
|
|
|
|
|
|
|
in. |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
For the GNU C library, we can use a known internal name. This is always |
222
|
|
|
|
|
|
|
available in the ABI, but no other library would define it. That is |
223
|
|
|
|
|
|
|
ideal, since any public pthread function might be intercepted just as |
224
|
|
|
|
|
|
|
pthread_create might be. __pthread_key_create is an "internal" |
225
|
|
|
|
|
|
|
implementation symbol, but it is part of the public exported ABI. Also, |
226
|
|
|
|
|
|
|
it's among the symbols that the static libpthread.a always links in |
227
|
|
|
|
|
|
|
whenever pthread_create is used, so there is no danger of a false |
228
|
|
|
|
|
|
|
negative result in any statically-linked, multi-threaded program. |
229
|
|
|
|
|
|
|
|
230
|
|
|
|
|
|
|
For others, we choose pthread_cancel as a function that seems unlikely |
231
|
|
|
|
|
|
|
to be redefined by an interceptor library. The bionic (Android) C |
232
|
|
|
|
|
|
|
library does not provide pthread_cancel, so we do use pthread_create |
233
|
|
|
|
|
|
|
there (and interceptor libraries lose). */ |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
#ifdef __GLIBC__ |
236
|
|
|
|
|
|
|
__gthrw2(__gthrw_(__pthread_key_create), |
237
|
|
|
|
|
|
|
__pthread_key_create, |
238
|
|
|
|
|
|
|
pthread_key_create) |
239
|
|
|
|
|
|
|
# define GTHR_ACTIVE_PROXY __gthrw_(__pthread_key_create) |
240
|
|
|
|
|
|
|
#elif defined (__BIONIC__) |
241
|
|
|
|
|
|
|
# define GTHR_ACTIVE_PROXY __gthrw_(pthread_create) |
242
|
|
|
|
|
|
|
#else |
243
|
|
|
|
|
|
|
# define GTHR_ACTIVE_PROXY __gthrw_(pthread_cancel) |
244
|
|
|
|
|
|
|
#endif |
245
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
static inline int |
247
|
0
|
|
|
|
|
|
__gthread_active_p (void) |
248
|
|
|
|
|
|
|
{ |
249
|
|
|
|
|
|
|
static void *const __gthread_active_ptr |
250
|
|
|
|
|
|
|
= __extension__ (void *) >HR_ACTIVE_PROXY; |
251
|
0
|
|
|
|
|
|
return __gthread_active_ptr != 0; |
252
|
|
|
|
|
|
|
} |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
#endif /* FreeBSD or Solaris */ |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
#else /* not __GXX_WEAK__ */ |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
/* Similar to Solaris, HP-UX 11 for PA-RISC provides stubs for pthread |
259
|
|
|
|
|
|
|
calls in shared flavors of the HP-UX C library. Most of the stubs |
260
|
|
|
|
|
|
|
have no functionality. The details are described in the "libc cumulative |
261
|
|
|
|
|
|
|
patch" for each subversion of HP-UX 11. There are two special interfaces |
262
|
|
|
|
|
|
|
provided for checking whether an application is linked to a shared pthread |
263
|
|
|
|
|
|
|
library or not. However, these interfaces aren't available in early |
264
|
|
|
|
|
|
|
libpthread libraries. We also need a test that works for archive |
265
|
|
|
|
|
|
|
libraries. We can't use pthread_once as some libc versions call the |
266
|
|
|
|
|
|
|
init function. We also can't use pthread_create or pthread_attr_init |
267
|
|
|
|
|
|
|
as these create a thread and thereby prevent changing the default stack |
268
|
|
|
|
|
|
|
size. The function pthread_default_stacksize_np is available in both |
269
|
|
|
|
|
|
|
the archive and shared versions of libpthread. It can be used to |
270
|
|
|
|
|
|
|
determine the default pthread stack size. There is a stub in some |
271
|
|
|
|
|
|
|
shared libc versions which returns a zero size if pthreads are not |
272
|
|
|
|
|
|
|
active. We provide an equivalent stub to handle cases where libc |
273
|
|
|
|
|
|
|
doesn't provide one. */ |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
#if defined(__hppa__) && defined(__hpux__) |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
static volatile int __gthread_active = -1; |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
static inline int |
280
|
|
|
|
|
|
|
__gthread_active_p (void) |
281
|
|
|
|
|
|
|
{ |
282
|
|
|
|
|
|
|
/* Avoid reading __gthread_active twice on the main code path. */ |
283
|
|
|
|
|
|
|
int __gthread_active_latest_value = __gthread_active; |
284
|
|
|
|
|
|
|
size_t __s; |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
if (__builtin_expect (__gthread_active_latest_value < 0, 0)) |
287
|
|
|
|
|
|
|
{ |
288
|
|
|
|
|
|
|
pthread_default_stacksize_np (0, &__s); |
289
|
|
|
|
|
|
|
__gthread_active = __s ? 1 : 0; |
290
|
|
|
|
|
|
|
__gthread_active_latest_value = __gthread_active; |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
return __gthread_active_latest_value != 0; |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
#else /* not hppa-hpux */ |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
static inline int |
299
|
|
|
|
|
|
|
__gthread_active_p (void) |
300
|
|
|
|
|
|
|
{ |
301
|
|
|
|
|
|
|
return 1; |
302
|
|
|
|
|
|
|
} |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
#endif /* hppa-hpux */ |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
#endif /* __GXX_WEAK__ */ |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
#ifdef _LIBOBJC |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
/* This is the config.h file in libobjc/ */ |
311
|
|
|
|
|
|
|
#include |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
#ifdef HAVE_SCHED_H |
314
|
|
|
|
|
|
|
# include |
315
|
|
|
|
|
|
|
#endif |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
/* Key structure for maintaining thread specific storage */ |
318
|
|
|
|
|
|
|
static pthread_key_t _objc_thread_storage; |
319
|
|
|
|
|
|
|
static pthread_attr_t _objc_thread_attribs; |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
/* Thread local storage for a single thread */ |
322
|
|
|
|
|
|
|
static void *thread_local_storage = NULL; |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
/* Backend initialization functions */ |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
/* Initialize the threads subsystem. */ |
327
|
|
|
|
|
|
|
static inline int |
328
|
|
|
|
|
|
|
__gthread_objc_init_thread_system (void) |
329
|
|
|
|
|
|
|
{ |
330
|
|
|
|
|
|
|
if (__gthread_active_p ()) |
331
|
|
|
|
|
|
|
{ |
332
|
|
|
|
|
|
|
/* Initialize the thread storage key. */ |
333
|
|
|
|
|
|
|
if (__gthrw_(pthread_key_create) (&_objc_thread_storage, NULL) == 0) |
334
|
|
|
|
|
|
|
{ |
335
|
|
|
|
|
|
|
/* The normal default detach state for threads is |
336
|
|
|
|
|
|
|
* PTHREAD_CREATE_JOINABLE which causes threads to not die |
337
|
|
|
|
|
|
|
* when you think they should. */ |
338
|
|
|
|
|
|
|
if (__gthrw_(pthread_attr_init) (&_objc_thread_attribs) == 0 |
339
|
|
|
|
|
|
|
&& __gthrw_(pthread_attr_setdetachstate) (&_objc_thread_attribs, |
340
|
|
|
|
|
|
|
PTHREAD_CREATE_DETACHED) == 0) |
341
|
|
|
|
|
|
|
return 0; |
342
|
|
|
|
|
|
|
} |
343
|
|
|
|
|
|
|
} |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
return -1; |
346
|
|
|
|
|
|
|
} |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
/* Close the threads subsystem. */ |
349
|
|
|
|
|
|
|
static inline int |
350
|
|
|
|
|
|
|
__gthread_objc_close_thread_system (void) |
351
|
|
|
|
|
|
|
{ |
352
|
|
|
|
|
|
|
if (__gthread_active_p () |
353
|
|
|
|
|
|
|
&& __gthrw_(pthread_key_delete) (_objc_thread_storage) == 0 |
354
|
|
|
|
|
|
|
&& __gthrw_(pthread_attr_destroy) (&_objc_thread_attribs) == 0) |
355
|
|
|
|
|
|
|
return 0; |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
return -1; |
358
|
|
|
|
|
|
|
} |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
/* Backend thread functions */ |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
/* Create a new thread of execution. */ |
363
|
|
|
|
|
|
|
static inline objc_thread_t |
364
|
|
|
|
|
|
|
__gthread_objc_thread_detach (void (*func)(void *), void *arg) |
365
|
|
|
|
|
|
|
{ |
366
|
|
|
|
|
|
|
objc_thread_t thread_id; |
367
|
|
|
|
|
|
|
pthread_t new_thread_handle; |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
if (!__gthread_active_p ()) |
370
|
|
|
|
|
|
|
return NULL; |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
if (!(__gthrw_(pthread_create) (&new_thread_handle, &_objc_thread_attribs, |
373
|
|
|
|
|
|
|
(void *) func, arg))) |
374
|
|
|
|
|
|
|
thread_id = (objc_thread_t) new_thread_handle; |
375
|
|
|
|
|
|
|
else |
376
|
|
|
|
|
|
|
thread_id = NULL; |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
return thread_id; |
379
|
|
|
|
|
|
|
} |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
/* Set the current thread's priority. */ |
382
|
|
|
|
|
|
|
static inline int |
383
|
|
|
|
|
|
|
__gthread_objc_thread_set_priority (int priority) |
384
|
|
|
|
|
|
|
{ |
385
|
|
|
|
|
|
|
if (!__gthread_active_p ()) |
386
|
|
|
|
|
|
|
return -1; |
387
|
|
|
|
|
|
|
else |
388
|
|
|
|
|
|
|
{ |
389
|
|
|
|
|
|
|
#ifdef _POSIX_PRIORITY_SCHEDULING |
390
|
|
|
|
|
|
|
#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING |
391
|
|
|
|
|
|
|
pthread_t thread_id = __gthrw_(pthread_self) (); |
392
|
|
|
|
|
|
|
int policy; |
393
|
|
|
|
|
|
|
struct sched_param params; |
394
|
|
|
|
|
|
|
int priority_min, priority_max; |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
if (__gthrw_(pthread_getschedparam) (thread_id, &policy, ¶ms) == 0) |
397
|
|
|
|
|
|
|
{ |
398
|
|
|
|
|
|
|
if ((priority_max = __gthrw_(sched_get_priority_max) (policy)) == -1) |
399
|
|
|
|
|
|
|
return -1; |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
if ((priority_min = __gthrw_(sched_get_priority_min) (policy)) == -1) |
402
|
|
|
|
|
|
|
return -1; |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
if (priority > priority_max) |
405
|
|
|
|
|
|
|
priority = priority_max; |
406
|
|
|
|
|
|
|
else if (priority < priority_min) |
407
|
|
|
|
|
|
|
priority = priority_min; |
408
|
|
|
|
|
|
|
params.sched_priority = priority; |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
/* |
411
|
|
|
|
|
|
|
* The solaris 7 and several other man pages incorrectly state that |
412
|
|
|
|
|
|
|
* this should be a pointer to policy but pthread.h is universally |
413
|
|
|
|
|
|
|
* at odds with this. |
414
|
|
|
|
|
|
|
*/ |
415
|
|
|
|
|
|
|
if (__gthrw_(pthread_setschedparam) (thread_id, policy, ¶ms) == 0) |
416
|
|
|
|
|
|
|
return 0; |
417
|
|
|
|
|
|
|
} |
418
|
|
|
|
|
|
|
#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ |
419
|
|
|
|
|
|
|
#endif /* _POSIX_PRIORITY_SCHEDULING */ |
420
|
|
|
|
|
|
|
return -1; |
421
|
|
|
|
|
|
|
} |
422
|
|
|
|
|
|
|
} |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
/* Return the current thread's priority. */ |
425
|
|
|
|
|
|
|
static inline int |
426
|
|
|
|
|
|
|
__gthread_objc_thread_get_priority (void) |
427
|
|
|
|
|
|
|
{ |
428
|
|
|
|
|
|
|
#ifdef _POSIX_PRIORITY_SCHEDULING |
429
|
|
|
|
|
|
|
#ifdef _POSIX_THREAD_PRIORITY_SCHEDULING |
430
|
|
|
|
|
|
|
if (__gthread_active_p ()) |
431
|
|
|
|
|
|
|
{ |
432
|
|
|
|
|
|
|
int policy; |
433
|
|
|
|
|
|
|
struct sched_param params; |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
if (__gthrw_(pthread_getschedparam) (__gthrw_(pthread_self) (), &policy, ¶ms) == 0) |
436
|
|
|
|
|
|
|
return params.sched_priority; |
437
|
|
|
|
|
|
|
else |
438
|
|
|
|
|
|
|
return -1; |
439
|
|
|
|
|
|
|
} |
440
|
|
|
|
|
|
|
else |
441
|
|
|
|
|
|
|
#endif /* _POSIX_THREAD_PRIORITY_SCHEDULING */ |
442
|
|
|
|
|
|
|
#endif /* _POSIX_PRIORITY_SCHEDULING */ |
443
|
|
|
|
|
|
|
return OBJC_THREAD_INTERACTIVE_PRIORITY; |
444
|
|
|
|
|
|
|
} |
445
|
|
|
|
|
|
|
|
446
|
|
|
|
|
|
|
/* Yield our process time to another thread. */ |
447
|
|
|
|
|
|
|
static inline void |
448
|
|
|
|
|
|
|
__gthread_objc_thread_yield (void) |
449
|
|
|
|
|
|
|
{ |
450
|
|
|
|
|
|
|
if (__gthread_active_p ()) |
451
|
|
|
|
|
|
|
__gthrw_(sched_yield) (); |
452
|
|
|
|
|
|
|
} |
453
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
/* Terminate the current thread. */ |
455
|
|
|
|
|
|
|
static inline int |
456
|
|
|
|
|
|
|
__gthread_objc_thread_exit (void) |
457
|
|
|
|
|
|
|
{ |
458
|
|
|
|
|
|
|
if (__gthread_active_p ()) |
459
|
|
|
|
|
|
|
/* exit the thread */ |
460
|
|
|
|
|
|
|
__gthrw_(pthread_exit) (&__objc_thread_exit_status); |
461
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
/* Failed if we reached here */ |
463
|
|
|
|
|
|
|
return -1; |
464
|
|
|
|
|
|
|
} |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
/* Returns an integer value which uniquely describes a thread. */ |
467
|
|
|
|
|
|
|
static inline objc_thread_t |
468
|
|
|
|
|
|
|
__gthread_objc_thread_id (void) |
469
|
|
|
|
|
|
|
{ |
470
|
|
|
|
|
|
|
if (__gthread_active_p ()) |
471
|
|
|
|
|
|
|
return (objc_thread_t) __gthrw_(pthread_self) (); |
472
|
|
|
|
|
|
|
else |
473
|
|
|
|
|
|
|
return (objc_thread_t) 1; |
474
|
|
|
|
|
|
|
} |
475
|
|
|
|
|
|
|
|
476
|
|
|
|
|
|
|
/* Sets the thread's local storage pointer. */ |
477
|
|
|
|
|
|
|
static inline int |
478
|
|
|
|
|
|
|
__gthread_objc_thread_set_data (void *value) |
479
|
|
|
|
|
|
|
{ |
480
|
|
|
|
|
|
|
if (__gthread_active_p ()) |
481
|
|
|
|
|
|
|
return __gthrw_(pthread_setspecific) (_objc_thread_storage, value); |
482
|
|
|
|
|
|
|
else |
483
|
|
|
|
|
|
|
{ |
484
|
|
|
|
|
|
|
thread_local_storage = value; |
485
|
|
|
|
|
|
|
return 0; |
486
|
|
|
|
|
|
|
} |
487
|
|
|
|
|
|
|
} |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
/* Returns the thread's local storage pointer. */ |
490
|
|
|
|
|
|
|
static inline void * |
491
|
|
|
|
|
|
|
__gthread_objc_thread_get_data (void) |
492
|
|
|
|
|
|
|
{ |
493
|
|
|
|
|
|
|
if (__gthread_active_p ()) |
494
|
|
|
|
|
|
|
return __gthrw_(pthread_getspecific) (_objc_thread_storage); |
495
|
|
|
|
|
|
|
else |
496
|
|
|
|
|
|
|
return thread_local_storage; |
497
|
|
|
|
|
|
|
} |
498
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
/* Backend mutex functions */ |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
/* Allocate a mutex. */ |
502
|
|
|
|
|
|
|
static inline int |
503
|
|
|
|
|
|
|
__gthread_objc_mutex_allocate (objc_mutex_t mutex) |
504
|
|
|
|
|
|
|
{ |
505
|
|
|
|
|
|
|
if (__gthread_active_p ()) |
506
|
|
|
|
|
|
|
{ |
507
|
|
|
|
|
|
|
mutex->backend = objc_malloc (sizeof (pthread_mutex_t)); |
508
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
if (__gthrw_(pthread_mutex_init) ((pthread_mutex_t *) mutex->backend, NULL)) |
510
|
|
|
|
|
|
|
{ |
511
|
|
|
|
|
|
|
objc_free (mutex->backend); |
512
|
|
|
|
|
|
|
mutex->backend = NULL; |
513
|
|
|
|
|
|
|
return -1; |
514
|
|
|
|
|
|
|
} |
515
|
|
|
|
|
|
|
} |
516
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
return 0; |
518
|
|
|
|
|
|
|
} |
519
|
|
|
|
|
|
|
|
520
|
|
|
|
|
|
|
/* Deallocate a mutex. */ |
521
|
|
|
|
|
|
|
static inline int |
522
|
|
|
|
|
|
|
__gthread_objc_mutex_deallocate (objc_mutex_t mutex) |
523
|
|
|
|
|
|
|
{ |
524
|
|
|
|
|
|
|
if (__gthread_active_p ()) |
525
|
|
|
|
|
|
|
{ |
526
|
|
|
|
|
|
|
int count; |
527
|
|
|
|
|
|
|
|
528
|
|
|
|
|
|
|
/* |
529
|
|
|
|
|
|
|
* Posix Threads specifically require that the thread be unlocked |
530
|
|
|
|
|
|
|
* for __gthrw_(pthread_mutex_destroy) to work. |
531
|
|
|
|
|
|
|
*/ |
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
do |
534
|
|
|
|
|
|
|
{ |
535
|
|
|
|
|
|
|
count = __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend); |
536
|
|
|
|
|
|
|
if (count < 0) |
537
|
|
|
|
|
|
|
return -1; |
538
|
|
|
|
|
|
|
} |
539
|
|
|
|
|
|
|
while (count); |
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
if (__gthrw_(pthread_mutex_destroy) ((pthread_mutex_t *) mutex->backend)) |
542
|
|
|
|
|
|
|
return -1; |
543
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
objc_free (mutex->backend); |
545
|
|
|
|
|
|
|
mutex->backend = NULL; |
546
|
|
|
|
|
|
|
} |
547
|
|
|
|
|
|
|
return 0; |
548
|
|
|
|
|
|
|
} |
549
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
/* Grab a lock on a mutex. */ |
551
|
|
|
|
|
|
|
static inline int |
552
|
|
|
|
|
|
|
__gthread_objc_mutex_lock (objc_mutex_t mutex) |
553
|
|
|
|
|
|
|
{ |
554
|
|
|
|
|
|
|
if (__gthread_active_p () |
555
|
|
|
|
|
|
|
&& __gthrw_(pthread_mutex_lock) ((pthread_mutex_t *) mutex->backend) != 0) |
556
|
|
|
|
|
|
|
{ |
557
|
|
|
|
|
|
|
return -1; |
558
|
|
|
|
|
|
|
} |
559
|
|
|
|
|
|
|
|
560
|
|
|
|
|
|
|
return 0; |
561
|
|
|
|
|
|
|
} |
562
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
/* Try to grab a lock on a mutex. */ |
564
|
|
|
|
|
|
|
static inline int |
565
|
|
|
|
|
|
|
__gthread_objc_mutex_trylock (objc_mutex_t mutex) |
566
|
|
|
|
|
|
|
{ |
567
|
|
|
|
|
|
|
if (__gthread_active_p () |
568
|
|
|
|
|
|
|
&& __gthrw_(pthread_mutex_trylock) ((pthread_mutex_t *) mutex->backend) != 0) |
569
|
|
|
|
|
|
|
{ |
570
|
|
|
|
|
|
|
return -1; |
571
|
|
|
|
|
|
|
} |
572
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
return 0; |
574
|
|
|
|
|
|
|
} |
575
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
/* Unlock the mutex */ |
577
|
|
|
|
|
|
|
static inline int |
578
|
|
|
|
|
|
|
__gthread_objc_mutex_unlock (objc_mutex_t mutex) |
579
|
|
|
|
|
|
|
{ |
580
|
|
|
|
|
|
|
if (__gthread_active_p () |
581
|
|
|
|
|
|
|
&& __gthrw_(pthread_mutex_unlock) ((pthread_mutex_t *) mutex->backend) != 0) |
582
|
|
|
|
|
|
|
{ |
583
|
|
|
|
|
|
|
return -1; |
584
|
|
|
|
|
|
|
} |
585
|
|
|
|
|
|
|
|
586
|
|
|
|
|
|
|
return 0; |
587
|
|
|
|
|
|
|
} |
588
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
/* Backend condition mutex functions */ |
590
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
/* Allocate a condition. */ |
592
|
|
|
|
|
|
|
static inline int |
593
|
|
|
|
|
|
|
__gthread_objc_condition_allocate (objc_condition_t condition) |
594
|
|
|
|
|
|
|
{ |
595
|
|
|
|
|
|
|
if (__gthread_active_p ()) |
596
|
|
|
|
|
|
|
{ |
597
|
|
|
|
|
|
|
condition->backend = objc_malloc (sizeof (pthread_cond_t)); |
598
|
|
|
|
|
|
|
|
599
|
|
|
|
|
|
|
if (__gthrw_(pthread_cond_init) ((pthread_cond_t *) condition->backend, NULL)) |
600
|
|
|
|
|
|
|
{ |
601
|
|
|
|
|
|
|
objc_free (condition->backend); |
602
|
|
|
|
|
|
|
condition->backend = NULL; |
603
|
|
|
|
|
|
|
return -1; |
604
|
|
|
|
|
|
|
} |
605
|
|
|
|
|
|
|
} |
606
|
|
|
|
|
|
|
|
607
|
|
|
|
|
|
|
return 0; |
608
|
|
|
|
|
|
|
} |
609
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
/* Deallocate a condition. */ |
611
|
|
|
|
|
|
|
static inline int |
612
|
|
|
|
|
|
|
__gthread_objc_condition_deallocate (objc_condition_t condition) |
613
|
|
|
|
|
|
|
{ |
614
|
|
|
|
|
|
|
if (__gthread_active_p ()) |
615
|
|
|
|
|
|
|
{ |
616
|
|
|
|
|
|
|
if (__gthrw_(pthread_cond_destroy) ((pthread_cond_t *) condition->backend)) |
617
|
|
|
|
|
|
|
return -1; |
618
|
|
|
|
|
|
|
|
619
|
|
|
|
|
|
|
objc_free (condition->backend); |
620
|
|
|
|
|
|
|
condition->backend = NULL; |
621
|
|
|
|
|
|
|
} |
622
|
|
|
|
|
|
|
return 0; |
623
|
|
|
|
|
|
|
} |
624
|
|
|
|
|
|
|
|
625
|
|
|
|
|
|
|
/* Wait on the condition */ |
626
|
|
|
|
|
|
|
static inline int |
627
|
|
|
|
|
|
|
__gthread_objc_condition_wait (objc_condition_t condition, objc_mutex_t mutex) |
628
|
|
|
|
|
|
|
{ |
629
|
|
|
|
|
|
|
if (__gthread_active_p ()) |
630
|
|
|
|
|
|
|
return __gthrw_(pthread_cond_wait) ((pthread_cond_t *) condition->backend, |
631
|
|
|
|
|
|
|
(pthread_mutex_t *) mutex->backend); |
632
|
|
|
|
|
|
|
else |
633
|
|
|
|
|
|
|
return 0; |
634
|
|
|
|
|
|
|
} |
635
|
|
|
|
|
|
|
|
636
|
|
|
|
|
|
|
/* Wake up all threads waiting on this condition. */ |
637
|
|
|
|
|
|
|
static inline int |
638
|
|
|
|
|
|
|
__gthread_objc_condition_broadcast (objc_condition_t condition) |
639
|
|
|
|
|
|
|
{ |
640
|
|
|
|
|
|
|
if (__gthread_active_p ()) |
641
|
|
|
|
|
|
|
return __gthrw_(pthread_cond_broadcast) ((pthread_cond_t *) condition->backend); |
642
|
|
|
|
|
|
|
else |
643
|
|
|
|
|
|
|
return 0; |
644
|
|
|
|
|
|
|
} |
645
|
|
|
|
|
|
|
|
646
|
|
|
|
|
|
|
/* Wake up one thread waiting on this condition. */ |
647
|
|
|
|
|
|
|
static inline int |
648
|
|
|
|
|
|
|
__gthread_objc_condition_signal (objc_condition_t condition) |
649
|
|
|
|
|
|
|
{ |
650
|
|
|
|
|
|
|
if (__gthread_active_p ()) |
651
|
|
|
|
|
|
|
return __gthrw_(pthread_cond_signal) ((pthread_cond_t *) condition->backend); |
652
|
|
|
|
|
|
|
else |
653
|
|
|
|
|
|
|
return 0; |
654
|
|
|
|
|
|
|
} |
655
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
#else /* _LIBOBJC */ |
657
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
static inline int |
659
|
|
|
|
|
|
|
__gthread_create (__gthread_t *__threadid, void *(*__func) (void*), |
660
|
|
|
|
|
|
|
void *__args) |
661
|
|
|
|
|
|
|
{ |
662
|
|
|
|
|
|
|
return __gthrw_(pthread_create) (__threadid, NULL, __func, __args); |
663
|
|
|
|
|
|
|
} |
664
|
|
|
|
|
|
|
|
665
|
|
|
|
|
|
|
static inline int |
666
|
|
|
|
|
|
|
__gthread_join (__gthread_t __threadid, void **__value_ptr) |
667
|
|
|
|
|
|
|
{ |
668
|
|
|
|
|
|
|
return __gthrw_(pthread_join) (__threadid, __value_ptr); |
669
|
|
|
|
|
|
|
} |
670
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
static inline int |
672
|
|
|
|
|
|
|
__gthread_detach (__gthread_t __threadid) |
673
|
|
|
|
|
|
|
{ |
674
|
|
|
|
|
|
|
return __gthrw_(pthread_detach) (__threadid); |
675
|
|
|
|
|
|
|
} |
676
|
|
|
|
|
|
|
|
677
|
|
|
|
|
|
|
static inline int |
678
|
|
|
|
|
|
|
__gthread_equal (__gthread_t __t1, __gthread_t __t2) |
679
|
|
|
|
|
|
|
{ |
680
|
|
|
|
|
|
|
return __gthrw_(pthread_equal) (__t1, __t2); |
681
|
|
|
|
|
|
|
} |
682
|
|
|
|
|
|
|
|
683
|
|
|
|
|
|
|
static inline __gthread_t |
684
|
|
|
|
|
|
|
__gthread_self (void) |
685
|
|
|
|
|
|
|
{ |
686
|
|
|
|
|
|
|
return __gthrw_(pthread_self) (); |
687
|
|
|
|
|
|
|
} |
688
|
|
|
|
|
|
|
|
689
|
|
|
|
|
|
|
static inline int |
690
|
|
|
|
|
|
|
__gthread_yield (void) |
691
|
|
|
|
|
|
|
{ |
692
|
|
|
|
|
|
|
return __gthrw_(sched_yield) (); |
693
|
|
|
|
|
|
|
} |
694
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
static inline int |
696
|
|
|
|
|
|
|
__gthread_once (__gthread_once_t *__once, void (*__func) (void)) |
697
|
|
|
|
|
|
|
{ |
698
|
|
|
|
|
|
|
if (__gthread_active_p ()) |
699
|
|
|
|
|
|
|
return __gthrw_(pthread_once) (__once, __func); |
700
|
|
|
|
|
|
|
else |
701
|
|
|
|
|
|
|
return -1; |
702
|
|
|
|
|
|
|
} |
703
|
|
|
|
|
|
|
|
704
|
|
|
|
|
|
|
static inline int |
705
|
|
|
|
|
|
|
__gthread_key_create (__gthread_key_t *__key, void (*__dtor) (void *)) |
706
|
|
|
|
|
|
|
{ |
707
|
|
|
|
|
|
|
return __gthrw_(pthread_key_create) (__key, __dtor); |
708
|
|
|
|
|
|
|
} |
709
|
|
|
|
|
|
|
|
710
|
|
|
|
|
|
|
static inline int |
711
|
|
|
|
|
|
|
__gthread_key_delete (__gthread_key_t __key) |
712
|
|
|
|
|
|
|
{ |
713
|
|
|
|
|
|
|
return __gthrw_(pthread_key_delete) (__key); |
714
|
|
|
|
|
|
|
} |
715
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
static inline void * |
717
|
|
|
|
|
|
|
__gthread_getspecific (__gthread_key_t __key) |
718
|
|
|
|
|
|
|
{ |
719
|
|
|
|
|
|
|
return __gthrw_(pthread_getspecific) (__key); |
720
|
|
|
|
|
|
|
} |
721
|
|
|
|
|
|
|
|
722
|
|
|
|
|
|
|
static inline int |
723
|
|
|
|
|
|
|
__gthread_setspecific (__gthread_key_t __key, const void *__ptr) |
724
|
|
|
|
|
|
|
{ |
725
|
|
|
|
|
|
|
return __gthrw_(pthread_setspecific) (__key, __ptr); |
726
|
|
|
|
|
|
|
} |
727
|
|
|
|
|
|
|
|
728
|
|
|
|
|
|
|
static inline void |
729
|
|
|
|
|
|
|
__gthread_mutex_init_function (__gthread_mutex_t *__mutex) |
730
|
|
|
|
|
|
|
{ |
731
|
|
|
|
|
|
|
if (__gthread_active_p ()) |
732
|
|
|
|
|
|
|
__gthrw_(pthread_mutex_init) (__mutex, NULL); |
733
|
|
|
|
|
|
|
} |
734
|
|
|
|
|
|
|
|
735
|
|
|
|
|
|
|
static inline int |
736
|
|
|
|
|
|
|
__gthread_mutex_destroy (__gthread_mutex_t *__mutex) |
737
|
|
|
|
|
|
|
{ |
738
|
|
|
|
|
|
|
if (__gthread_active_p ()) |
739
|
|
|
|
|
|
|
return __gthrw_(pthread_mutex_destroy) (__mutex); |
740
|
|
|
|
|
|
|
else |
741
|
|
|
|
|
|
|
return 0; |
742
|
|
|
|
|
|
|
} |
743
|
|
|
|
|
|
|
|
744
|
|
|
|
|
|
|
static inline int |
745
|
0
|
|
|
|
|
|
__gthread_mutex_lock (__gthread_mutex_t *__mutex) |
746
|
|
|
|
|
|
|
{ |
747
|
0
|
0
|
|
|
|
|
if (__gthread_active_p ()) |
748
|
0
|
|
|
|
|
|
return __gthrw_(pthread_mutex_lock) (__mutex); |
749
|
|
|
|
|
|
|
else |
750
|
0
|
|
|
|
|
|
return 0; |
751
|
|
|
|
|
|
|
} |
752
|
|
|
|
|
|
|
|
753
|
|
|
|
|
|
|
static inline int |
754
|
|
|
|
|
|
|
__gthread_mutex_trylock (__gthread_mutex_t *__mutex) |
755
|
|
|
|
|
|
|
{ |
756
|
|
|
|
|
|
|
if (__gthread_active_p ()) |
757
|
|
|
|
|
|
|
return __gthrw_(pthread_mutex_trylock) (__mutex); |
758
|
|
|
|
|
|
|
else |
759
|
|
|
|
|
|
|
return 0; |
760
|
|
|
|
|
|
|
} |
761
|
|
|
|
|
|
|
|
762
|
|
|
|
|
|
|
#if _GTHREAD_USE_MUTEX_TIMEDLOCK |
763
|
|
|
|
|
|
|
static inline int |
764
|
|
|
|
|
|
|
__gthread_mutex_timedlock (__gthread_mutex_t *__mutex, |
765
|
|
|
|
|
|
|
const __gthread_time_t *__abs_timeout) |
766
|
|
|
|
|
|
|
{ |
767
|
|
|
|
|
|
|
if (__gthread_active_p ()) |
768
|
|
|
|
|
|
|
return __gthrw_(pthread_mutex_timedlock) (__mutex, __abs_timeout); |
769
|
|
|
|
|
|
|
else |
770
|
|
|
|
|
|
|
return 0; |
771
|
|
|
|
|
|
|
} |
772
|
|
|
|
|
|
|
#endif |
773
|
|
|
|
|
|
|
|
774
|
|
|
|
|
|
|
static inline int |
775
|
0
|
|
|
|
|
|
__gthread_mutex_unlock (__gthread_mutex_t *__mutex) |
776
|
|
|
|
|
|
|
{ |
777
|
0
|
0
|
|
|
|
|
if (__gthread_active_p ()) |
778
|
0
|
|
|
|
|
|
return __gthrw_(pthread_mutex_unlock) (__mutex); |
779
|
|
|
|
|
|
|
else |
780
|
0
|
|
|
|
|
|
return 0; |
781
|
|
|
|
|
|
|
} |
782
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
#if !defined( PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP) \ |
784
|
|
|
|
|
|
|
|| defined(_GTHREAD_USE_RECURSIVE_MUTEX_INIT_FUNC) |
785
|
|
|
|
|
|
|
static inline int |
786
|
|
|
|
|
|
|
__gthread_recursive_mutex_init_function (__gthread_recursive_mutex_t *__mutex) |
787
|
|
|
|
|
|
|
{ |
788
|
|
|
|
|
|
|
if (__gthread_active_p ()) |
789
|
|
|
|
|
|
|
{ |
790
|
|
|
|
|
|
|
pthread_mutexattr_t __attr; |
791
|
|
|
|
|
|
|
int __r; |
792
|
|
|
|
|
|
|
|
793
|
|
|
|
|
|
|
__r = __gthrw_(pthread_mutexattr_init) (&__attr); |
794
|
|
|
|
|
|
|
if (!__r) |
795
|
|
|
|
|
|
|
__r = __gthrw_(pthread_mutexattr_settype) (&__attr, |
796
|
|
|
|
|
|
|
PTHREAD_MUTEX_RECURSIVE); |
797
|
|
|
|
|
|
|
if (!__r) |
798
|
|
|
|
|
|
|
__r = __gthrw_(pthread_mutex_init) (__mutex, &__attr); |
799
|
|
|
|
|
|
|
if (!__r) |
800
|
|
|
|
|
|
|
__r = __gthrw_(pthread_mutexattr_destroy) (&__attr); |
801
|
|
|
|
|
|
|
return __r; |
802
|
|
|
|
|
|
|
} |
803
|
|
|
|
|
|
|
return 0; |
804
|
|
|
|
|
|
|
} |
805
|
|
|
|
|
|
|
#endif |
806
|
|
|
|
|
|
|
|
807
|
|
|
|
|
|
|
static inline int |
808
|
|
|
|
|
|
|
__gthread_recursive_mutex_lock (__gthread_recursive_mutex_t *__mutex) |
809
|
|
|
|
|
|
|
{ |
810
|
|
|
|
|
|
|
return __gthread_mutex_lock (__mutex); |
811
|
|
|
|
|
|
|
} |
812
|
|
|
|
|
|
|
|
813
|
|
|
|
|
|
|
static inline int |
814
|
|
|
|
|
|
|
__gthread_recursive_mutex_trylock (__gthread_recursive_mutex_t *__mutex) |
815
|
|
|
|
|
|
|
{ |
816
|
|
|
|
|
|
|
return __gthread_mutex_trylock (__mutex); |
817
|
|
|
|
|
|
|
} |
818
|
|
|
|
|
|
|
|
819
|
|
|
|
|
|
|
#if _GTHREAD_USE_MUTEX_TIMEDLOCK |
820
|
|
|
|
|
|
|
static inline int |
821
|
|
|
|
|
|
|
__gthread_recursive_mutex_timedlock (__gthread_recursive_mutex_t *__mutex, |
822
|
|
|
|
|
|
|
const __gthread_time_t *__abs_timeout) |
823
|
|
|
|
|
|
|
{ |
824
|
|
|
|
|
|
|
return __gthread_mutex_timedlock (__mutex, __abs_timeout); |
825
|
|
|
|
|
|
|
} |
826
|
|
|
|
|
|
|
#endif |
827
|
|
|
|
|
|
|
|
828
|
|
|
|
|
|
|
static inline int |
829
|
|
|
|
|
|
|
__gthread_recursive_mutex_unlock (__gthread_recursive_mutex_t *__mutex) |
830
|
|
|
|
|
|
|
{ |
831
|
|
|
|
|
|
|
return __gthread_mutex_unlock (__mutex); |
832
|
|
|
|
|
|
|
} |
833
|
|
|
|
|
|
|
|
834
|
|
|
|
|
|
|
static inline int |
835
|
|
|
|
|
|
|
__gthread_recursive_mutex_destroy (__gthread_recursive_mutex_t *__mutex) |
836
|
|
|
|
|
|
|
{ |
837
|
|
|
|
|
|
|
return __gthread_mutex_destroy (__mutex); |
838
|
|
|
|
|
|
|
} |
839
|
|
|
|
|
|
|
|
840
|
|
|
|
|
|
|
#ifdef _GTHREAD_USE_COND_INIT_FUNC |
841
|
|
|
|
|
|
|
static inline void |
842
|
|
|
|
|
|
|
__gthread_cond_init_function (__gthread_cond_t *__cond) |
843
|
|
|
|
|
|
|
{ |
844
|
|
|
|
|
|
|
if (__gthread_active_p ()) |
845
|
|
|
|
|
|
|
__gthrw_(pthread_cond_init) (__cond, NULL); |
846
|
|
|
|
|
|
|
} |
847
|
|
|
|
|
|
|
#endif |
848
|
|
|
|
|
|
|
|
849
|
|
|
|
|
|
|
static inline int |
850
|
|
|
|
|
|
|
__gthread_cond_broadcast (__gthread_cond_t *__cond) |
851
|
|
|
|
|
|
|
{ |
852
|
|
|
|
|
|
|
return __gthrw_(pthread_cond_broadcast) (__cond); |
853
|
|
|
|
|
|
|
} |
854
|
|
|
|
|
|
|
|
855
|
|
|
|
|
|
|
static inline int |
856
|
|
|
|
|
|
|
__gthread_cond_signal (__gthread_cond_t *__cond) |
857
|
|
|
|
|
|
|
{ |
858
|
|
|
|
|
|
|
return __gthrw_(pthread_cond_signal) (__cond); |
859
|
|
|
|
|
|
|
} |
860
|
|
|
|
|
|
|
|
861
|
|
|
|
|
|
|
static inline int |
862
|
|
|
|
|
|
|
__gthread_cond_wait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex) |
863
|
|
|
|
|
|
|
{ |
864
|
|
|
|
|
|
|
return __gthrw_(pthread_cond_wait) (__cond, __mutex); |
865
|
|
|
|
|
|
|
} |
866
|
|
|
|
|
|
|
|
867
|
|
|
|
|
|
|
static inline int |
868
|
|
|
|
|
|
|
__gthread_cond_timedwait (__gthread_cond_t *__cond, __gthread_mutex_t *__mutex, |
869
|
|
|
|
|
|
|
const __gthread_time_t *__abs_timeout) |
870
|
|
|
|
|
|
|
{ |
871
|
|
|
|
|
|
|
return __gthrw_(pthread_cond_timedwait) (__cond, __mutex, __abs_timeout); |
872
|
|
|
|
|
|
|
} |
873
|
|
|
|
|
|
|
|
874
|
|
|
|
|
|
|
static inline int |
875
|
|
|
|
|
|
|
__gthread_cond_wait_recursive (__gthread_cond_t *__cond, |
876
|
|
|
|
|
|
|
__gthread_recursive_mutex_t *__mutex) |
877
|
|
|
|
|
|
|
{ |
878
|
|
|
|
|
|
|
return __gthread_cond_wait (__cond, __mutex); |
879
|
|
|
|
|
|
|
} |
880
|
|
|
|
|
|
|
|
881
|
|
|
|
|
|
|
static inline int |
882
|
|
|
|
|
|
|
__gthread_cond_destroy (__gthread_cond_t* __cond) |
883
|
|
|
|
|
|
|
{ |
884
|
|
|
|
|
|
|
return __gthrw_(pthread_cond_destroy) (__cond); |
885
|
|
|
|
|
|
|
} |
886
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
#endif /* _LIBOBJC */ |
888
|
|
|
|
|
|
|
|
889
|
|
|
|
|
|
|
#endif /* ! _GLIBCXX_GCC_GTHR_POSIX_H */ |