~ubuntu-branches/ubuntu/trusty/drizzle/trusty

« back to all changes in this revision

Viewing changes to drizzled/internal/my_thr_init.cc

  • Committer: Bazaar Package Importer
  • Author(s): Monty Taylor
  • Date: 2010-03-18 12:12:31 UTC
  • Revision ID: james.westby@ubuntu.com-20100318121231-k6g1xe6cshbwa0f8
Tags: upstream-2010.03.1347
ImportĀ upstreamĀ versionĀ 2010.03.1347

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
21
#include "config.h"
 
22
 
 
23
#include "drizzled/internal/my_sys.h"
 
24
#include "drizzled/internal/my_pthread.h"
 
25
#include "drizzled/internal/m_string.h"
 
26
 
 
27
#include <cstdio>
 
28
#include <signal.h>
 
29
 
 
30
#if TIME_WITH_SYS_TIME
 
31
# include <sys/time.h>
 
32
# include <time.h>
 
33
#else
 
34
# if HAVE_SYS_TIME_H
 
35
#  include <sys/time.h>
 
36
# else
 
37
#  include <time.h>
 
38
# endif
 
39
#endif
 
40
 
 
41
namespace drizzled
 
42
{
 
43
namespace internal
 
44
{
 
45
 
 
46
uint32_t thd_lib_detected= 0;
 
47
 
 
48
pthread_key_t THR_KEY_mysys;
 
49
pthread_mutex_t THR_LOCK_lock;
 
50
pthread_mutex_t THR_LOCK_threads;
 
51
pthread_cond_t  THR_COND_threads;
 
52
uint32_t            THR_thread_count= 0;
 
53
static 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
 
 
58
static uint32_t get_thread_lib(void);
 
59
 
 
60
/*
 
61
  initialize thread environment
 
62
 
 
63
  SYNOPSIS
 
64
    my_thread_global_init()
 
65
 
 
66
  RETURN
 
67
    0  ok
 
68
    1  error (Couldn't create THR_KEY_mysys)
 
69
*/
 
70
 
 
71
bool my_thread_global_init(void)
 
72
{
 
73
  int pth_ret;
 
74
  thd_lib_detected= get_thread_lib();
 
75
 
 
76
  if ((pth_ret= pthread_key_create(&THR_KEY_mysys, NULL)) != 0)
 
77
  {
 
78
    fprintf(stderr,"Can't initialize threads: error %d\n", pth_ret);
 
79
    return 1;
 
80
  }
 
81
 
 
82
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
 
83
  /*
 
84
    Set mutex type to "fast" a.k.a "adaptive"
 
85
 
 
86
    In this case the thread may steal the mutex from some other thread
 
87
    that is waiting for the same mutex.  This will save us some
 
88
    context switches but may cause a thread to 'starve forever' while
 
89
    waiting for the mutex (not likely if the code within the mutex is
 
90
    short).
 
91
  */
 
92
  pthread_mutexattr_init(&my_fast_mutexattr);
 
93
  pthread_mutexattr_settype(&my_fast_mutexattr,
 
94
                            PTHREAD_MUTEX_ADAPTIVE_NP);
 
95
#endif
 
96
 
 
97
  pthread_mutex_init(&THR_LOCK_lock,MY_MUTEX_INIT_FAST);
 
98
  pthread_mutex_init(&THR_LOCK_threads,MY_MUTEX_INIT_FAST);
 
99
  pthread_cond_init(&THR_COND_threads, NULL);
 
100
  if (my_thread_init())
 
101
  {
 
102
    my_thread_global_end();                     /* Clean up */
 
103
    return 1;
 
104
  }
 
105
  return 0;
 
106
}
 
107
 
 
108
 
 
109
void my_thread_global_end(void)
 
110
{
 
111
  struct timespec abstime;
 
112
  bool all_threads_killed= 1;
 
113
 
 
114
  set_timespec(abstime, my_thread_end_wait_time);
 
115
  pthread_mutex_lock(&THR_LOCK_threads);
 
116
  while (THR_thread_count > 0)
 
117
  {
 
118
    int error= pthread_cond_timedwait(&THR_COND_threads, &THR_LOCK_threads,
 
119
                                      &abstime);
 
120
    if (error == ETIMEDOUT || error == ETIME)
 
121
    {
 
122
      /*
 
123
        We shouldn't give an error here, because if we don't have
 
124
        pthread_kill(), programs like mysqld can't ensure that all threads
 
125
        are killed when we enter here.
 
126
      */
 
127
      if (THR_thread_count)
 
128
        fprintf(stderr,
 
129
                "Error in my_thread_global_end(): %d threads didn't exit\n",
 
130
                THR_thread_count);
 
131
      all_threads_killed= 0;
 
132
      break;
 
133
    }
 
134
  }
 
135
  pthread_mutex_unlock(&THR_LOCK_threads);
 
136
 
 
137
  pthread_key_delete(THR_KEY_mysys);
 
138
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
 
139
  pthread_mutexattr_destroy(&my_fast_mutexattr);
 
140
#endif
 
141
  pthread_mutex_destroy(&THR_LOCK_lock);
 
142
  if (all_threads_killed)
 
143
  {
 
144
    pthread_mutex_destroy(&THR_LOCK_threads);
 
145
    pthread_cond_destroy(&THR_COND_threads);
 
146
  }
 
147
}
 
148
 
 
149
static uint64_t thread_id= 0;
 
150
 
 
151
/*
 
152
  Allocate thread specific memory for the thread, used by mysys
 
153
 
 
154
  SYNOPSIS
 
155
    my_thread_init()
 
156
 
 
157
  RETURN
 
158
    0  ok
 
159
    1  Fatal error; mysys/dbug functions can't be used
 
160
*/
 
161
 
 
162
bool my_thread_init(void)
 
163
{
 
164
  bool error=0;
 
165
  st_my_thread_var *tmp= NULL;
 
166
 
 
167
#ifdef EXTRA_DEBUG_THREADS
 
168
  fprintf(stderr,"my_thread_init(): thread_id: 0x%lx\n",
 
169
          (uint32_t) pthread_self());
 
170
#endif
 
171
 
 
172
  if (pthread_getspecific(THR_KEY_mysys))
 
173
  {
 
174
#ifdef EXTRA_DEBUG_THREADS
 
175
    fprintf(stderr,"my_thread_init() called more than once in thread 0x%lx\n",
 
176
            (long) pthread_self());
 
177
#endif
 
178
    goto end;
 
179
  }
 
180
  tmp= static_cast<st_my_thread_var *>(calloc(1, sizeof(*tmp)));
 
181
  if (tmp == NULL)
 
182
  {
 
183
    error= 1;
 
184
    goto end;
 
185
  }
 
186
  pthread_setspecific(THR_KEY_mysys,tmp);
 
187
  tmp->pthread_self= pthread_self();
 
188
  pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST);
 
189
  pthread_cond_init(&tmp->suspend, NULL);
 
190
  tmp->init= 1;
 
191
 
 
192
  pthread_mutex_lock(&THR_LOCK_threads);
 
193
  tmp->id= ++thread_id;
 
194
  ++THR_thread_count;
 
195
  pthread_mutex_unlock(&THR_LOCK_threads);
 
196
 
 
197
end:
 
198
  return error;
 
199
}
 
200
 
 
201
 
 
202
/*
 
203
  Deallocate memory used by the thread for book-keeping
 
204
 
 
205
  SYNOPSIS
 
206
    my_thread_end()
 
207
 
 
208
  NOTE
 
209
    This may be called multiple times for a thread.
 
210
    This happens for example when one calls 'mysql_server_init()'
 
211
    mysql_server_end() and then ends with a mysql_end().
 
212
*/
 
213
 
 
214
void my_thread_end(void)
 
215
{
 
216
  st_my_thread_var *tmp=
 
217
    static_cast<st_my_thread_var *>(pthread_getspecific(THR_KEY_mysys));
 
218
 
 
219
#ifdef EXTRA_DEBUG_THREADS
 
220
  fprintf(stderr,"my_thread_end(): tmp: 0x%lx  pthread_self: 0x%lx  thread_id: %ld\n",
 
221
          (long) tmp, (long) pthread_self(), tmp ? (long) tmp->id : 0L);
 
222
#endif
 
223
  if (tmp && tmp->init)
 
224
  {
 
225
#if !defined(__bsdi__) && !defined(__OpenBSD__)
 
226
 /* bsdi and openbsd 3.5 dumps core here */
 
227
    pthread_cond_destroy(&tmp->suspend);
 
228
#endif
 
229
    pthread_mutex_destroy(&tmp->mutex);
 
230
    free(tmp);
 
231
 
 
232
    /*
 
233
      Decrement counter for number of running threads. We are using this
 
234
      in my_thread_global_end() to wait until all threads have called
 
235
      my_thread_end and thus freed all memory they have allocated in
 
236
      my_thread_init()
 
237
    */
 
238
    pthread_mutex_lock(&THR_LOCK_threads);
 
239
    assert(THR_thread_count != 0);
 
240
    if (--THR_thread_count == 0)
 
241
      pthread_cond_signal(&THR_COND_threads);
 
242
    pthread_mutex_unlock(&THR_LOCK_threads);
 
243
  }
 
244
}
 
245
 
 
246
struct st_my_thread_var *_my_thread_var(void)
 
247
{
 
248
  struct st_my_thread_var *tmp= (struct st_my_thread_var*)pthread_getspecific(THR_KEY_mysys);
 
249
  return tmp;
 
250
}
 
251
 
 
252
static uint32_t get_thread_lib(void)
 
253
{
 
254
#ifdef _CS_GNU_LIBPTHREAD_VERSION
 
255
  char buff[64];
 
256
 
 
257
  confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff));
 
258
 
 
259
  if (!strncasecmp(buff, "NPTL", 4))
 
260
    return THD_LIB_NPTL;
 
261
  if (!strncasecmp(buff, "linuxthreads", 12))
 
262
    return THD_LIB_LT;
 
263
#endif
 
264
  return THD_LIB_OTHER;
 
265
}
 
266
 
 
267
} /* namespace internal */
 
268
} /* namespace drizzled */