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
static uint32_t my_thread_end_wait_time= 5;
47
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
48
pthread_mutexattr_t my_fast_mutexattr;
51
static uint32_t get_thread_lib(void);
54
54
initialize thread environment
64
64
bool my_thread_global_init(void)
67
thd_lib_detected= get_thread_lib();
69
if ((pth_ret= pthread_key_create(&THR_KEY_mysys, NULL)) != 0)
71
fprintf(stderr,"Can't initialize threads: error %d\n", pth_ret);
75
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
77
Set mutex type to "fast" a.k.a "adaptive"
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
85
pthread_mutexattr_init(&my_fast_mutexattr);
86
pthread_mutexattr_settype(&my_fast_mutexattr,
87
PTHREAD_MUTEX_ADAPTIVE_NP);
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())
68
95
my_thread_global_end(); /* Clean up */
75
102
void my_thread_global_end(void)
104
struct timespec abstime;
105
bool all_threads_killed= 1;
107
set_timespec(abstime, my_thread_end_wait_time);
108
pthread_mutex_lock(&THR_LOCK_threads);
109
while (THR_thread_count > 0)
111
int error= pthread_cond_timedwait(&THR_COND_threads, &THR_LOCK_threads,
113
if (error == ETIMEDOUT || error == ETIME)
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.
120
if (THR_thread_count)
122
"Error in my_thread_global_end(): %d threads didn't exit\n",
124
all_threads_killed= 0;
128
pthread_mutex_unlock(&THR_LOCK_threads);
130
pthread_key_delete(THR_KEY_mysys);
131
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
132
pthread_mutexattr_destroy(&my_fast_mutexattr);
134
pthread_mutex_destroy(&THR_LOCK_lock);
135
if (all_threads_killed)
137
pthread_mutex_destroy(&THR_LOCK_threads);
138
pthread_cond_destroy(&THR_COND_threads);
79
static uint64_t thread_id= 0;
142
static my_thread_id thread_id= 0;
82
145
Allocate thread specific memory for the thread, used by mysys
92
155
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;
158
st_my_thread_var *tmp= NULL;
160
#ifdef EXTRA_DEBUG_THREADS
161
fprintf(stderr,"my_thread_init(): thread_id: 0x%lx\n",
162
(uint32_t) pthread_self());
165
if (pthread_getspecific(THR_KEY_mysys))
167
#ifdef EXTRA_DEBUG_THREADS
168
fprintf(stderr,"my_thread_init() called more than once in thread 0x%lx\n",
169
(long) pthread_self());
173
tmp= static_cast<st_my_thread_var *>(calloc(1, sizeof(*tmp)));
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);
105
boost::mutex::scoped_lock scopedLock(THR_LOCK_threads);
185
pthread_mutex_lock(&THR_LOCK_threads);
106
186
tmp->id= ++thread_id;
188
pthread_mutex_unlock(&THR_LOCK_threads);
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().
124
207
void my_thread_end(void)
209
st_my_thread_var *tmp=
210
static_cast<st_my_thread_var *>(pthread_getspecific(THR_KEY_mysys));
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);
216
if (tmp && tmp->init)
218
#if !defined(__bsdi__) && !defined(__OpenBSD__)
219
/* bsdi and openbsd 3.5 dumps core here */
220
pthread_cond_destroy(&tmp->suspend);
222
pthread_mutex_destroy(&tmp->mutex);
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
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);
128
239
struct st_my_thread_var *_my_thread_var(void)
130
return THR_KEY_mysys.get();
133
} /* namespace internal */
134
} /* namespace drizzled */
241
struct st_my_thread_var *tmp= (struct st_my_thread_var*)pthread_getspecific(THR_KEY_mysys);
245
static uint32_t get_thread_lib(void)
247
#ifdef _CS_GNU_LIBPTHREAD_VERSION
250
confstr(_CS_GNU_LIBPTHREAD_VERSION, buff, sizeof(buff));
252
if (!strncasecmp(buff, "NPTL", 4))
254
if (!strncasecmp(buff, "linuxthreads", 12))
257
return THD_LIB_OTHER;