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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
17
17
Functions to handle initializating and allocationg of all mysys & debug
42
#include <boost/thread/thread.hpp>
43
#include <boost/thread/mutex.hpp>
44
#include <boost/thread/tss.hpp>
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);
51
boost::thread_specific_ptr<st_my_thread_var> THR_KEY_mysys;
52
boost::mutex THR_LOCK_threads;
61
55
initialize thread environment
71
65
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
67
if (my_thread_init())
102
69
my_thread_global_end(); /* Clean up */
109
76
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
80
static uint64_t thread_id= 0;
162
93
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)));
95
// We should mever see my_thread_init() called twice
96
if (THR_KEY_mysys.get())
99
st_my_thread_var *tmp= new st_my_thread_var;
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);
104
THR_KEY_mysys.reset(tmp);
192
pthread_mutex_lock(&THR_LOCK_threads);
106
boost::mutex::scoped_lock scopedLock(THR_LOCK_threads);
193
107
tmp->id= ++thread_id;
195
pthread_mutex_unlock(&THR_LOCK_threads);
214
125
void my_thread_end(void)
216
st_my_thread_var *tmp=
217
static_cast<st_my_thread_var *>(pthread_getspecific(THR_KEY_mysys));
127
st_my_thread_var *tmp= THR_KEY_mysys.get();
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);
132
THR_KEY_mysys.release();
246
136
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;
138
return THR_KEY_mysys.get();
267
141
} /* namespace internal */