18 #include <my_global.h>
19 #if defined(TARGET_OS_LINUX) && !defined (__USE_UNIX98)
22 #if defined(SAFE_MUTEX)
24 #include "mysys_priv.h"
25 #include "my_static.h"
28 #ifndef DO_NOT_REMOVE_THREAD_WRAPPERS
30 #undef pthread_mutex_t
31 #undef pthread_mutex_init
32 #undef pthread_mutex_lock
33 #undef pthread_mutex_unlock
34 #undef pthread_mutex_destroy
35 #undef pthread_cond_wait
36 #undef pthread_cond_timedwait
37 #ifdef HAVE_NONPOSIX_PTHREAD_MUTEX_INIT
38 #define pthread_mutex_init(a,b) my_pthread_mutex_init((a),(b))
43 static pthread_mutex_t THR_LOCK_mutex;
44 static ulong safe_mutex_count= 0;
45 #ifdef SAFE_MUTEX_DETECT_DESTROY
46 static struct st_safe_mutex_info_t *safe_mutex_root= NULL;
49 void safe_mutex_global_init(
void)
51 pthread_mutex_init(&THR_LOCK_mutex,MY_MUTEX_INIT_FAST);
56 const pthread_mutexattr_t *attr __attribute__((unused)),
60 memset(mp, 0,
sizeof(*mp));
61 pthread_mutex_init(&mp->global,MY_MUTEX_INIT_ERRCHK);
62 pthread_mutex_init(&mp->mutex,attr);
67 #ifdef SAFE_MUTEX_DETECT_DESTROY
72 if ((mp->info= (safe_mutex_info_t *) malloc(
sizeof(safe_mutex_info_t))))
74 struct st_safe_mutex_info_t *info =mp->info;
76 info->init_file=
file;
77 info->init_line= line;
81 pthread_mutex_lock(&THR_LOCK_mutex);
82 if ((info->next= safe_mutex_root))
83 safe_mutex_root->prev= info;
84 safe_mutex_root= info;
86 pthread_mutex_unlock(&THR_LOCK_mutex);
89 pthread_mutex_lock(&THR_LOCK_mutex);
91 pthread_mutex_unlock(&THR_LOCK_mutex);
97 int safe_mutex_lock(
safe_mutex_t *mp, my_bool try_lock,
const char *file, uint line)
103 "safe_mutex: Trying to lock unitialized mutex at %s, line %d\n",
109 pthread_mutex_lock(&mp->global);
114 pthread_mutex_unlock(&mp->global);
117 else if (pthread_equal(pthread_self(),mp->thread))
120 "safe_mutex: Trying to lock mutex at %s, line %d, when the"
121 " mutex was already locked at %s, line %d in thread %s\n",
122 file,line,mp->file, mp->line, my_thread_name());
127 pthread_mutex_unlock(&mp->global);
147 error= pthread_mutex_trylock(&mp->mutex);
152 error= pthread_mutex_lock(&mp->mutex);
154 if (error || (error=pthread_mutex_lock(&mp->global)))
156 fprintf(stderr,
"Got error %d when trying to lock mutex at %s, line %d\n",
161 mp->thread= pthread_self();
164 fprintf(stderr,
"safe_mutex: Error in thread libray: Got mutex at %s, \
165 line %d more than 1 time\n", file,line);
171 pthread_mutex_unlock(&mp->global);
176 int safe_mutex_unlock(
safe_mutex_t *mp,
const char *file, uint line)
179 pthread_mutex_lock(&mp->global);
182 fprintf(stderr,
"safe_mutex: Trying to unlock mutex that wasn't locked at %s, line %d\n Last used at %s, line: %d\n",
183 file,line,mp->file ? mp->file :
"",mp->line);
187 if (!pthread_equal(pthread_self(),mp->thread))
189 fprintf(stderr,
"safe_mutex: Trying to unlock mutex at %s, line %d that was locked by another thread at: %s, line: %d\n",
190 file,line,mp->file,mp->line);
197 pthread_mutex_unlock(&mp->mutex);
200 error=pthread_mutex_unlock(&mp->mutex);
203 fprintf(stderr,
"safe_mutex: Got error: %d (%d) when trying to unlock mutex at %s, line %d\n", error, errno, file, line);
208 pthread_mutex_unlock(&mp->global);
213 int safe_cond_wait(pthread_cond_t *cond,
safe_mutex_t *mp,
const char *file,
217 pthread_mutex_lock(&mp->global);
220 fprintf(stderr,
"safe_mutex: Trying to cond_wait on a unlocked mutex at %s, line %d\n",file,line);
224 if (!pthread_equal(pthread_self(),mp->thread))
226 fprintf(stderr,
"safe_mutex: Trying to cond_wait on a mutex at %s, line %d that was locked by another thread at: %s, line: %d\n",
227 file,line,mp->file,mp->line);
232 if (mp->count-- != 1)
234 fprintf(stderr,
"safe_mutex: Count was %d on locked mutex at %s, line %d\n",
235 mp->count+1, file, line);
239 pthread_mutex_unlock(&mp->global);
240 error=pthread_cond_wait(cond,&mp->mutex);
241 pthread_mutex_lock(&mp->global);
244 fprintf(stderr,
"safe_mutex: Got error: %d (%d) when doing a safe_mutex_wait at %s, line %d\n", error, errno, file, line);
248 mp->thread=pthread_self();
252 "safe_mutex: Count was %d in thread 0x%lx when locking mutex at %s, line %d\n",
253 mp->count-1, my_thread_dbug_id(), file, line);
259 pthread_mutex_unlock(&mp->global);
264 int safe_cond_timedwait(pthread_cond_t *cond,
safe_mutex_t *mp,
266 const char *file, uint line)
269 pthread_mutex_lock(&mp->global);
270 if (mp->count != 1 || !pthread_equal(pthread_self(),mp->thread))
272 fprintf(stderr,
"safe_mutex: Trying to cond_wait at %s, line %d on a not hold mutex\n",file,line);
277 pthread_mutex_unlock(&mp->global);
278 error=pthread_cond_timedwait(cond,&mp->mutex,abstime);
280 if (error && (error != EINTR && error != ETIMEDOUT && error != ETIME))
282 fprintf(stderr,
"safe_mutex: Got error: %d (%d) when doing a safe_mutex_timedwait at %s, line %d\n", error, errno, file, line);
285 pthread_mutex_lock(&mp->global);
286 mp->thread=pthread_self();
290 "safe_mutex: Count was %d in thread 0x%lx when locking mutex at %s, line %d (error: %d (%d))\n",
291 mp->count-1, my_thread_dbug_id(), file, line, error, error);
297 pthread_mutex_unlock(&mp->global);
302 int safe_mutex_destroy(
safe_mutex_t *mp,
const char *file, uint line)
308 "safe_mutex: Trying to destroy unitialized mutex at %s, line %d\n",
315 fprintf(stderr,
"safe_mutex: Trying to destroy a mutex that was locked at %s, line %d at %s, line %d\n",
316 mp->file,mp->line, file, line);
321 pthread_mutex_destroy(&mp->global);
322 pthread_mutex_destroy(&mp->mutex);
324 if (pthread_mutex_destroy(&mp->global))
326 if (pthread_mutex_destroy(&mp->mutex))
331 #ifdef SAFE_MUTEX_DETECT_DESTROY
334 struct st_safe_mutex_info_t *info= mp->info;
335 pthread_mutex_lock(&THR_LOCK_mutex);
338 info->prev->next = info->next;
340 safe_mutex_root = info->next;
342 info->next->prev = info->prev;
345 pthread_mutex_unlock(&THR_LOCK_mutex);
350 pthread_mutex_lock(&THR_LOCK_mutex);
352 pthread_mutex_unlock(&THR_LOCK_mutex);
373 void safe_mutex_end(FILE *file __attribute__((unused)))
375 if (!safe_mutex_count)
376 pthread_mutex_destroy(&THR_LOCK_mutex);
377 #ifdef SAFE_MUTEX_DETECT_DESTROY
381 if (safe_mutex_count)
383 fprintf(file,
"Warning: Not destroyed mutex: %lu\n", safe_mutex_count);
387 struct st_safe_mutex_info_t *ptr;
388 for (ptr= safe_mutex_root ; ptr ; ptr= ptr->next)
390 fprintf(file,
"\tMutex initiated at line %4u in '%s'\n",
391 ptr->init_line, ptr->init_file);
400 #if defined(MY_PTHREAD_FASTMUTEX) && !defined(SAFE_MUTEX)
402 #include "mysys_priv.h"
403 #include "my_static.h"
404 #include <m_string.h>
408 #include <myisampack.h>
409 #include <mysys_err.h>
412 #undef pthread_mutex_t
413 #undef pthread_mutex_init
414 #undef pthread_mutex_lock
415 #undef pthread_mutex_trylock
416 #undef pthread_mutex_unlock
417 #undef pthread_mutex_destroy
418 #undef pthread_cond_wait
419 #undef pthread_cond_timedwait
421 ulong mutex_delay(ulong delayloops)
428 for (i = 0; i < delayloops * 50; i++)
434 #define MY_PTHREAD_FASTMUTEX_SPINS 8
435 #define MY_PTHREAD_FASTMUTEX_DELAY 4
437 static int cpu_count= 0;
439 int my_pthread_fastmutex_init(my_pthread_fastmutex_t *mp,
440 const pthread_mutexattr_t *attr)
442 if ((cpu_count > 1) && (attr == MY_MUTEX_INIT_FAST))
443 mp->spins= MY_PTHREAD_FASTMUTEX_SPINS;
447 return pthread_mutex_init(&mp->mutex, attr);
467 static double park_rng(my_pthread_fastmutex_t *mp)
469 mp->rng_state= ((my_ulonglong)mp->rng_state * 279470273
U) % 4294967291
U;
470 return (mp->rng_state / 2147483647.0);
473 int my_pthread_fastmutex_lock(my_pthread_fastmutex_t *mp)
477 uint maxdelay= MY_PTHREAD_FASTMUTEX_DELAY;
479 for (i= 0; i < mp->spins; i++)
481 res= pthread_mutex_trylock(&mp->mutex);
489 mutex_delay(maxdelay);
490 maxdelay += park_rng(mp) * MY_PTHREAD_FASTMUTEX_DELAY + 1;
492 return pthread_mutex_lock(&mp->mutex);
496 void fastmutex_global_init(
void)
498 #ifdef _SC_NPROCESSORS_CONF
499 cpu_count= sysconf(_SC_NPROCESSORS_CONF);