~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/internal/my_thr_init.cc

  • Committer: Monty Taylor
  • Date: 2010-03-02 19:10:25 UTC
  • mto: (1317.1.8)
  • mto: This revision was merged to the branch mainline in revision 1322.
  • Revision ID: mordred@inaugust.com-20100302191025-zoxjz4xwkoa6160h
Prevent unauthorized users from changing schema.

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
21
21
#include "config.h"
22
22
 
23
23
#include "drizzled/internal/my_sys.h"
24
 
#include "drizzled/internal/thread_var.h"
 
24
#include "drizzled/internal/my_pthread.h"
25
25
#include "drizzled/internal/m_string.h"
26
26
 
27
27
#include <cstdio>
38
38
# endif
39
39
#endif
40
40
 
41
 
#include <boost/thread/thread.hpp>
42
 
#include <boost/thread/mutex.hpp>
43
 
#include <boost/thread/tss.hpp>
44
 
 
45
41
namespace drizzled
46
42
{
47
43
namespace internal
48
44
{
49
45
 
50
 
boost::thread_specific_ptr<st_my_thread_var> THR_KEY_mysys;
51
 
boost::mutex THR_LOCK_threads;
 
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);
52
59
 
53
60
/*
54
61
  initialize thread environment
63
70
 
64
71
bool my_thread_global_init(void)
65
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);
66
100
  if (my_thread_init())
67
101
  {
68
102
    my_thread_global_end();                     /* Clean up */
74
108
 
75
109
void my_thread_global_end(void)
76
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
  }
77
147
}
78
148
 
79
149
static uint64_t thread_id= 0;
91
161
 
92
162
bool my_thread_init(void)
93
163
{
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;
 
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)));
99
181
  if (tmp == NULL)
100
182
  {
101
 
    return true;
 
183
    error= 1;
 
184
    goto end;
102
185
  }
103
 
  THR_KEY_mysys.reset(tmp);
 
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;
104
191
 
105
 
  boost::mutex::scoped_lock scopedLock(THR_LOCK_threads);
 
192
  pthread_mutex_lock(&THR_LOCK_threads);
106
193
  tmp->id= ++thread_id;
 
194
  ++THR_thread_count;
 
195
  pthread_mutex_unlock(&THR_LOCK_threads);
107
196
 
108
 
  return false;
 
197
end:
 
198
  return error;
109
199
}
110
200
 
111
201
 
117
207
 
118
208
  NOTE
119
209
    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().
 
210
    This happens for example when one calls 'mysql_server_init()'
 
211
    mysql_server_end() and then ends with a mysql_end().
122
212
*/
123
213
 
124
214
void my_thread_end(void)
125
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
  }
126
244
}
127
245
 
128
246
struct st_my_thread_var *_my_thread_var(void)
129
247
{
130
 
  return THR_KEY_mysys.get();
 
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;
131
265
}
132
266
 
133
267
} /* namespace internal */