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
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;
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);
54
61
initialize thread environment
64
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);
66
100
if (my_thread_init())
68
102
my_thread_global_end(); /* Clean up */
75
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);
79
149
static uint64_t thread_id= 0;
92
162
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;
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)));
103
THR_KEY_mysys.reset(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);
105
boost::mutex::scoped_lock scopedLock(THR_LOCK_threads);
192
pthread_mutex_lock(&THR_LOCK_threads);
106
193
tmp->id= ++thread_id;
195
pthread_mutex_unlock(&THR_LOCK_threads);
119
209
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().
210
This happens for example when one calls 'mysql_server_init()'
211
mysql_server_end() and then ends with a mysql_end().
124
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);
128
246
struct st_my_thread_var *_my_thread_var(void)
130
return THR_KEY_mysys.get();
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;
133
267
} /* namespace internal */