my_thr_init.c
上传用户:romrleung
上传日期:2022-05-23
资源大小:18897k
文件大小:8k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000 MySQL AB
  2.    This program is free software; you can redistribute it and/or modify
  3.    it under the terms of the GNU General Public License as published by
  4.    the Free Software Foundation; either version 2 of the License, or
  5.    (at your option) any later version.
  6.    This program is distributed in the hope that it will be useful,
  7.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  8.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  9.    GNU General Public License for more details.
  10.    You should have received a copy of the GNU General Public License
  11.    along with this program; if not, write to the Free Software
  12.    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
  13. /*
  14.   Functions to handle initializating and allocationg of all mysys & debug
  15.   thread variables.
  16. */
  17. #include "mysys_priv.h"
  18. #include <m_string.h>
  19. #ifdef THREAD
  20. #ifdef USE_TLS
  21. pthread_key(struct st_my_thread_var*, THR_KEY_mysys);
  22. #else
  23. pthread_key(struct st_my_thread_var, THR_KEY_mysys);
  24. #endif /* USE_TLS */
  25. pthread_mutex_t THR_LOCK_malloc,THR_LOCK_open,
  26.         THR_LOCK_lock,THR_LOCK_isam,THR_LOCK_myisam,THR_LOCK_heap,
  27.         THR_LOCK_net, THR_LOCK_charset; 
  28. #if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
  29. pthread_mutex_t LOCK_localtime_r;
  30. #endif
  31. #ifndef HAVE_GETHOSTBYNAME_R
  32. pthread_mutex_t LOCK_gethostbyname_r;
  33. #endif
  34. #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
  35. pthread_mutexattr_t my_fast_mutexattr;
  36. #endif
  37. #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
  38. pthread_mutexattr_t my_errorcheck_mutexattr;
  39. #endif
  40. /*
  41.   initialize thread environment
  42.   SYNOPSIS
  43.     my_thread_global_init()
  44.   RETURN
  45.     0  ok
  46.     1  error (Couldn't create THR_KEY_mysys)
  47. */
  48. my_bool my_thread_global_init(void)
  49. {
  50.   if (pthread_key_create(&THR_KEY_mysys,0))
  51.   {
  52.     fprintf(stderr,"Can't initialize threads: error %dn",errno);
  53.     return 1;
  54.   }
  55. #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
  56.   /*
  57.     Set mutex type to "fast" a.k.a "adaptive"
  58.     The mutex kind determines what happens if a thread attempts to lock
  59.     a mutex it already owns with pthread_mutex_lock(3). If the mutex
  60.     is of the ``fast'' kind, pthread_mutex_lock(3) simply suspends
  61.     the calling thread forever. If the mutex is of the ``error checking''
  62.     kind, pthread_mutex_lock(3) returns immediately with the error
  63.     code EDEADLK.
  64.   */
  65.   pthread_mutexattr_init(&my_fast_mutexattr);
  66.   pthread_mutexattr_settype(&my_fast_mutexattr,
  67.                             PTHREAD_MUTEX_ADAPTIVE_NP);
  68. #endif
  69. #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
  70.   /*
  71.     Set mutex type to "errorcheck" a.k.a "adaptive"
  72.   */
  73.   pthread_mutexattr_init(&my_errorcheck_mutexattr);
  74.   pthread_mutexattr_settype(&my_errorcheck_mutexattr,
  75.                             PTHREAD_MUTEX_ERRORCHECK);
  76. #endif
  77.   pthread_mutex_init(&THR_LOCK_malloc,MY_MUTEX_INIT_FAST);
  78.   pthread_mutex_init(&THR_LOCK_open,MY_MUTEX_INIT_FAST);
  79.   pthread_mutex_init(&THR_LOCK_lock,MY_MUTEX_INIT_FAST);
  80.   pthread_mutex_init(&THR_LOCK_isam,MY_MUTEX_INIT_SLOW);
  81.   pthread_mutex_init(&THR_LOCK_myisam,MY_MUTEX_INIT_SLOW);
  82.   pthread_mutex_init(&THR_LOCK_heap,MY_MUTEX_INIT_FAST);
  83.   pthread_mutex_init(&THR_LOCK_net,MY_MUTEX_INIT_FAST);
  84.   pthread_mutex_init(&THR_LOCK_charset,MY_MUTEX_INIT_FAST);
  85. #if defined( __WIN__) || defined(OS2)
  86.   win_pthread_init();
  87. #endif
  88. #if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
  89.   pthread_mutex_init(&LOCK_localtime_r,MY_MUTEX_INIT_SLOW);
  90. #endif
  91. #ifndef HAVE_GETHOSTBYNAME_R
  92.   pthread_mutex_init(&LOCK_gethostbyname_r,MY_MUTEX_INIT_SLOW);
  93. #endif
  94.   if (my_thread_init())
  95.   {
  96.     my_thread_global_end(); /* Clean up */
  97.     return 1;
  98.   }
  99.   return 0;
  100. }
  101. void my_thread_global_end(void)
  102. {
  103.   pthread_key_delete(THR_KEY_mysys);
  104. #ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
  105.   pthread_mutexattr_destroy(&my_fast_mutexattr);
  106. #endif
  107. #ifdef PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP
  108.   pthread_mutexattr_destroy(&my_errorcheck_mutexattr);
  109. #endif
  110.   pthread_mutex_destroy(&THR_LOCK_malloc);
  111.   pthread_mutex_destroy(&THR_LOCK_open);
  112.   pthread_mutex_destroy(&THR_LOCK_lock);
  113.   pthread_mutex_destroy(&THR_LOCK_isam);
  114.   pthread_mutex_destroy(&THR_LOCK_myisam);
  115.   pthread_mutex_destroy(&THR_LOCK_heap);
  116.   pthread_mutex_destroy(&THR_LOCK_net);
  117.   pthread_mutex_destroy(&THR_LOCK_charset);
  118. #if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
  119.   pthread_mutex_destroy(&LOCK_localtime_r);
  120. #endif
  121. #ifndef HAVE_GETHOSTBYNAME_R
  122.   pthread_mutex_destroy(&LOCK_gethostbyname_r);
  123. #endif
  124. }
  125. static long thread_id=0;
  126. /*
  127.   We can't use mutex_locks here if we are using windows as
  128.   we may have compiled the program with SAFE_MUTEX, in which
  129.   case the checking of mutex_locks will not work until
  130.   the pthread_self thread specific variable is initialized.
  131. */
  132. my_bool my_thread_init(void)
  133. {
  134.   struct st_my_thread_var *tmp;
  135.   my_bool error=0;
  136. #ifdef EXTRA_DEBUG_THREADS
  137.   fprintf(stderr,"my_thread_init(): thread_id=%ldn",pthread_self());
  138. #endif  
  139. #if !defined(__WIN__) || defined(USE_TLS) || ! defined(SAFE_MUTEX)
  140.   pthread_mutex_lock(&THR_LOCK_lock);
  141. #endif
  142. #if !defined(__WIN__) || defined(USE_TLS)
  143.   if (my_pthread_getspecific(struct st_my_thread_var *,THR_KEY_mysys))
  144.   {
  145. #ifdef EXTRA_DEBUG_THREADS
  146.     fprintf(stderr,"my_thread_init() called more than once in thread %ldn",
  147.         pthread_self());
  148. #endif    
  149.     goto end;
  150.   }
  151.   if (!(tmp= (struct st_my_thread_var *) calloc(1, sizeof(*tmp))))
  152.   {
  153.     error= 1;
  154.     goto end;
  155.   }
  156.   pthread_setspecific(THR_KEY_mysys,tmp);
  157. #else
  158.   /*
  159.     Skip initialization if the thread specific variable is already initialized
  160.   */
  161.   if (THR_KEY_mysys.id)
  162.     goto end;
  163.   tmp= &THR_KEY_mysys;
  164. #endif
  165.   tmp->id= ++thread_id;
  166. #if defined(__WIN__) && defined(EMBEDDED_LIBRARY)
  167.   tmp->thread_self= (pthread_t)getpid();
  168. #endif
  169.   pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST);
  170.   pthread_cond_init(&tmp->suspend, NULL);
  171.   tmp->init= 1;
  172. end:
  173. #if !defined(__WIN__) || defined(USE_TLS) || ! defined(SAFE_MUTEX)
  174.   pthread_mutex_unlock(&THR_LOCK_lock);
  175. #endif
  176.   return error;
  177. }
  178. void my_thread_end(void)
  179. {
  180.   struct st_my_thread_var *tmp;
  181.   tmp= my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys);
  182. #ifdef EXTRA_DEBUG_THREADS
  183.   fprintf(stderr,"my_thread_end(): tmp=%p,thread_id=%ldn",
  184.   tmp,pthread_self());
  185. #endif  
  186.   if (tmp && tmp->init)
  187.   {
  188. #if !defined(DBUG_OFF)
  189.     /* tmp->dbug is allocated inside DBUG library */
  190.     if (tmp->dbug)
  191.     {
  192.       free(tmp->dbug);
  193.       tmp->dbug=0;
  194.     }
  195. #endif
  196. #if !defined(__bsdi__) && !defined(__OpenBSD__) || defined(HAVE_mit_thread)
  197.  /* bsdi and openbsd 3.5 dumps core here */
  198.     pthread_cond_destroy(&tmp->suspend);
  199. #endif
  200.     pthread_mutex_destroy(&tmp->mutex);
  201. #if (!defined(__WIN__) && !defined(OS2)) || defined(USE_TLS)
  202.     free(tmp);
  203. #else
  204.     tmp->init= 0;
  205. #endif
  206.   }
  207.   /* The following free has to be done, even if my_thread_var() is 0 */
  208. #if (!defined(__WIN__) && !defined(OS2)) || defined(USE_TLS)
  209.   pthread_setspecific(THR_KEY_mysys,0);
  210. #endif
  211. }
  212. struct st_my_thread_var *_my_thread_var(void)
  213. {
  214.   struct st_my_thread_var *tmp=
  215.     my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys);
  216. #if defined(USE_TLS)
  217.   /* This can only happen in a .DLL */
  218.   if (!tmp)
  219.   {
  220.     my_thread_init();
  221.     tmp=my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys);
  222.   }
  223. #endif
  224.   return tmp;
  225. }
  226. /****************************************************************************
  227.   Get name of current thread.
  228. ****************************************************************************/
  229. #define UNKNOWN_THREAD -1
  230. long my_thread_id()
  231. {
  232. #if defined(HAVE_PTHREAD_GETSEQUENCE_NP)
  233.   return pthread_getsequence_np(pthread_self());
  234. #elif (defined(__sun) || defined(__sgi) || defined(__linux__)) && !defined(HAVE_mit_thread)
  235.   return pthread_self();
  236. #else
  237.   return my_thread_var->id;
  238. #endif
  239. }
  240. #ifdef DBUG_OFF
  241. const char *my_thread_name(void)
  242. {
  243.   return "no_name";
  244. }
  245. #else
  246. const char *my_thread_name(void)
  247. {
  248.   char name_buff[100];
  249.   struct st_my_thread_var *tmp=my_thread_var;
  250.   if (!tmp->name[0])
  251.   {
  252.     long id=my_thread_id();
  253.     sprintf(name_buff,"T@%ld", id);
  254.     strmake(tmp->name,name_buff,THREAD_NAME_SIZE);
  255.   }
  256.   return tmp->name;
  257. }
  258. #endif /* DBUG_OFF */
  259. #endif /* THREAD */