21
#include "mysys/mysys_priv.h"
22
#include <mysys/my_pthread.h>
21
#include "mysys_priv.h"
23
22
#include <mystrings/m_string.h>
26
23
#include <signal.h>
28
#if TIME_WITH_SYS_TIME
29
# include <sys/time.h>
25
uint thd_lib_detected= 0;
28
pthread_key(struct st_my_thread_var*, THR_KEY_mysys);
33
# include <sys/time.h>
39
uint32_t thd_lib_detected= 0;
41
pthread_key_t THR_KEY_mysys;
42
pthread_mutex_t THR_LOCK_lock;
43
pthread_mutex_t THR_LOCK_threads;
30
pthread_key(struct st_my_thread_var, THR_KEY_mysys);
32
pthread_mutex_t THR_LOCK_malloc,THR_LOCK_open,
33
THR_LOCK_lock,THR_LOCK_isam,THR_LOCK_myisam,THR_LOCK_heap,
34
THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads, THR_LOCK_time;
44
35
pthread_cond_t THR_COND_threads;
45
uint32_t THR_thread_count= 0;
46
static uint32_t my_thread_end_wait_time= 5;
36
uint THR_thread_count= 0;
37
uint my_thread_end_wait_time= 5;
38
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
39
pthread_mutex_t LOCK_localtime_r;
41
#ifndef HAVE_GETHOSTBYNAME_R
42
pthread_mutex_t LOCK_gethostbyname_r;
47
44
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
48
45
pthread_mutexattr_t my_fast_mutexattr;
51
static uint32_t get_thread_lib(void);
47
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
48
pthread_mutexattr_t my_errorcheck_mutexattr;
51
#ifdef TARGET_OS_LINUX
54
Dummy thread spawned in my_thread_global_init() below to avoid
55
race conditions in NPTL pthread_exit code.
58
static pthread_handler_t
59
nptl_pthread_exit_hack_handler(void *arg __attribute((unused)))
66
#endif /* TARGET_OS_LINUX */
69
static uint get_thread_lib(void);
54
72
initialize thread environment
93
#ifdef TARGET_OS_LINUX
95
BUG#24507: Race conditions inside current NPTL pthread_exit()
98
To avoid a possible segmentation fault during concurrent
99
executions of pthread_exit(), a dummy thread is spawned which
100
initializes internal variables of pthread lib. See bug description
101
for a full explanation.
103
TODO: Remove this code when fixed versions of glibc6 are in common
106
if (thd_lib_detected == THD_LIB_NPTL)
108
pthread_t dummy_thread;
109
pthread_attr_t dummy_thread_attr;
111
pthread_attr_init(&dummy_thread_attr);
112
pthread_attr_setdetachstate(&dummy_thread_attr, PTHREAD_CREATE_DETACHED);
114
pthread_create(&dummy_thread,&dummy_thread_attr,
115
nptl_pthread_exit_hack_handler, NULL);
117
#endif /* TARGET_OS_LINUX */
75
119
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
77
121
Set mutex type to "fast" a.k.a "adaptive"
86
130
pthread_mutexattr_settype(&my_fast_mutexattr,
87
131
PTHREAD_MUTEX_ADAPTIVE_NP);
133
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
135
Set mutex type to "errorcheck"
137
pthread_mutexattr_init(&my_errorcheck_mutexattr);
138
pthread_mutexattr_settype(&my_errorcheck_mutexattr,
139
PTHREAD_MUTEX_ERRORCHECK);
142
pthread_mutex_init(&THR_LOCK_malloc,MY_MUTEX_INIT_FAST);
143
pthread_mutex_init(&THR_LOCK_open,MY_MUTEX_INIT_FAST);
90
144
pthread_mutex_init(&THR_LOCK_lock,MY_MUTEX_INIT_FAST);
145
pthread_mutex_init(&THR_LOCK_isam,MY_MUTEX_INIT_SLOW);
146
pthread_mutex_init(&THR_LOCK_myisam,MY_MUTEX_INIT_SLOW);
147
pthread_mutex_init(&THR_LOCK_heap,MY_MUTEX_INIT_FAST);
148
pthread_mutex_init(&THR_LOCK_net,MY_MUTEX_INIT_FAST);
149
pthread_mutex_init(&THR_LOCK_charset,MY_MUTEX_INIT_FAST);
91
150
pthread_mutex_init(&THR_LOCK_threads,MY_MUTEX_INIT_FAST);
151
pthread_mutex_init(&THR_LOCK_time,MY_MUTEX_INIT_FAST);
92
152
pthread_cond_init(&THR_COND_threads, NULL);
153
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
154
pthread_mutex_init(&LOCK_localtime_r,MY_MUTEX_INIT_SLOW);
156
#ifndef HAVE_GETHOSTBYNAME_R
157
pthread_mutex_init(&LOCK_gethostbyname_r,MY_MUTEX_INIT_SLOW);
93
159
if (my_thread_init())
95
161
my_thread_global_end(); /* Clean up */
131
199
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
132
200
pthread_mutexattr_destroy(&my_fast_mutexattr);
202
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
203
pthread_mutexattr_destroy(&my_errorcheck_mutexattr);
205
pthread_mutex_destroy(&THR_LOCK_malloc);
206
pthread_mutex_destroy(&THR_LOCK_open);
134
207
pthread_mutex_destroy(&THR_LOCK_lock);
208
pthread_mutex_destroy(&THR_LOCK_isam);
209
pthread_mutex_destroy(&THR_LOCK_myisam);
210
pthread_mutex_destroy(&THR_LOCK_heap);
211
pthread_mutex_destroy(&THR_LOCK_net);
212
pthread_mutex_destroy(&THR_LOCK_time);
213
pthread_mutex_destroy(&THR_LOCK_charset);
135
214
if (all_threads_killed)
137
216
pthread_mutex_destroy(&THR_LOCK_threads);
138
217
pthread_cond_destroy(&THR_COND_threads);
219
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
220
pthread_mutex_destroy(&LOCK_localtime_r);
222
#ifndef HAVE_GETHOSTBYNAME_R
223
pthread_mutex_destroy(&LOCK_gethostbyname_r);
142
227
static my_thread_id thread_id= 0;
236
We can't use mutex_locks here if we are using windows as
237
we may have compiled the program with SAFE_MUTEX, in which
238
case the checking of mutex_locks will not work until
239
the pthread_self thread specific variable is initialized.
152
243
1 Fatal error; mysys/dbug functions can't be used
155
246
bool my_thread_init(void)
248
struct st_my_thread_var *tmp;
158
st_my_thread_var *tmp= NULL;
160
251
#ifdef EXTRA_DEBUG_THREADS
161
252
fprintf(stderr,"my_thread_init(): thread_id: 0x%lx\n",
162
253
(uint32_t) pthread_self());
165
256
if (pthread_getspecific(THR_KEY_mysys))
167
258
#ifdef EXTRA_DEBUG_THREADS
168
259
fprintf(stderr,"my_thread_init() called more than once in thread 0x%lx\n",
169
260
(long) pthread_self());
173
tmp= static_cast<st_my_thread_var *>(calloc(1, sizeof(*tmp)));
264
if (!(tmp= (struct st_my_thread_var *) calloc(1, sizeof(*tmp))))
207
297
void my_thread_end(void)
209
st_my_thread_var *tmp=
210
static_cast<st_my_thread_var *>(pthread_getspecific(THR_KEY_mysys));
299
struct st_my_thread_var *tmp;
300
tmp= (struct st_my_thread_var *)pthread_getspecific(THR_KEY_mysys);
212
302
#ifdef EXTRA_DEBUG_THREADS
213
303
fprintf(stderr,"my_thread_end(): tmp: 0x%lx pthread_self: 0x%lx thread_id: %ld\n",
214
304
(long) tmp, (long) pthread_self(), tmp ? (long) tmp->id : 0L);
216
306
if (tmp && tmp->init)
218
308
#if !defined(__bsdi__) && !defined(__OpenBSD__)
220
310
pthread_cond_destroy(&tmp->suspend);
222
312
pthread_mutex_destroy(&tmp->mutex);
226
320
Decrement counter for number of running threads. We are using this
227
321
in my_thread_global_end() to wait until all threads have called
228
322
my_thread_end and thus freed all memory they have allocated in
231
325
pthread_mutex_lock(&THR_LOCK_threads);
232
326
assert(THR_thread_count != 0);
233
327
if (--THR_thread_count == 0)
234
328
pthread_cond_signal(&THR_COND_threads);
235
pthread_mutex_unlock(&THR_LOCK_threads);
329
pthread_mutex_unlock(&THR_LOCK_threads);
331
/* The following free has to be done, even if my_thread_var() is 0 */
333
pthread_setspecific(THR_KEY_mysys,0);
239
337
struct st_my_thread_var *_my_thread_var(void)
241
339
struct st_my_thread_var *tmp= (struct st_my_thread_var*)pthread_getspecific(THR_KEY_mysys);
341
/* This can only happen in a .DLL */
345
tmp=my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys);
245
static uint32_t get_thread_lib(void)
352
/****************************************************************************
353
Get name of current thread.
354
****************************************************************************/
356
my_thread_id my_thread_dbug_id()
358
return my_thread_var->id;
361
static uint get_thread_lib(void)
247
363
#ifdef _CS_GNU_LIBPTHREAD_VERSION
250
366
confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff));
252
368
if (!strncasecmp(buff, "NPTL", 4))