~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
16
/*
17
  Functions to handle initializating and allocationg of all mysys & debug
18
  thread variables.
19
*/
20
595 by Brian Aker
Fix, partial, for Sun Studio.
21
#include <stdio.h>
575.3.1 by Monty Taylor
Made mysys and mystrings c++. Fixed the resulting bugs the compiler found.
22
#include <mysys/mysys_priv.h>
23
#include <mysys/my_pthread.h>
212.5.18 by Monty Taylor
Moved m_ctype, m_string and my_bitmap. Removed t_ctype.
24
#include <mystrings/m_string.h>
1 by brian
clean slate
25
#include <signal.h>
26
481.1.15 by Monty Taylor
Removed time.h and sys/time.h from global.h.
27
#if TIME_WITH_SYS_TIME
28
# include <sys/time.h>
29
# include <time.h>
30
#else
31
# if HAVE_SYS_TIME_H
32
#  include <sys/time.h>
33
# else
34
#  include <time.h>
35
# endif
36
#endif  
37
482 by Brian Aker
Remove uint.
38
uint32_t thd_lib_detected= 0;
8 by Brian Aker
Pstack removal. Cleanup around final my_pthread.c removal.
39
1 by brian
clean slate
40
#ifdef USE_TLS
520.6.7 by Monty Taylor
Moved a bunch of crap out of common_includes.
41
pthread_key_t THR_KEY_mysys;
1 by brian
clean slate
42
#else
520.6.7 by Monty Taylor
Moved a bunch of crap out of common_includes.
43
pthread_key_t THR_KEY_mysys;
1 by brian
clean slate
44
#endif /* USE_TLS */
596 by Brian Aker
Refactor out dead mutexes
45
pthread_mutex_t THR_LOCK_open;
46
pthread_mutex_t THR_LOCK_lock;
47
pthread_mutex_t THR_LOCK_myisam;
48
pthread_mutex_t THR_LOCK_charset; 
49
pthread_mutex_t THR_LOCK_threads; 
50
pthread_mutex_t THR_LOCK_time;
1 by brian
clean slate
51
pthread_cond_t  THR_COND_threads;
482 by Brian Aker
Remove uint.
52
uint32_t            THR_thread_count= 0;
53
uint32_t 		my_thread_end_wait_time= 5;
1 by brian
clean slate
54
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
55
pthread_mutex_t LOCK_localtime_r;
56
#endif
57
#ifndef HAVE_GETHOSTBYNAME_R
58
pthread_mutex_t LOCK_gethostbyname_r;
59
#endif
60
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
61
pthread_mutexattr_t my_fast_mutexattr;
62
#endif
63
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
64
pthread_mutexattr_t my_errorcheck_mutexattr;
65
#endif
66
67
#ifdef TARGET_OS_LINUX
68
69
/*
70
  Dummy thread spawned in my_thread_global_init() below to avoid
71
  race conditions in NPTL pthread_exit code.
72
*/
73
575.3.1 by Monty Taylor
Made mysys and mystrings c++. Fixed the resulting bugs the compiler found.
74
extern "C"
75
void *
1 by brian
clean slate
76
nptl_pthread_exit_hack_handler(void *arg __attribute((unused)))
77
{
78
  /* Do nothing! */
79
  pthread_exit(0);
80
  return 0;
81
}
82
83
#endif /* TARGET_OS_LINUX */
84
85
482 by Brian Aker
Remove uint.
86
static uint32_t get_thread_lib(void);
1 by brian
clean slate
87
88
/*
89
  initialize thread environment
90
91
  SYNOPSIS
92
    my_thread_global_init()
93
94
  RETURN
95
    0  ok
96
    1  error (Couldn't create THR_KEY_mysys)
97
*/
98
146 by Brian Aker
my_bool cleanup.
99
bool my_thread_global_init(void)
1 by brian
clean slate
100
{
101
  int pth_ret;
102
  thd_lib_detected= get_thread_lib();
103
104
  if ((pth_ret= pthread_key_create(&THR_KEY_mysys, NULL)) != 0)
105
  {
106
    fprintf(stderr,"Can't initialize threads: error %d\n", pth_ret);
107
    return 1;
108
  }
109
110
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
111
  /*
112
    Set mutex type to "fast" a.k.a "adaptive"
113
114
    In this case the thread may steal the mutex from some other thread
115
    that is waiting for the same mutex.  This will save us some
116
    context switches but may cause a thread to 'starve forever' while
117
    waiting for the mutex (not likely if the code within the mutex is
118
    short).
119
  */
120
  pthread_mutexattr_init(&my_fast_mutexattr);
121
  pthread_mutexattr_settype(&my_fast_mutexattr,
122
                            PTHREAD_MUTEX_ADAPTIVE_NP);
123
#endif
124
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
125
  /*
126
    Set mutex type to "errorcheck"
127
  */
128
  pthread_mutexattr_init(&my_errorcheck_mutexattr);
129
  pthread_mutexattr_settype(&my_errorcheck_mutexattr,
130
                            PTHREAD_MUTEX_ERRORCHECK);
131
#endif
132
133
  pthread_mutex_init(&THR_LOCK_open,MY_MUTEX_INIT_FAST);
134
  pthread_mutex_init(&THR_LOCK_lock,MY_MUTEX_INIT_FAST);
135
  pthread_mutex_init(&THR_LOCK_myisam,MY_MUTEX_INIT_SLOW);
136
  pthread_mutex_init(&THR_LOCK_charset,MY_MUTEX_INIT_FAST);
137
  pthread_mutex_init(&THR_LOCK_threads,MY_MUTEX_INIT_FAST);
138
  pthread_mutex_init(&THR_LOCK_time,MY_MUTEX_INIT_FAST);
139
  pthread_cond_init(&THR_COND_threads, NULL);
140
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
141
  pthread_mutex_init(&LOCK_localtime_r,MY_MUTEX_INIT_SLOW);
142
#endif
143
#ifndef HAVE_GETHOSTBYNAME_R
144
  pthread_mutex_init(&LOCK_gethostbyname_r,MY_MUTEX_INIT_SLOW);
145
#endif
146
  if (my_thread_init())
147
  {
148
    my_thread_global_end();			/* Clean up */
149
    return 1;
150
  }
151
  return 0;
152
}
153
154
155
void my_thread_global_end(void)
156
{
157
  struct timespec abstime;
146 by Brian Aker
my_bool cleanup.
158
  bool all_threads_killed= 1;
1 by brian
clean slate
159
160
  set_timespec(abstime, my_thread_end_wait_time);
161
  pthread_mutex_lock(&THR_LOCK_threads);
162
  while (THR_thread_count > 0)
163
  {
164
    int error= pthread_cond_timedwait(&THR_COND_threads, &THR_LOCK_threads,
165
                                      &abstime);
166
    if (error == ETIMEDOUT || error == ETIME)
167
    {
168
#ifdef HAVE_PTHREAD_KILL
169
      /*
170
        We shouldn't give an error here, because if we don't have
171
        pthread_kill(), programs like mysqld can't ensure that all threads
172
        are killed when we enter here.
173
      */
174
      if (THR_thread_count)
175
        fprintf(stderr,
176
                "Error in my_thread_global_end(): %d threads didn't exit\n",
177
                THR_thread_count);
178
#endif
179
      all_threads_killed= 0;
180
      break;
181
    }
182
  }
183
  pthread_mutex_unlock(&THR_LOCK_threads);
184
185
  pthread_key_delete(THR_KEY_mysys);
186
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
187
  pthread_mutexattr_destroy(&my_fast_mutexattr);
188
#endif
189
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
190
  pthread_mutexattr_destroy(&my_errorcheck_mutexattr);
191
#endif
192
  pthread_mutex_destroy(&THR_LOCK_open);
193
  pthread_mutex_destroy(&THR_LOCK_lock);
194
  pthread_mutex_destroy(&THR_LOCK_myisam);
195
  pthread_mutex_destroy(&THR_LOCK_time);
196
  pthread_mutex_destroy(&THR_LOCK_charset);
197
  if (all_threads_killed)
198
  {
199
    pthread_mutex_destroy(&THR_LOCK_threads);
200
    pthread_cond_destroy(&THR_COND_threads);
201
  }
202
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
203
  pthread_mutex_destroy(&LOCK_localtime_r);
204
#endif
205
#ifndef HAVE_GETHOSTBYNAME_R
206
  pthread_mutex_destroy(&LOCK_gethostbyname_r);
207
#endif
208
}
209
210
static my_thread_id thread_id= 0;
211
212
/*
51.3.28 by Jay Pipes
DBUG entirely removed from server and client
213
  Allocate thread specific memory for the thread, used by mysys
1 by brian
clean slate
214
215
  SYNOPSIS
216
    my_thread_init()
217
218
  NOTES
219
    We can't use mutex_locks here if we are using windows as
220
    we may have compiled the program with SAFE_MUTEX, in which
221
    case the checking of mutex_locks will not work until
222
    the pthread_self thread specific variable is initialized.
223
224
  RETURN
225
    0  ok
226
    1  Fatal error; mysys/dbug functions can't be used
227
*/
228
146 by Brian Aker
my_bool cleanup.
229
bool my_thread_init(void)
1 by brian
clean slate
230
{
231
  struct st_my_thread_var *tmp;
146 by Brian Aker
my_bool cleanup.
232
  bool error=0;
1 by brian
clean slate
233
234
#ifdef EXTRA_DEBUG_THREADS
235
  fprintf(stderr,"my_thread_init(): thread_id: 0x%lx\n",
298 by Brian Aker
ulong conversion.
236
          (uint32_t) pthread_self());
1 by brian
clean slate
237
#endif  
238
5 by Brian Aker
Removed my_pthread_setprio()
239
  if (pthread_getspecific(THR_KEY_mysys))
1 by brian
clean slate
240
  {
241
#ifdef EXTRA_DEBUG_THREADS
242
    fprintf(stderr,"my_thread_init() called more than once in thread 0x%lx\n",
243
            (long) pthread_self());
244
#endif    
245
    goto end;
246
  }
247
  if (!(tmp= (struct st_my_thread_var *) calloc(1, sizeof(*tmp))))
248
  {
249
    error= 1;
250
    goto end;
251
  }
252
  pthread_setspecific(THR_KEY_mysys,tmp);
253
  tmp->pthread_self= pthread_self();
254
  pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST);
255
  pthread_cond_init(&tmp->suspend, NULL);
256
  tmp->init= 1;
257
258
  pthread_mutex_lock(&THR_LOCK_threads);
259
  tmp->id= ++thread_id;
260
  ++THR_thread_count;
261
  pthread_mutex_unlock(&THR_LOCK_threads);
262
263
end:
264
  return error;
265
}
266
267
268
/*
269
  Deallocate memory used by the thread for book-keeping
270
271
  SYNOPSIS
272
    my_thread_end()
273
274
  NOTE
275
    This may be called multiple times for a thread.
276
    This happens for example when one calls 'mysql_server_init()'
277
    mysql_server_end() and then ends with a mysql_end().
278
*/
279
280
void my_thread_end(void)
281
{
282
  struct st_my_thread_var *tmp;
5 by Brian Aker
Removed my_pthread_setprio()
283
  tmp= (struct st_my_thread_var *)pthread_getspecific(THR_KEY_mysys);
1 by brian
clean slate
284
285
#ifdef EXTRA_DEBUG_THREADS
286
  fprintf(stderr,"my_thread_end(): tmp: 0x%lx  pthread_self: 0x%lx  thread_id: %ld\n",
287
	  (long) tmp, (long) pthread_self(), tmp ? (long) tmp->id : 0L);
288
#endif  
289
  if (tmp && tmp->init)
290
  {
291
#if !defined(__bsdi__) && !defined(__OpenBSD__)
292
 /* bsdi and openbsd 3.5 dumps core here */
293
    pthread_cond_destroy(&tmp->suspend);
294
#endif
295
    pthread_mutex_destroy(&tmp->mutex);
296
#if defined(USE_TLS)
297
    free(tmp);
298
#else
299
    tmp->init= 0;
300
#endif
301
302
    /*
303
      Decrement counter for number of running threads. We are using this
304
      in my_thread_global_end() to wait until all threads have called
305
      my_thread_end and thus freed all memory they have allocated in
51.3.15 by Jay Pipes
Phase 3 removal of DBUG in mysys
306
      my_thread_init() 
1 by brian
clean slate
307
    */
308
    pthread_mutex_lock(&THR_LOCK_threads);
51.3.15 by Jay Pipes
Phase 3 removal of DBUG in mysys
309
    assert(THR_thread_count != 0);
1 by brian
clean slate
310
    if (--THR_thread_count == 0)
311
      pthread_cond_signal(&THR_COND_threads);
312
   pthread_mutex_unlock(&THR_LOCK_threads);
313
  }
314
  /* The following free has to be done, even if my_thread_var() is 0 */
315
#if defined(USE_TLS)
316
  pthread_setspecific(THR_KEY_mysys,0);
317
#endif
318
}
319
320
struct st_my_thread_var *_my_thread_var(void)
321
{
5 by Brian Aker
Removed my_pthread_setprio()
322
  struct st_my_thread_var *tmp= (struct st_my_thread_var*)pthread_getspecific(THR_KEY_mysys);
1 by brian
clean slate
323
#if defined(USE_TLS)
324
  /* This can only happen in a .DLL */
325
  if (!tmp)
326
  {
327
    my_thread_init();
512.1.10 by Stewart Smith
remove my_pthread_[gs]etspecific
328
    tmp=(struct st_my_thread_var*)pthread_getspecific(THR_KEY_mysys);
1 by brian
clean slate
329
  }
330
#endif
331
  return tmp;
332
}
333
334
335
/****************************************************************************
336
  Get name of current thread.
337
****************************************************************************/
338
339
my_thread_id my_thread_dbug_id()
340
{
341
  return my_thread_var->id;
342
}
343
482 by Brian Aker
Remove uint.
344
static uint32_t get_thread_lib(void)
1 by brian
clean slate
345
{
346
#ifdef _CS_GNU_LIBPTHREAD_VERSION
347
  char buff[64];
348
    
349
  confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff));
350
351
  if (!strncasecmp(buff, "NPTL", 4))
352
    return THD_LIB_NPTL;
353
  if (!strncasecmp(buff, "linuxthreads", 12))
354
    return THD_LIB_LT;
355
#endif
356
  return THD_LIB_OTHER;
357
}