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 */
17
17
Functions to handle initializating and allocationg of all mysys & debug
23
#include "drizzled/internal/my_sys.h"
24
#include "drizzled/internal/thread_var.h"
25
#include "drizzled/internal/m_string.h"
21
#include "mysys_priv.h"
22
#include <mystrings/m_string.h>
28
23
#include <signal.h>
30
25
#if TIME_WITH_SYS_TIME
41
#include <boost/thread/thread.hpp>
42
#include <boost/thread/mutex.hpp>
43
#include <boost/thread/tss.hpp>
50
boost::thread_specific_ptr<st_my_thread_var> THR_KEY_mysys;
51
boost::mutex THR_LOCK_threads;
36
uint32_t thd_lib_detected= 0;
39
pthread_key_t THR_KEY_mysys;
41
pthread_key_t THR_KEY_mysys;
43
pthread_mutex_t THR_LOCK_malloc,THR_LOCK_open,
44
THR_LOCK_lock,THR_LOCK_isam,THR_LOCK_myisam,THR_LOCK_heap,
45
THR_LOCK_net, THR_LOCK_charset, THR_LOCK_threads, THR_LOCK_time;
46
pthread_cond_t THR_COND_threads;
47
uint32_t THR_thread_count= 0;
48
uint32_t my_thread_end_wait_time= 5;
49
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
50
pthread_mutex_t LOCK_localtime_r;
52
#ifndef HAVE_GETHOSTBYNAME_R
53
pthread_mutex_t LOCK_gethostbyname_r;
55
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
56
pthread_mutexattr_t my_fast_mutexattr;
58
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
59
pthread_mutexattr_t my_errorcheck_mutexattr;
62
#ifdef TARGET_OS_LINUX
65
Dummy thread spawned in my_thread_global_init() below to avoid
66
race conditions in NPTL pthread_exit code.
69
static pthread_handler_t
70
nptl_pthread_exit_hack_handler(void *arg __attribute((unused)))
77
#endif /* TARGET_OS_LINUX */
80
static uint32_t get_thread_lib(void);
54
83
initialize thread environment
64
93
bool my_thread_global_init(void)
96
thd_lib_detected= get_thread_lib();
98
if ((pth_ret= pthread_key_create(&THR_KEY_mysys, NULL)) != 0)
100
fprintf(stderr,"Can't initialize threads: error %d\n", pth_ret);
104
#ifdef TARGET_OS_LINUX
106
BUG#24507: Race conditions inside current NPTL pthread_exit()
109
To avoid a possible segmentation fault during concurrent
110
executions of pthread_exit(), a dummy thread is spawned which
111
initializes internal variables of pthread lib. See bug description
112
for a full explanation.
114
TODO: Remove this code when fixed versions of glibc6 are in common
117
if (thd_lib_detected == THD_LIB_NPTL)
119
pthread_t dummy_thread;
120
pthread_attr_t dummy_thread_attr;
122
pthread_attr_init(&dummy_thread_attr);
123
pthread_attr_setdetachstate(&dummy_thread_attr, PTHREAD_CREATE_DETACHED);
125
pthread_create(&dummy_thread,&dummy_thread_attr,
126
nptl_pthread_exit_hack_handler, NULL);
128
#endif /* TARGET_OS_LINUX */
130
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
132
Set mutex type to "fast" a.k.a "adaptive"
134
In this case the thread may steal the mutex from some other thread
135
that is waiting for the same mutex. This will save us some
136
context switches but may cause a thread to 'starve forever' while
137
waiting for the mutex (not likely if the code within the mutex is
140
pthread_mutexattr_init(&my_fast_mutexattr);
141
pthread_mutexattr_settype(&my_fast_mutexattr,
142
PTHREAD_MUTEX_ADAPTIVE_NP);
144
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
146
Set mutex type to "errorcheck"
148
pthread_mutexattr_init(&my_errorcheck_mutexattr);
149
pthread_mutexattr_settype(&my_errorcheck_mutexattr,
150
PTHREAD_MUTEX_ERRORCHECK);
153
pthread_mutex_init(&THR_LOCK_malloc,MY_MUTEX_INIT_FAST);
154
pthread_mutex_init(&THR_LOCK_open,MY_MUTEX_INIT_FAST);
155
pthread_mutex_init(&THR_LOCK_lock,MY_MUTEX_INIT_FAST);
156
pthread_mutex_init(&THR_LOCK_isam,MY_MUTEX_INIT_SLOW);
157
pthread_mutex_init(&THR_LOCK_myisam,MY_MUTEX_INIT_SLOW);
158
pthread_mutex_init(&THR_LOCK_heap,MY_MUTEX_INIT_FAST);
159
pthread_mutex_init(&THR_LOCK_net,MY_MUTEX_INIT_FAST);
160
pthread_mutex_init(&THR_LOCK_charset,MY_MUTEX_INIT_FAST);
161
pthread_mutex_init(&THR_LOCK_threads,MY_MUTEX_INIT_FAST);
162
pthread_mutex_init(&THR_LOCK_time,MY_MUTEX_INIT_FAST);
163
pthread_cond_init(&THR_COND_threads, NULL);
164
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
165
pthread_mutex_init(&LOCK_localtime_r,MY_MUTEX_INIT_SLOW);
167
#ifndef HAVE_GETHOSTBYNAME_R
168
pthread_mutex_init(&LOCK_gethostbyname_r,MY_MUTEX_INIT_SLOW);
66
170
if (my_thread_init())
68
172
my_thread_global_end(); /* Clean up */
75
179
void my_thread_global_end(void)
181
struct timespec abstime;
182
bool all_threads_killed= 1;
184
set_timespec(abstime, my_thread_end_wait_time);
185
pthread_mutex_lock(&THR_LOCK_threads);
186
while (THR_thread_count > 0)
188
int error= pthread_cond_timedwait(&THR_COND_threads, &THR_LOCK_threads,
190
if (error == ETIMEDOUT || error == ETIME)
192
#ifdef HAVE_PTHREAD_KILL
194
We shouldn't give an error here, because if we don't have
195
pthread_kill(), programs like mysqld can't ensure that all threads
196
are killed when we enter here.
198
if (THR_thread_count)
200
"Error in my_thread_global_end(): %d threads didn't exit\n",
203
all_threads_killed= 0;
207
pthread_mutex_unlock(&THR_LOCK_threads);
209
pthread_key_delete(THR_KEY_mysys);
210
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
211
pthread_mutexattr_destroy(&my_fast_mutexattr);
213
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
214
pthread_mutexattr_destroy(&my_errorcheck_mutexattr);
216
pthread_mutex_destroy(&THR_LOCK_malloc);
217
pthread_mutex_destroy(&THR_LOCK_open);
218
pthread_mutex_destroy(&THR_LOCK_lock);
219
pthread_mutex_destroy(&THR_LOCK_isam);
220
pthread_mutex_destroy(&THR_LOCK_myisam);
221
pthread_mutex_destroy(&THR_LOCK_heap);
222
pthread_mutex_destroy(&THR_LOCK_net);
223
pthread_mutex_destroy(&THR_LOCK_time);
224
pthread_mutex_destroy(&THR_LOCK_charset);
225
if (all_threads_killed)
227
pthread_mutex_destroy(&THR_LOCK_threads);
228
pthread_cond_destroy(&THR_COND_threads);
230
#if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
231
pthread_mutex_destroy(&LOCK_localtime_r);
233
#ifndef HAVE_GETHOSTBYNAME_R
234
pthread_mutex_destroy(&LOCK_gethostbyname_r);
79
static uint64_t thread_id= 0;
238
static my_thread_id thread_id= 0;
82
241
Allocate thread specific memory for the thread, used by mysys
92
257
bool my_thread_init(void)
94
// We should mever see my_thread_init() called twice
95
if (THR_KEY_mysys.get())
98
st_my_thread_var *tmp= new st_my_thread_var;
103
THR_KEY_mysys.reset(tmp);
105
boost::mutex::scoped_lock scopedLock(THR_LOCK_threads);
259
struct st_my_thread_var *tmp;
262
#ifdef EXTRA_DEBUG_THREADS
263
fprintf(stderr,"my_thread_init(): thread_id: 0x%lx\n",
264
(uint32_t) pthread_self());
267
if (pthread_getspecific(THR_KEY_mysys))
269
#ifdef EXTRA_DEBUG_THREADS
270
fprintf(stderr,"my_thread_init() called more than once in thread 0x%lx\n",
271
(long) pthread_self());
275
if (!(tmp= (struct st_my_thread_var *) calloc(1, sizeof(*tmp))))
280
pthread_setspecific(THR_KEY_mysys,tmp);
281
tmp->pthread_self= pthread_self();
282
pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST);
283
pthread_cond_init(&tmp->suspend, NULL);
286
pthread_mutex_lock(&THR_LOCK_threads);
106
287
tmp->id= ++thread_id;
289
pthread_mutex_unlock(&THR_LOCK_threads);
119
303
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().
304
This happens for example when one calls 'mysql_server_init()'
305
mysql_server_end() and then ends with a mysql_end().
124
308
void my_thread_end(void)
310
struct st_my_thread_var *tmp;
311
tmp= (struct st_my_thread_var *)pthread_getspecific(THR_KEY_mysys);
313
#ifdef EXTRA_DEBUG_THREADS
314
fprintf(stderr,"my_thread_end(): tmp: 0x%lx pthread_self: 0x%lx thread_id: %ld\n",
315
(long) tmp, (long) pthread_self(), tmp ? (long) tmp->id : 0L);
317
if (tmp && tmp->init)
319
#if !defined(__bsdi__) && !defined(__OpenBSD__)
320
/* bsdi and openbsd 3.5 dumps core here */
321
pthread_cond_destroy(&tmp->suspend);
323
pthread_mutex_destroy(&tmp->mutex);
331
Decrement counter for number of running threads. We are using this
332
in my_thread_global_end() to wait until all threads have called
333
my_thread_end and thus freed all memory they have allocated in
336
pthread_mutex_lock(&THR_LOCK_threads);
337
assert(THR_thread_count != 0);
338
if (--THR_thread_count == 0)
339
pthread_cond_signal(&THR_COND_threads);
340
pthread_mutex_unlock(&THR_LOCK_threads);
342
/* The following free has to be done, even if my_thread_var() is 0 */
344
pthread_setspecific(THR_KEY_mysys,0);
128
348
struct st_my_thread_var *_my_thread_var(void)
130
return THR_KEY_mysys.get();
133
} /* namespace internal */
134
} /* namespace drizzled */
350
struct st_my_thread_var *tmp= (struct st_my_thread_var*)pthread_getspecific(THR_KEY_mysys);
352
/* This can only happen in a .DLL */
356
tmp=(struct st_my_thread_var*)pthread_getspecific(THR_KEY_mysys);
363
/****************************************************************************
364
Get name of current thread.
365
****************************************************************************/
367
my_thread_id my_thread_dbug_id()
369
return my_thread_var->id;
372
static uint32_t get_thread_lib(void)
374
#ifdef _CS_GNU_LIBPTHREAD_VERSION
377
confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff));
379
if (!strncasecmp(buff, "NPTL", 4))
381
if (!strncasecmp(buff, "linuxthreads", 12))
384
return THD_LIB_OTHER;