~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/my_thr_init.cc

  • Committer: Brian Aker
  • Date: 2009-12-06 01:55:53 UTC
  • mfrom: (1238.1.5 push)
  • Revision ID: brian@gaz-20091206015553-cva833q4gvwj11ob
Bundle for staging.

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