~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/my_thr_init.cc

  • Committer: Brian Aker
  • Date: 2009-02-05 09:11:16 UTC
  • Revision ID: brian@tangent.org-20090205091116-iy0ersp6bhyzt1ad
Removed dead variables.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
13
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
/*
17
17
  Functions to handle initializating and allocationg of all mysys & debug
18
18
  thread variables.
19
19
*/
20
20
 
21
 
#include "config.h"
22
 
 
23
 
#include "drizzled/internal/my_sys.h"
24
 
#include "drizzled/internal/thread_var.h"
25
 
#include "drizzled/internal/m_string.h"
26
 
 
27
 
#include <cstdio>
 
21
#include "mysys_priv.h"
 
22
#include <mysys/my_pthread.h>
 
23
#include <mystrings/m_string.h>
 
24
 
 
25
#include <stdio.h>
28
26
#include <signal.h>
29
27
 
30
28
#if TIME_WITH_SYS_TIME
38
36
# endif
39
37
#endif
40
38
 
41
 
#include <boost/thread/thread.hpp>
42
 
#include <boost/thread/mutex.hpp>
43
 
#include <boost/thread/tss.hpp>
44
 
 
45
 
namespace drizzled
46
 
{
47
 
namespace internal
48
 
{
49
 
 
50
 
boost::thread_specific_ptr<st_my_thread_var> THR_KEY_mysys;
51
 
boost::mutex THR_LOCK_threads;
 
39
uint32_t thd_lib_detected= 0;
 
40
 
 
41
#ifdef USE_TLS
 
42
pthread_key_t THR_KEY_mysys;
 
43
#else
 
44
pthread_key_t THR_KEY_mysys;
 
45
#endif /* USE_TLS */
 
46
pthread_mutex_t THR_LOCK_open;
 
47
pthread_mutex_t THR_LOCK_lock;
 
48
pthread_mutex_t THR_LOCK_charset;
 
49
pthread_mutex_t THR_LOCK_threads;
 
50
pthread_mutex_t THR_LOCK_time;
 
51
pthread_cond_t  THR_COND_threads;
 
52
uint32_t            THR_thread_count= 0;
 
53
uint32_t                my_thread_end_wait_time= 5;
 
54
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
 
55
pthread_mutexattr_t my_fast_mutexattr;
 
56
#endif
 
57
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
 
58
pthread_mutexattr_t my_errorcheck_mutexattr;
 
59
#endif
 
60
 
 
61
#ifdef TARGET_OS_LINUX
 
62
 
 
63
/*
 
64
  Dummy thread spawned in my_thread_global_init() below to avoid
 
65
  race conditions in NPTL pthread_exit code.
 
66
*/
 
67
 
 
68
extern "C"
 
69
void *
 
70
nptl_pthread_exit_hack_handler(void *arg __attribute((unused)))
 
71
{
 
72
  /* Do nothing! */
 
73
  pthread_exit(0);
 
74
  return 0;
 
75
}
 
76
 
 
77
#endif /* TARGET_OS_LINUX */
 
78
 
 
79
 
 
80
static uint32_t get_thread_lib(void);
52
81
 
53
82
/*
54
83
  initialize thread environment
63
92
 
64
93
bool my_thread_global_init(void)
65
94
{
 
95
  int pth_ret;
 
96
  thd_lib_detected= get_thread_lib();
 
97
 
 
98
  if ((pth_ret= pthread_key_create(&THR_KEY_mysys, NULL)) != 0)
 
99
  {
 
100
    fprintf(stderr,"Can't initialize threads: error %d\n", pth_ret);
 
101
    return 1;
 
102
  }
 
103
 
 
104
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
 
105
  /*
 
106
    Set mutex type to "fast" a.k.a "adaptive"
 
107
 
 
108
    In this case the thread may steal the mutex from some other thread
 
109
    that is waiting for the same mutex.  This will save us some
 
110
    context switches but may cause a thread to 'starve forever' while
 
111
    waiting for the mutex (not likely if the code within the mutex is
 
112
    short).
 
113
  */
 
114
  pthread_mutexattr_init(&my_fast_mutexattr);
 
115
  pthread_mutexattr_settype(&my_fast_mutexattr,
 
116
                            PTHREAD_MUTEX_ADAPTIVE_NP);
 
117
#endif
 
118
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
 
119
  /*
 
120
    Set mutex type to "errorcheck"
 
121
  */
 
122
  pthread_mutexattr_init(&my_errorcheck_mutexattr);
 
123
  pthread_mutexattr_settype(&my_errorcheck_mutexattr,
 
124
                            PTHREAD_MUTEX_ERRORCHECK);
 
125
#endif
 
126
 
 
127
  pthread_mutex_init(&THR_LOCK_open,MY_MUTEX_INIT_FAST);
 
128
  pthread_mutex_init(&THR_LOCK_lock,MY_MUTEX_INIT_FAST);
 
129
  pthread_mutex_init(&THR_LOCK_charset,MY_MUTEX_INIT_FAST);
 
130
  pthread_mutex_init(&THR_LOCK_threads,MY_MUTEX_INIT_FAST);
 
131
  pthread_mutex_init(&THR_LOCK_time,MY_MUTEX_INIT_FAST);
 
132
  pthread_cond_init(&THR_COND_threads, NULL);
66
133
  if (my_thread_init())
67
134
  {
68
135
    my_thread_global_end();                     /* Clean up */
74
141
 
75
142
void my_thread_global_end(void)
76
143
{
 
144
  struct timespec abstime;
 
145
  bool all_threads_killed= 1;
 
146
 
 
147
  set_timespec(abstime, my_thread_end_wait_time);
 
148
  pthread_mutex_lock(&THR_LOCK_threads);
 
149
  while (THR_thread_count > 0)
 
150
  {
 
151
    int error= pthread_cond_timedwait(&THR_COND_threads, &THR_LOCK_threads,
 
152
                                      &abstime);
 
153
    if (error == ETIMEDOUT || error == ETIME)
 
154
    {
 
155
#ifdef HAVE_PTHREAD_KILL
 
156
      /*
 
157
        We shouldn't give an error here, because if we don't have
 
158
        pthread_kill(), programs like mysqld can't ensure that all threads
 
159
        are killed when we enter here.
 
160
      */
 
161
      if (THR_thread_count)
 
162
        fprintf(stderr,
 
163
                "Error in my_thread_global_end(): %d threads didn't exit\n",
 
164
                THR_thread_count);
 
165
#endif
 
166
      all_threads_killed= 0;
 
167
      break;
 
168
    }
 
169
  }
 
170
  pthread_mutex_unlock(&THR_LOCK_threads);
 
171
 
 
172
  pthread_key_delete(THR_KEY_mysys);
 
173
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
 
174
  pthread_mutexattr_destroy(&my_fast_mutexattr);
 
175
#endif
 
176
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
 
177
  pthread_mutexattr_destroy(&my_errorcheck_mutexattr);
 
178
#endif
 
179
  pthread_mutex_destroy(&THR_LOCK_open);
 
180
  pthread_mutex_destroy(&THR_LOCK_lock);
 
181
  pthread_mutex_destroy(&THR_LOCK_time);
 
182
  pthread_mutex_destroy(&THR_LOCK_charset);
 
183
  if (all_threads_killed)
 
184
  {
 
185
    pthread_mutex_destroy(&THR_LOCK_threads);
 
186
    pthread_cond_destroy(&THR_COND_threads);
 
187
  }
77
188
}
78
189
 
79
 
static uint64_t thread_id= 0;
 
190
static my_thread_id thread_id= 0;
80
191
 
81
192
/*
82
193
  Allocate thread specific memory for the thread, used by mysys
84
195
  SYNOPSIS
85
196
    my_thread_init()
86
197
 
 
198
  NOTES
 
199
    We can't use mutex_locks here if we are using windows as
 
200
    we may have compiled the program with SAFE_MUTEX, in which
 
201
    case the checking of mutex_locks will not work until
 
202
    the pthread_self thread specific variable is initialized.
 
203
 
87
204
  RETURN
88
205
    0  ok
89
206
    1  Fatal error; mysys/dbug functions can't be used
91
208
 
92
209
bool my_thread_init(void)
93
210
{
94
 
  // We should mever see my_thread_init()  called twice
95
 
  if (THR_KEY_mysys.get())
96
 
    return 0;
97
 
 
98
 
  st_my_thread_var *tmp= new st_my_thread_var;
99
 
  if (tmp == NULL)
100
 
  {
101
 
    return true;
102
 
  }
103
 
  THR_KEY_mysys.reset(tmp);
104
 
 
105
 
  boost::mutex::scoped_lock scopedLock(THR_LOCK_threads);
 
211
  struct st_my_thread_var *tmp;
 
212
  bool error=0;
 
213
 
 
214
#ifdef EXTRA_DEBUG_THREADS
 
215
  fprintf(stderr,"my_thread_init(): thread_id: 0x%lx\n",
 
216
          (uint32_t) pthread_self());
 
217
#endif
 
218
 
 
219
  if (pthread_getspecific(THR_KEY_mysys))
 
220
  {
 
221
#ifdef EXTRA_DEBUG_THREADS
 
222
    fprintf(stderr,"my_thread_init() called more than once in thread 0x%lx\n",
 
223
            (long) pthread_self());
 
224
#endif
 
225
    goto end;
 
226
  }
 
227
  if (!(tmp= (struct st_my_thread_var *) calloc(1, sizeof(*tmp))))
 
228
  {
 
229
    error= 1;
 
230
    goto end;
 
231
  }
 
232
  pthread_setspecific(THR_KEY_mysys,tmp);
 
233
  tmp->pthread_self= pthread_self();
 
234
  pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST);
 
235
  pthread_cond_init(&tmp->suspend, NULL);
 
236
  tmp->init= 1;
 
237
 
 
238
  pthread_mutex_lock(&THR_LOCK_threads);
106
239
  tmp->id= ++thread_id;
 
240
  ++THR_thread_count;
 
241
  pthread_mutex_unlock(&THR_LOCK_threads);
107
242
 
108
 
  return false;
 
243
end:
 
244
  return error;
109
245
}
110
246
 
111
247
 
117
253
 
118
254
  NOTE
119
255
    This may be called multiple times for a thread.
120
 
    This happens for example when one calls 'server_init()'
121
 
    server_end() and then ends with a end().
 
256
    This happens for example when one calls 'mysql_server_init()'
 
257
    mysql_server_end() and then ends with a mysql_end().
122
258
*/
123
259
 
124
260
void my_thread_end(void)
125
261
{
 
262
  struct st_my_thread_var *tmp;
 
263
  tmp= (struct st_my_thread_var *)pthread_getspecific(THR_KEY_mysys);
 
264
 
 
265
#ifdef EXTRA_DEBUG_THREADS
 
266
  fprintf(stderr,"my_thread_end(): tmp: 0x%lx  pthread_self: 0x%lx  thread_id: %ld\n",
 
267
          (long) tmp, (long) pthread_self(), tmp ? (long) tmp->id : 0L);
 
268
#endif
 
269
  if (tmp && tmp->init)
 
270
  {
 
271
#if !defined(__bsdi__) && !defined(__OpenBSD__)
 
272
 /* bsdi and openbsd 3.5 dumps core here */
 
273
    pthread_cond_destroy(&tmp->suspend);
 
274
#endif
 
275
    pthread_mutex_destroy(&tmp->mutex);
 
276
#if defined(USE_TLS)
 
277
    free(tmp);
 
278
#else
 
279
    tmp->init= 0;
 
280
#endif
 
281
 
 
282
    /*
 
283
      Decrement counter for number of running threads. We are using this
 
284
      in my_thread_global_end() to wait until all threads have called
 
285
      my_thread_end and thus freed all memory they have allocated in
 
286
      my_thread_init()
 
287
    */
 
288
    pthread_mutex_lock(&THR_LOCK_threads);
 
289
    assert(THR_thread_count != 0);
 
290
    if (--THR_thread_count == 0)
 
291
      pthread_cond_signal(&THR_COND_threads);
 
292
   pthread_mutex_unlock(&THR_LOCK_threads);
 
293
  }
 
294
  /* The following free has to be done, even if my_thread_var() is 0 */
 
295
#if defined(USE_TLS)
 
296
  pthread_setspecific(THR_KEY_mysys,0);
 
297
#endif
126
298
}
127
299
 
128
300
struct st_my_thread_var *_my_thread_var(void)
129
301
{
130
 
  return THR_KEY_mysys.get();
131
 
}
132
 
 
133
 
} /* namespace internal */
134
 
} /* namespace drizzled */
 
302
  struct st_my_thread_var *tmp= (struct st_my_thread_var*)pthread_getspecific(THR_KEY_mysys);
 
303
#if defined(USE_TLS)
 
304
  /* This can only happen in a .DLL */
 
305
  if (!tmp)
 
306
  {
 
307
    my_thread_init();
 
308
    tmp=(struct st_my_thread_var*)pthread_getspecific(THR_KEY_mysys);
 
309
  }
 
310
#endif
 
311
  return tmp;
 
312
}
 
313
 
 
314
 
 
315
/****************************************************************************
 
316
  Get name of current thread.
 
317
****************************************************************************/
 
318
 
 
319
my_thread_id my_thread_dbug_id()
 
320
{
 
321
  return my_thread_var->id;
 
322
}
 
323
 
 
324
static uint32_t get_thread_lib(void)
 
325
{
 
326
#ifdef _CS_GNU_LIBPTHREAD_VERSION
 
327
  char buff[64];
 
328
 
 
329
  confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff));
 
330
 
 
331
  if (!strncasecmp(buff, "NPTL", 4))
 
332
    return THD_LIB_NPTL;
 
333
  if (!strncasecmp(buff, "linuxthreads", 12))
 
334
    return THD_LIB_LT;
 
335
#endif
 
336
  return THD_LIB_OTHER;
 
337
}