home *** CD-ROM | disk | FTP | other *** search
/ Chip 2001 January / Chip_2001-01_cd1.bin / tema / mysql / mysql-3.23.28g-win-source.exe / mysys / thr_mutex.c < prev    next >
C/C++ Source or Header  |  2000-09-22  |  7KB  |  243 lines

  1. /* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
  2.    
  3.    This library is free software; you can redistribute it and/or
  4.    modify it under the terms of the GNU Library General Public
  5.    License as published by the Free Software Foundation; either
  6.    version 2 of the License, or (at your option) any later version.
  7.    
  8.    This library is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11.    Library General Public License for more details.
  12.    
  13.    You should have received a copy of the GNU Library General Public
  14.    License along with this library; if not, write to the Free
  15.    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
  16.    MA 02111-1307, USA */
  17.  
  18. /* This makes a wrapper for mutex handling to make it easier to debug mutex */
  19.  
  20. #include <global.h>
  21. #if defined(HAVE_LINUXTHREADS) && !defined (__USE_UNIX98)
  22. #define __USE_UNIX98            /* To get rw locks under Linux */
  23. #endif
  24. #include <m_string.h>
  25. #if defined(THREAD) && defined(SAFE_MUTEX)
  26. #undef SAFE_MUTEX            /* Avoid safe_mutex redefinitions */
  27. #include <my_pthread.h>
  28.  
  29. #ifndef DO_NOT_REMOVE_THREAD_WRAPPERS
  30. /* Remove wrappers */
  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))
  39. #endif
  40. #endif /* DO_NOT_REMOVE_THREAD_WRAPPERS */
  41.  
  42. int safe_mutex_init(safe_mutex_t *mp,
  43.             const pthread_mutexattr_t *attr __attribute__((unused)))
  44. {
  45.   bzero((char*) mp,sizeof(*mp));
  46. #ifdef HAVE_LINUXTHREADS            /* Some extra safety */
  47.   {
  48.     pthread_mutexattr_t tmp;
  49.     pthread_mutexattr_init(&tmp);
  50.     pthread_mutexattr_setkind_np(&tmp,PTHREAD_MUTEX_ERRORCHECK_NP);
  51.     pthread_mutex_init(&mp->global,&tmp);
  52.     pthread_mutex_init(&mp->mutex, &tmp);
  53.     pthread_mutexattr_destroy(&tmp);
  54.   }
  55. #else
  56.   pthread_mutex_init(&mp->global,NULL);
  57.   pthread_mutex_init(&mp->mutex,attr);
  58. #endif
  59.   return 0;
  60. }
  61.  
  62. int safe_mutex_lock(safe_mutex_t *mp,const char *file, uint line)
  63. {
  64.   int error;
  65.   pthread_mutex_lock(&mp->global);
  66.   if (mp->count > 0 && pthread_equal(pthread_self(),mp->thread))
  67.   {
  68.     fprintf(stderr,"safe_mutex: Trying to lock mutex at %s, line %d, when the mutex was already locked at %s, line %d\n",
  69.         file,line,mp->file,mp->line);
  70.     fflush(stderr);
  71.     abort();
  72.   }
  73.   pthread_mutex_unlock(&mp->global);
  74.   error=pthread_mutex_lock(&mp->mutex);
  75.   if (error || (error=pthread_mutex_lock(&mp->global)))
  76.   {
  77.     fprintf(stderr,"Got error %d when trying to lock mutex at %s, line %d\n",
  78.         error, file, line);
  79.     fflush(stderr);
  80.     abort();
  81.   }
  82.   if (mp->count++)
  83.   {
  84.     fprintf(stderr,"safe_mutex: Error in thread libray: Got mutex at %s, line %d more than 1 time\n", file,line);
  85.     fflush(stderr);
  86.     abort();
  87.   }
  88.   mp->thread=pthread_self();
  89.   mp->file= (char*) file;
  90.   mp->line=line;
  91.   pthread_mutex_unlock(&mp->global);
  92.   return error;
  93. }
  94.  
  95.  
  96. int safe_mutex_unlock(safe_mutex_t *mp,const char *file, uint line)
  97. {
  98.   int error;
  99.   pthread_mutex_lock(&mp->global);
  100.   if (mp->count == 0)
  101.   {
  102.     fprintf(stderr,"safe_mutex: Trying to unlock mutex that wasn't locked at %s, line %d\n            Last used at %s, line: %d\n",
  103.         file,line,mp->file ? mp->file : "",mp->line);
  104.     fflush(stderr);
  105.     abort();
  106.   }
  107.   if (!pthread_equal(pthread_self(),mp->thread))
  108.   {
  109.     fprintf(stderr,"safe_mutex: Trying to unlock mutex at %s, line %d  that was locked by another thread at: %s, line: %d\n",
  110.         file,line,mp->file,mp->line);
  111.     fflush(stderr);
  112.     abort();
  113.   }
  114.   mp->count--;
  115. #ifdef __WIN__
  116.   pthread_mutex_unlock(&mp->mutex);
  117.   error=0;
  118. #else
  119.   error=pthread_mutex_unlock(&mp->mutex);
  120.   if (error)
  121.   {
  122.     fprintf(stderr,"safe_mutex: Got error: %d when trying to unlock mutex at %s, line %d\n", error, file, line);
  123.     fflush(stderr);
  124.     abort();
  125.   }
  126. #endif /* __WIN__ */
  127.   pthread_mutex_unlock(&mp->global);
  128.   return error;
  129. }
  130.  
  131.  
  132. int safe_cond_wait(pthread_cond_t *cond, safe_mutex_t *mp, const char *file,
  133.            uint line)
  134. {
  135.   int error;
  136.   pthread_mutex_lock(&mp->global);
  137.   if (mp->count == 0)
  138.   {
  139.     fprintf(stderr,"safe_mutex: Trying to cond_wait on a unlocked mutex at %s, line %d\n",file,line);
  140.     fflush(stderr);
  141.     abort();
  142.   }
  143.   if (!pthread_equal(pthread_self(),mp->thread))
  144.   {
  145.     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",
  146.         file,line,mp->file,mp->line);
  147.     fflush(stderr);
  148.     abort();
  149.   }
  150.  
  151.   if (mp->count-- != 1)
  152.   {
  153.     fprintf(stderr,"safe_mutex:  Count was %d on locked mutex at %s, line %d\n",
  154.         mp->count+1, file, line);
  155.     fflush(stderr);
  156.     abort();
  157.   }
  158.   pthread_mutex_unlock(&mp->global);
  159.   error=pthread_cond_wait(cond,&mp->mutex);
  160.   pthread_mutex_lock(&mp->global);
  161.   if (error)
  162.   {
  163.     fprintf(stderr,"safe_mutex: Got error: %d when doing a safe_mutex_wait at %s, line %d\n", error, file, line);
  164.     fflush(stderr);
  165.     abort();
  166.   }
  167.   if (mp->count++)
  168.   {
  169.     fprintf(stderr,
  170.         "safe_mutex:  Count was %d in thread %lx when locking mutex at %s, line %d\n",
  171.         mp->count-1, my_thread_id(), file, line);
  172.     fflush(stderr);
  173.     abort();
  174.   }
  175.   mp->thread=pthread_self();
  176.   mp->file= (char*) file;
  177.   mp->line=line;
  178.   pthread_mutex_unlock(&mp->global);
  179.   return error;
  180. }
  181.  
  182.  
  183. int safe_cond_timedwait(pthread_cond_t *cond, safe_mutex_t *mp,
  184.             struct timespec *abstime,
  185.             const char *file, uint line)
  186. {
  187.   int error;
  188.   pthread_mutex_lock(&mp->global);
  189.   if (mp->count != 1 || !pthread_equal(pthread_self(),mp->thread))
  190.   {
  191.     fprintf(stderr,"safe_mutex: Trying to cond_wait at %s, line %d on a not hold mutex\n",file,line);
  192.     fflush(stderr);
  193.     abort();
  194.   }
  195.   mp->count--;                    /* Mutex will be released */
  196.   pthread_mutex_unlock(&mp->global);
  197.   error=pthread_cond_timedwait(cond,&mp->mutex,abstime);
  198. #ifdef EXTRA_DEBUG
  199.   if (error && (error != EINTR && error != ETIMEDOUT))
  200.   {
  201.     fprintf(stderr,"safe_mutex: Got error: %d when doing a safe_mutex_timedwait at %s, line %d\n", error, file, line);
  202.   }
  203. #endif
  204.   pthread_mutex_lock(&mp->global);
  205.   if (mp->count++)
  206.   {
  207.     fprintf(stderr,
  208.         "safe_mutex:  Count was %d in thread %lx when locking mutex at %s, line %d (error: %d)\n",
  209.         mp->count-1, my_thread_id(), file, line, error);
  210.     fflush(stderr);
  211.     abort();
  212.   }
  213.   mp->thread=pthread_self();
  214.   mp->file= (char*) file;
  215.   mp->line=line;
  216.   pthread_mutex_unlock(&mp->global);
  217.   return error;
  218. }
  219.  
  220. int safe_mutex_destroy(safe_mutex_t *mp, const char *file, uint line)
  221. {
  222.   int error=0;
  223.   if (mp->count != 0)
  224.   {
  225.     fprintf(stderr,"safe_mutex: Trying to destroy a mutex that was locked at %s, line %d at %s, line %d\n",
  226.         mp->file,mp->line, file, line);
  227.     fflush(stderr);
  228.     abort();
  229.   }
  230. #ifdef __WIN__ 
  231.   pthread_mutex_destroy(&mp->global);
  232.   pthread_mutex_destroy(&mp->mutex);
  233. #else
  234.   if (pthread_mutex_destroy(&mp->global))
  235.     error=1;
  236.   if (pthread_mutex_destroy(&mp->mutex))
  237.     error=1;
  238. #endif
  239.   return error;
  240. }
  241.  
  242. #endif /* THREAD && SAFE_MUTEX */
  243.