~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/my_thr_init.c

  • Committer: Brian Aker
  • Date: 2008-08-16 15:41:14 UTC
  • mto: This revision was merged to the branch mainline in revision 346.
  • Revision ID: brian@tangent.org-20080816154114-eufmwf31p6ie1nd6
Cleaned up depend in Proto utils. Modified int to bool. Put TmpTable class
into play.

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
  thread variables.
19
19
*/
20
20
 
21
 
#include "mysys/mysys_priv.h"
22
 
#include <mysys/my_pthread.h>
 
21
#include "mysys_priv.h"
23
22
#include <mystrings/m_string.h>
24
 
 
25
 
#include <stdio.h>
26
23
#include <signal.h>
27
24
 
28
 
#if TIME_WITH_SYS_TIME
29
 
# include <sys/time.h>
30
 
# include <time.h>
 
25
uint thd_lib_detected= 0;
 
26
 
 
27
#ifdef USE_TLS
 
28
pthread_key(struct st_my_thread_var*, THR_KEY_mysys);
31
29
#else
32
 
# if HAVE_SYS_TIME_H
33
 
#  include <sys/time.h>
34
 
# else
35
 
#  include <time.h>
36
 
# endif
37
 
#endif
38
 
 
39
 
uint32_t thd_lib_detected= 0;
40
 
 
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);
 
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;
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;
 
40
#endif
 
41
#ifndef HAVE_GETHOSTBYNAME_R
 
42
pthread_mutex_t LOCK_gethostbyname_r;
 
43
#endif
47
44
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
48
45
pthread_mutexattr_t my_fast_mutexattr;
49
46
#endif
50
 
 
51
 
static uint32_t get_thread_lib(void);
 
47
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
 
48
pthread_mutexattr_t my_errorcheck_mutexattr;
 
49
#endif
 
50
 
 
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
 
 
69
static uint get_thread_lib(void);
52
70
 
53
71
/*
54
72
  initialize thread environment
72
90
    return 1;
73
91
  }
74
92
 
 
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
 
75
119
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
76
120
  /*
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);
88
132
#endif
 
133
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
 
134
  /*
 
135
    Set mutex type to "errorcheck"
 
136
  */
 
137
  pthread_mutexattr_init(&my_errorcheck_mutexattr);
 
138
  pthread_mutexattr_settype(&my_errorcheck_mutexattr,
 
139
                            PTHREAD_MUTEX_ERRORCHECK);
 
140
#endif
89
141
 
 
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);
 
155
#endif
 
156
#ifndef HAVE_GETHOSTBYNAME_R
 
157
  pthread_mutex_init(&LOCK_gethostbyname_r,MY_MUTEX_INIT_SLOW);
 
158
#endif
93
159
  if (my_thread_init())
94
160
  {
95
161
    my_thread_global_end();                     /* Clean up */
112
178
                                      &abstime);
113
179
    if (error == ETIMEDOUT || error == ETIME)
114
180
    {
 
181
#ifdef HAVE_PTHREAD_KILL
115
182
      /*
116
183
        We shouldn't give an error here, because if we don't have
117
184
        pthread_kill(), programs like mysqld can't ensure that all threads
121
188
        fprintf(stderr,
122
189
                "Error in my_thread_global_end(): %d threads didn't exit\n",
123
190
                THR_thread_count);
 
191
#endif
124
192
      all_threads_killed= 0;
125
193
      break;
126
194
    }
131
199
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
132
200
  pthread_mutexattr_destroy(&my_fast_mutexattr);
133
201
#endif
 
202
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
 
203
  pthread_mutexattr_destroy(&my_errorcheck_mutexattr);
 
204
#endif
 
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)
136
215
  {
137
216
    pthread_mutex_destroy(&THR_LOCK_threads);
138
217
    pthread_cond_destroy(&THR_COND_threads);
139
218
  }
 
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
140
225
}
141
226
 
142
227
static my_thread_id thread_id= 0;
147
232
  SYNOPSIS
148
233
    my_thread_init()
149
234
 
 
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
 
150
241
  RETURN
151
242
    0  ok
152
243
    1  Fatal error; mysys/dbug functions can't be used
154
245
 
155
246
bool my_thread_init(void)
156
247
{
 
248
  struct st_my_thread_var *tmp;
157
249
  bool error=0;
158
 
  st_my_thread_var *tmp= NULL;
159
250
 
160
251
#ifdef EXTRA_DEBUG_THREADS
161
252
  fprintf(stderr,"my_thread_init(): thread_id: 0x%lx\n",
162
253
          (uint32_t) pthread_self());
163
 
#endif
 
254
#endif  
164
255
 
165
256
  if (pthread_getspecific(THR_KEY_mysys))
166
257
  {
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());
170
 
#endif
 
261
#endif    
171
262
    goto end;
172
263
  }
173
 
  tmp= static_cast<st_my_thread_var *>(calloc(1, sizeof(*tmp)));
174
 
  if (tmp == NULL)
 
264
  if (!(tmp= (struct st_my_thread_var *) calloc(1, sizeof(*tmp))))
175
265
  {
176
266
    error= 1;
177
267
    goto end;
206
296
 
207
297
void my_thread_end(void)
208
298
{
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);
211
301
 
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);
215
 
#endif
 
305
#endif  
216
306
  if (tmp && tmp->init)
217
307
  {
218
308
#if !defined(__bsdi__) && !defined(__OpenBSD__)
220
310
    pthread_cond_destroy(&tmp->suspend);
221
311
#endif
222
312
    pthread_mutex_destroy(&tmp->mutex);
 
313
#if defined(USE_TLS)
223
314
    free(tmp);
 
315
#else
 
316
    tmp->init= 0;
 
317
#endif
224
318
 
225
319
    /*
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
229
 
      my_thread_init()
 
323
      my_thread_init() 
230
324
    */
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);
236
330
  }
 
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
237
335
}
238
336
 
239
337
struct st_my_thread_var *_my_thread_var(void)
240
338
{
241
339
  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
242
348
  return tmp;
243
349
}
244
350
 
245
 
static uint32_t get_thread_lib(void)
 
351
 
 
352
/****************************************************************************
 
353
  Get name of current thread.
 
354
****************************************************************************/
 
355
 
 
356
my_thread_id my_thread_dbug_id()
 
357
{
 
358
  return my_thread_var->id;
 
359
}
 
360
 
 
361
static uint get_thread_lib(void)
246
362
{
247
363
#ifdef _CS_GNU_LIBPTHREAD_VERSION
248
364
  char buff[64];
249
 
 
 
365
    
250
366
  confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff));
251
367
 
252
368
  if (!strncasecmp(buff, "NPTL", 4))