1
/* Copyright (C) 2000 MySQL AB
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.
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.
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 */
17
Functions to handle initializating and allocationg of all mysys & debug
23
#include "drizzled/internal/my_sys.h"
24
#include "drizzled/internal/my_pthread.h"
25
#include "drizzled/internal/m_string.h"
30
#if TIME_WITH_SYS_TIME
31
# include <sys/time.h>
35
# include <sys/time.h>
46
uint32_t thd_lib_detected= 0;
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;
58
static uint32_t get_thread_lib(void);
61
initialize thread environment
64
my_thread_global_init()
68
1 error (Couldn't create THR_KEY_mysys)
71
bool my_thread_global_init(void)
74
thd_lib_detected= get_thread_lib();
76
if ((pth_ret= pthread_key_create(&THR_KEY_mysys, NULL)) != 0)
78
fprintf(stderr,"Can't initialize threads: error %d\n", pth_ret);
82
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
84
Set mutex type to "fast" a.k.a "adaptive"
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
92
pthread_mutexattr_init(&my_fast_mutexattr);
93
pthread_mutexattr_settype(&my_fast_mutexattr,
94
PTHREAD_MUTEX_ADAPTIVE_NP);
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())
102
my_thread_global_end(); /* Clean up */
109
void my_thread_global_end(void)
111
struct timespec abstime;
112
bool all_threads_killed= 1;
114
set_timespec(abstime, my_thread_end_wait_time);
115
pthread_mutex_lock(&THR_LOCK_threads);
116
while (THR_thread_count > 0)
118
int error= pthread_cond_timedwait(&THR_COND_threads, &THR_LOCK_threads,
120
if (error == ETIMEDOUT || error == ETIME)
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.
127
if (THR_thread_count)
129
"Error in my_thread_global_end(): %d threads didn't exit\n",
131
all_threads_killed= 0;
135
pthread_mutex_unlock(&THR_LOCK_threads);
137
pthread_key_delete(THR_KEY_mysys);
138
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
139
pthread_mutexattr_destroy(&my_fast_mutexattr);
141
pthread_mutex_destroy(&THR_LOCK_lock);
142
if (all_threads_killed)
144
pthread_mutex_destroy(&THR_LOCK_threads);
145
pthread_cond_destroy(&THR_COND_threads);
149
static uint64_t thread_id= 0;
152
Allocate thread specific memory for the thread, used by mysys
159
1 Fatal error; mysys/dbug functions can't be used
162
bool my_thread_init(void)
165
st_my_thread_var *tmp= NULL;
167
#ifdef EXTRA_DEBUG_THREADS
168
fprintf(stderr,"my_thread_init(): thread_id: 0x%lx\n",
169
(uint32_t) pthread_self());
172
if (pthread_getspecific(THR_KEY_mysys))
174
#ifdef EXTRA_DEBUG_THREADS
175
fprintf(stderr,"my_thread_init() called more than once in thread 0x%lx\n",
176
(long) pthread_self());
180
tmp= static_cast<st_my_thread_var *>(calloc(1, sizeof(*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);
192
pthread_mutex_lock(&THR_LOCK_threads);
193
tmp->id= ++thread_id;
195
pthread_mutex_unlock(&THR_LOCK_threads);
203
Deallocate memory used by the thread for book-keeping
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().
214
void my_thread_end(void)
216
st_my_thread_var *tmp=
217
static_cast<st_my_thread_var *>(pthread_getspecific(THR_KEY_mysys));
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);
223
if (tmp && tmp->init)
225
#if !defined(__bsdi__) && !defined(__OpenBSD__)
226
/* bsdi and openbsd 3.5 dumps core here */
227
pthread_cond_destroy(&tmp->suspend);
229
pthread_mutex_destroy(&tmp->mutex);
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
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);
246
struct st_my_thread_var *_my_thread_var(void)
248
struct st_my_thread_var *tmp= (struct st_my_thread_var*)pthread_getspecific(THR_KEY_mysys);
252
static uint32_t get_thread_lib(void)
254
#ifdef _CS_GNU_LIBPTHREAD_VERSION
257
confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff));
259
if (!strncasecmp(buff, "NPTL", 4))
261
if (!strncasecmp(buff, "linuxthreads", 12))
264
return THD_LIB_OTHER;
267
} /* namespace internal */
268
} /* namespace drizzled */