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/mysys_priv.h"
22
#include <mysys/my_pthread.h>
23
#include <mystrings/m_string.h>
28
26
#include <signal.h>
30
28
#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;
39
uint32_t thd_lib_detected= 0;
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;
50
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
51
pthread_mutexattr_t my_errorcheck_mutexattr;
54
#ifdef TARGET_OS_LINUX
57
Dummy thread spawned in my_thread_global_init() below to avoid
58
race conditions in NPTL pthread_exit code.
63
nptl_pthread_exit_hack_handler(void *arg __attribute((unused)))
70
#endif /* TARGET_OS_LINUX */
73
static uint32_t get_thread_lib(void);
54
76
initialize thread environment
64
86
bool my_thread_global_init(void)
89
thd_lib_detected= get_thread_lib();
91
if ((pth_ret= pthread_key_create(&THR_KEY_mysys, NULL)) != 0)
93
fprintf(stderr,"Can't initialize threads: error %d\n", pth_ret);
97
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
99
Set mutex type to "fast" a.k.a "adaptive"
101
In this case the thread may steal the mutex from some other thread
102
that is waiting for the same mutex. This will save us some
103
context switches but may cause a thread to 'starve forever' while
104
waiting for the mutex (not likely if the code within the mutex is
107
pthread_mutexattr_init(&my_fast_mutexattr);
108
pthread_mutexattr_settype(&my_fast_mutexattr,
109
PTHREAD_MUTEX_ADAPTIVE_NP);
111
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
113
Set mutex type to "errorcheck"
115
pthread_mutexattr_init(&my_errorcheck_mutexattr);
116
pthread_mutexattr_settype(&my_errorcheck_mutexattr,
117
PTHREAD_MUTEX_ERRORCHECK);
120
pthread_mutex_init(&THR_LOCK_lock,MY_MUTEX_INIT_FAST);
121
pthread_mutex_init(&THR_LOCK_threads,MY_MUTEX_INIT_FAST);
122
pthread_cond_init(&THR_COND_threads, NULL);
66
123
if (my_thread_init())
68
125
my_thread_global_end(); /* Clean up */
75
132
void my_thread_global_end(void)
134
struct timespec abstime;
135
bool all_threads_killed= 1;
137
set_timespec(abstime, my_thread_end_wait_time);
138
pthread_mutex_lock(&THR_LOCK_threads);
139
while (THR_thread_count > 0)
141
int error= pthread_cond_timedwait(&THR_COND_threads, &THR_LOCK_threads,
143
if (error == ETIMEDOUT || error == ETIME)
146
We shouldn't give an error here, because if we don't have
147
pthread_kill(), programs like mysqld can't ensure that all threads
148
are killed when we enter here.
150
if (THR_thread_count)
152
"Error in my_thread_global_end(): %d threads didn't exit\n",
154
all_threads_killed= 0;
158
pthread_mutex_unlock(&THR_LOCK_threads);
160
pthread_key_delete(THR_KEY_mysys);
161
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
162
pthread_mutexattr_destroy(&my_fast_mutexattr);
164
#ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
165
pthread_mutexattr_destroy(&my_errorcheck_mutexattr);
167
pthread_mutex_destroy(&THR_LOCK_lock);
168
if (all_threads_killed)
170
pthread_mutex_destroy(&THR_LOCK_threads);
171
pthread_cond_destroy(&THR_COND_threads);
79
static uint64_t thread_id= 0;
175
static my_thread_id thread_id= 0;
82
178
Allocate thread specific memory for the thread, used by mysys
92
188
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);
190
struct st_my_thread_var *tmp;
193
#ifdef EXTRA_DEBUG_THREADS
194
fprintf(stderr,"my_thread_init(): thread_id: 0x%lx\n",
195
(uint32_t) pthread_self());
198
if (pthread_getspecific(THR_KEY_mysys))
200
#ifdef EXTRA_DEBUG_THREADS
201
fprintf(stderr,"my_thread_init() called more than once in thread 0x%lx\n",
202
(long) pthread_self());
206
if (!(tmp= (struct st_my_thread_var *) calloc(1, sizeof(*tmp))))
211
pthread_setspecific(THR_KEY_mysys,tmp);
212
tmp->pthread_self= pthread_self();
213
pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST);
214
pthread_cond_init(&tmp->suspend, NULL);
217
pthread_mutex_lock(&THR_LOCK_threads);
106
218
tmp->id= ++thread_id;
220
pthread_mutex_unlock(&THR_LOCK_threads);
119
234
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().
235
This happens for example when one calls 'mysql_server_init()'
236
mysql_server_end() and then ends with a mysql_end().
124
239
void my_thread_end(void)
241
struct st_my_thread_var *tmp;
242
tmp= (struct st_my_thread_var *)pthread_getspecific(THR_KEY_mysys);
244
#ifdef EXTRA_DEBUG_THREADS
245
fprintf(stderr,"my_thread_end(): tmp: 0x%lx pthread_self: 0x%lx thread_id: %ld\n",
246
(long) tmp, (long) pthread_self(), tmp ? (long) tmp->id : 0L);
248
if (tmp && tmp->init)
250
#if !defined(__bsdi__) && !defined(__OpenBSD__)
251
/* bsdi and openbsd 3.5 dumps core here */
252
pthread_cond_destroy(&tmp->suspend);
254
pthread_mutex_destroy(&tmp->mutex);
258
Decrement counter for number of running threads. We are using this
259
in my_thread_global_end() to wait until all threads have called
260
my_thread_end and thus freed all memory they have allocated in
263
pthread_mutex_lock(&THR_LOCK_threads);
264
assert(THR_thread_count != 0);
265
if (--THR_thread_count == 0)
266
pthread_cond_signal(&THR_COND_threads);
267
pthread_mutex_unlock(&THR_LOCK_threads);
128
271
struct st_my_thread_var *_my_thread_var(void)
130
return THR_KEY_mysys.get();
133
} /* namespace internal */
134
} /* namespace drizzled */
273
struct st_my_thread_var *tmp= (struct st_my_thread_var*)pthread_getspecific(THR_KEY_mysys);
278
/****************************************************************************
279
Get name of current thread.
280
****************************************************************************/
282
my_thread_id my_thread_dbug_id()
284
return my_thread_var->id;
287
static uint32_t get_thread_lib(void)
289
#ifdef _CS_GNU_LIBPTHREAD_VERSION
292
confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff));
294
if (!strncasecmp(buff, "NPTL", 4))
296
if (!strncasecmp(buff, "linuxthreads", 12))
299
return THD_LIB_OTHER;