~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/my_thr_init.cc

MergedĀ inĀ trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
  thread variables.
19
19
*/
20
20
 
21
 
#include "mysys_priv.h"
 
21
#include "mysys/mysys_priv.h"
 
22
#include <mysys/my_pthread.h>
22
23
#include <mystrings/m_string.h>
 
24
 
 
25
#include <stdio.h>
23
26
#include <signal.h>
24
27
 
 
28
#if TIME_WITH_SYS_TIME
 
29
# include <sys/time.h>
 
30
# include <time.h>
 
31
#else
 
32
# if HAVE_SYS_TIME_H
 
33
#  include <sys/time.h>
 
34
# else
 
35
#  include <time.h>
 
36
# endif
 
37
#endif
 
38
 
25
39
uint32_t thd_lib_detected= 0;
26
40
 
27
 
#ifdef USE_TLS
28
 
pthread_key(struct st_my_thread_var*, THR_KEY_mysys);
29
 
#else
30
 
pthread_key(struct st_my_thread_var, THR_KEY_mysys);
31
 
#endif /* USE_TLS */
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;
 
41
pthread_key_t THR_KEY_mysys;
 
42
pthread_mutex_t THR_LOCK_lock;
 
43
pthread_mutex_t THR_LOCK_threads;
35
44
pthread_cond_t  THR_COND_threads;
36
45
uint32_t            THR_thread_count= 0;
37
46
uint32_t                my_thread_end_wait_time= 5;
38
 
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
39
 
pthread_mutex_t LOCK_localtime_r;
40
 
#endif
41
 
#ifndef HAVE_GETHOSTBYNAME_R
42
 
pthread_mutex_t LOCK_gethostbyname_r;
43
 
#endif
44
47
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
45
48
pthread_mutexattr_t my_fast_mutexattr;
46
49
#endif
48
51
pthread_mutexattr_t my_errorcheck_mutexattr;
49
52
#endif
50
53
 
51
 
#ifdef TARGET_OS_LINUX
52
 
 
53
 
/*
54
 
  Dummy thread spawned in my_thread_global_init() below to avoid
55
 
  race conditions in NPTL pthread_exit code.
56
 
*/
57
 
 
58
 
static pthread_handler_t
59
 
nptl_pthread_exit_hack_handler(void *arg __attribute((unused)))
60
 
{
61
 
  /* Do nothing! */
62
 
  pthread_exit(0);
63
 
  return 0;
64
 
}
65
 
 
66
 
#endif /* TARGET_OS_LINUX */
67
 
 
68
54
 
69
55
static uint32_t get_thread_lib(void);
70
56
 
90
76
    return 1;
91
77
  }
92
78
 
93
 
#ifdef TARGET_OS_LINUX
94
 
  /*
95
 
    BUG#24507: Race conditions inside current NPTL pthread_exit()
96
 
    implementation.
97
 
 
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.
102
 
 
103
 
    TODO: Remove this code when fixed versions of glibc6 are in common
104
 
    use.
105
 
  */
106
 
  if (thd_lib_detected == THD_LIB_NPTL)
107
 
  {
108
 
    pthread_t       dummy_thread;
109
 
    pthread_attr_t  dummy_thread_attr;
110
 
 
111
 
    pthread_attr_init(&dummy_thread_attr);
112
 
    pthread_attr_setdetachstate(&dummy_thread_attr, PTHREAD_CREATE_DETACHED);
113
 
 
114
 
    pthread_create(&dummy_thread,&dummy_thread_attr,
115
 
                   nptl_pthread_exit_hack_handler, NULL);
116
 
  }
117
 
#endif /* TARGET_OS_LINUX */
118
 
 
119
79
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
120
80
  /*
121
81
    Set mutex type to "fast" a.k.a "adaptive"
139
99
                            PTHREAD_MUTEX_ERRORCHECK);
140
100
#endif
141
101
 
142
 
  pthread_mutex_init(&THR_LOCK_malloc,MY_MUTEX_INIT_FAST);
143
 
  pthread_mutex_init(&THR_LOCK_open,MY_MUTEX_INIT_FAST);
144
102
  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);
150
103
  pthread_mutex_init(&THR_LOCK_threads,MY_MUTEX_INIT_FAST);
151
 
  pthread_mutex_init(&THR_LOCK_time,MY_MUTEX_INIT_FAST);
152
104
  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);
155
 
#endif
156
 
#ifndef HAVE_GETHOSTBYNAME_R
157
 
  pthread_mutex_init(&LOCK_gethostbyname_r,MY_MUTEX_INIT_SLOW);
158
 
#endif
159
105
  if (my_thread_init())
160
106
  {
161
107
    my_thread_global_end();                     /* Clean up */
178
124
                                      &abstime);
179
125
    if (error == ETIMEDOUT || error == ETIME)
180
126
    {
181
 
#ifdef HAVE_PTHREAD_KILL
182
127
      /*
183
128
        We shouldn't give an error here, because if we don't have
184
129
        pthread_kill(), programs like mysqld can't ensure that all threads
188
133
        fprintf(stderr,
189
134
                "Error in my_thread_global_end(): %d threads didn't exit\n",
190
135
                THR_thread_count);
191
 
#endif
192
136
      all_threads_killed= 0;
193
137
      break;
194
138
    }
202
146
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
203
147
  pthread_mutexattr_destroy(&my_errorcheck_mutexattr);
204
148
#endif
205
 
  pthread_mutex_destroy(&THR_LOCK_malloc);
206
 
  pthread_mutex_destroy(&THR_LOCK_open);
207
149
  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);
214
150
  if (all_threads_killed)
215
151
  {
216
152
    pthread_mutex_destroy(&THR_LOCK_threads);
217
153
    pthread_cond_destroy(&THR_COND_threads);
218
154
  }
219
 
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
220
 
  pthread_mutex_destroy(&LOCK_localtime_r);
221
 
#endif
222
 
#ifndef HAVE_GETHOSTBYNAME_R
223
 
  pthread_mutex_destroy(&LOCK_gethostbyname_r);
224
 
#endif
225
155
}
226
156
 
227
157
static my_thread_id thread_id= 0;
232
162
  SYNOPSIS
233
163
    my_thread_init()
234
164
 
235
 
  NOTES
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.
240
 
 
241
165
  RETURN
242
166
    0  ok
243
167
    1  Fatal error; mysys/dbug functions can't be used
245
169
 
246
170
bool my_thread_init(void)
247
171
{
248
 
  struct st_my_thread_var *tmp;
249
172
  bool error=0;
 
173
  st_my_thread_var *tmp= NULL;
250
174
 
251
175
#ifdef EXTRA_DEBUG_THREADS
252
176
  fprintf(stderr,"my_thread_init(): thread_id: 0x%lx\n",
253
177
          (uint32_t) pthread_self());
254
 
#endif  
 
178
#endif
255
179
 
256
180
  if (pthread_getspecific(THR_KEY_mysys))
257
181
  {
258
182
#ifdef EXTRA_DEBUG_THREADS
259
183
    fprintf(stderr,"my_thread_init() called more than once in thread 0x%lx\n",
260
184
            (long) pthread_self());
261
 
#endif    
 
185
#endif
262
186
    goto end;
263
187
  }
264
 
  if (!(tmp= (struct st_my_thread_var *) calloc(1, sizeof(*tmp))))
 
188
  tmp= static_cast<st_my_thread_var *>(calloc(1, sizeof(*tmp)));
 
189
  if (tmp == NULL)
265
190
  {
266
191
    error= 1;
267
192
    goto end;
296
221
 
297
222
void my_thread_end(void)
298
223
{
299
 
  struct st_my_thread_var *tmp;
300
 
  tmp= (struct st_my_thread_var *)pthread_getspecific(THR_KEY_mysys);
 
224
  st_my_thread_var *tmp=
 
225
    static_cast<st_my_thread_var *>(pthread_getspecific(THR_KEY_mysys));
301
226
 
302
227
#ifdef EXTRA_DEBUG_THREADS
303
228
  fprintf(stderr,"my_thread_end(): tmp: 0x%lx  pthread_self: 0x%lx  thread_id: %ld\n",
304
229
          (long) tmp, (long) pthread_self(), tmp ? (long) tmp->id : 0L);
305
 
#endif  
 
230
#endif
306
231
  if (tmp && tmp->init)
307
232
  {
308
233
#if !defined(__bsdi__) && !defined(__OpenBSD__)
310
235
    pthread_cond_destroy(&tmp->suspend);
311
236
#endif
312
237
    pthread_mutex_destroy(&tmp->mutex);
313
 
#if defined(USE_TLS)
314
238
    free(tmp);
315
 
#else
316
 
    tmp->init= 0;
317
 
#endif
318
239
 
319
240
    /*
320
241
      Decrement counter for number of running threads. We are using this
321
242
      in my_thread_global_end() to wait until all threads have called
322
243
      my_thread_end and thus freed all memory they have allocated in
323
 
      my_thread_init() 
 
244
      my_thread_init()
324
245
    */
325
246
    pthread_mutex_lock(&THR_LOCK_threads);
326
247
    assert(THR_thread_count != 0);
327
248
    if (--THR_thread_count == 0)
328
249
      pthread_cond_signal(&THR_COND_threads);
329
 
   pthread_mutex_unlock(&THR_LOCK_threads);
 
250
    pthread_mutex_unlock(&THR_LOCK_threads);
330
251
  }
331
 
  /* The following free has to be done, even if my_thread_var() is 0 */
332
 
#if defined(USE_TLS)
333
 
  pthread_setspecific(THR_KEY_mysys,0);
334
 
#endif
335
252
}
336
253
 
337
254
struct st_my_thread_var *_my_thread_var(void)
338
255
{
339
256
  struct st_my_thread_var *tmp= (struct st_my_thread_var*)pthread_getspecific(THR_KEY_mysys);
340
 
#if defined(USE_TLS)
341
 
  /* This can only happen in a .DLL */
342
 
  if (!tmp)
343
 
  {
344
 
    my_thread_init();
345
 
    tmp=my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys);
346
 
  }
347
 
#endif
348
257
  return tmp;
349
258
}
350
259
 
362
271
{
363
272
#ifdef _CS_GNU_LIBPTHREAD_VERSION
364
273
  char buff[64];
365
 
    
 
274
 
366
275
  confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff));
367
276
 
368
277
  if (!strncasecmp(buff, "NPTL", 4))