~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/my_thr_init.cc

  • Committer: Jay Pipes
  • Date: 2009-09-15 21:01:42 UTC
  • mto: (1126.2.5 merge)
  • mto: This revision was merged to the branch mainline in revision 1128.
  • Revision ID: jpipes@serialcoder-20090915210142-x8mwiqn1q0vzjspp
Moves Alter_info out into its own header and source file, cleans up some related include mess in sql_lex.h, and renames Alter_info to AlterInfo.

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