my_pthread.c
上传用户:tsgydb
上传日期:2007-04-14
资源大小:10674k
文件大小:12k
源码类别:

MySQL数据库

开发平台:

Visual C++

  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. /* Functions to get threads more portable */
  18. #include "mysys_priv.h"
  19. #ifdef THREAD
  20. #include <signal.h>
  21. #include <m_string.h>
  22. #include <thr_alarm.h>
  23. #include <assert.h>
  24. #if !defined(MSDOS) && !defined(__WIN__)
  25. #include <netdb.h>
  26. #endif
  27. #if (defined(__BSD__) || defined(_BSDI_VERSION)) && !defined(HAVE_mit_thread)
  28. #define SCHED_POLICY SCHED_RR
  29. #else
  30. #define SCHED_POLICY SCHED_OTHER
  31. #endif
  32. #ifndef my_pthread_setprio
  33. void my_pthread_setprio(pthread_t thread_id,int prior)
  34. {
  35. #ifdef HAVE_PTHREAD_SETSCHEDPARAM
  36.   struct sched_param tmp_sched_param;
  37.   bzero((char*) &tmp_sched_param,sizeof(tmp_sched_param));
  38.   tmp_sched_param.sched_priority=prior;
  39.   VOID(pthread_setschedparam(thread_id,SCHED_POLICY,&tmp_sched_param));
  40. #endif
  41. }
  42. #endif
  43. #ifndef my_pthread_getprio
  44. int my_pthread_getprio(pthread_t thread_id)
  45. {
  46. #ifdef HAVE_PTHREAD_SETSCHEDPARAM
  47.   struct sched_param tmp_sched_param;
  48.   int policy;
  49.   if (!pthread_getschedparam(thread_id,&policy,&tmp_sched_param))
  50.   {
  51.     DBUG_PRINT("thread",("policy: %d  priority: %d",
  52.  policy,tmp_sched_param.sched_priority));
  53.     return tmp_sched_param.sched_priority;
  54.   }
  55. #endif
  56.   return -1;
  57. }
  58. #endif
  59. #ifndef my_pthread_attr_setprio
  60. void my_pthread_attr_setprio(pthread_attr_t *attr, int priority)
  61. {
  62. #ifdef HAVE_PTHREAD_SETSCHEDPARAM
  63.   struct sched_param tmp_sched_param;
  64.   bzero((char*) &tmp_sched_param,sizeof(tmp_sched_param));
  65.   tmp_sched_param.sched_priority=priority;
  66.   VOID(pthread_attr_setschedparam(attr,&tmp_sched_param));
  67. #endif
  68. }
  69. #endif
  70. /* To allow use of pthread_getspecific with two arguments */
  71. #ifdef HAVE_NONPOSIX_PTHREAD_GETSPECIFIC
  72. #undef pthread_getspecific
  73. #ifdef HAVE_UNIXWARE7_THREADS
  74. #define pthread_getspecific thr_getspecific
  75. #endif
  76. void *my_pthread_getspecific_imp(pthread_key_t key)
  77. {
  78.   void *value;
  79.   if (pthread_getspecific(key,(void *) &value))
  80.     return 0;
  81.   return value;
  82. }
  83. #endif
  84. /* Some functions for RTS threads, AIX, Siemens Unix and UnixWare 7
  85.    (and DEC OSF/1 3.2 too) */
  86. int my_pthread_create_detached=1;
  87. #if defined(HAVE_NONPOSIX_SIGWAIT) || defined(HAVE_DEC_3_2_THREADS)
  88. int my_sigwait(const sigset_t *set,int *sig)
  89. {
  90.   int signal=sigwait((sigset_t*) set);
  91.   if (signal < 0)
  92.     return errno;
  93.   *sig=signal;
  94.   return 0;
  95. }
  96. #endif
  97. /* localtime_r for SCO 3.2V4.2 */
  98. #ifndef HAVE_LOCALTIME_R
  99. extern pthread_mutex_t LOCK_localtime_r;
  100. struct tm *localtime_r(const time_t *clock, struct tm *res)
  101. {
  102.   struct tm *tmp;
  103.   pthread_mutex_lock(&LOCK_localtime_r);
  104.   tmp=localtime(clock);
  105.   *res= *tmp;
  106.   pthread_mutex_unlock(&LOCK_localtime_r);
  107.   return res;
  108. }
  109. #endif
  110. /****************************************************************************
  111. ** Replacement of sigwait if the system doesn't have one (like BSDI 3.0)
  112. **
  113. ** Note:
  114. ** This version of sigwait() is assumed to called in a loop so the signalmask
  115. ** is permanently modified to reflect the signal set. This is done to get
  116. ** a much faster implementation.
  117. **
  118. ** This implementation isn't thread safe: It assumes that only one
  119. ** thread is using sigwait.
  120. **
  121. ** If one later supplies a different signal mask, all old signals that
  122. ** was used before are unblocked and set to SIGDFL.
  123. **
  124. ** Author: Gary Wisniewski <garyw@spidereye.com.au>, much modified by Monty
  125. ****************************************************************************/
  126. #if !defined(HAVE_SIGWAIT) && !defined(HAVE_mit_thread) && !defined(sigwait) && !defined(__WIN__) && !defined(HAVE_rts_threads) && !defined(HAVE_NONPOSIX_SIGWAIT) && !defined(HAVE_DEC_3_2_THREADS)
  127. #if !defined(DONT_USE_SIGSUSPEND)
  128. static sigset_t sigwait_set,rev_sigwait_set,px_recd;
  129. void px_handle_sig(int sig)
  130. {
  131.   sigaddset(&px_recd, sig);
  132. }
  133. void sigwait_setup(sigset_t *set)
  134. {
  135.   int i;
  136.   struct sigaction sact,sact1;
  137.   sigset_t unblock_mask;
  138.   sact.sa_flags = 0;
  139.   sact.sa_handler = px_handle_sig;
  140.   memcpy_fixed(&sact.sa_mask,set,sizeof(*set)); /* handler isn't thread_safe */
  141.   sigemptyset(&unblock_mask);
  142.   pthread_sigmask(SIG_UNBLOCK,(sigset_t*) 0,&rev_sigwait_set);
  143.   for (i = 1; i <= sizeof(sigwait_set)*8; i++)
  144.   {
  145.     if (sigismember(set,i))
  146.     {
  147.       sigdelset(&rev_sigwait_set,i);
  148.       if (!sigismember(&sigwait_set,i))
  149. sigaction(i, &sact, (struct sigaction*) 0);
  150.     }
  151.     else
  152.     {
  153.       sigdelset(&px_recd,i); /* Don't handle this */
  154.       if (sigismember(&sigwait_set,i))
  155.       { /* Remove the old handler */
  156. sigaddset(&unblock_mask,i);
  157. sigdelset(&rev_sigwait_set,i);
  158. sact1.sa_flags = 0;
  159. sact1.sa_handler = SIG_DFL;
  160. sigemptyset(&sact1.sa_mask);
  161. sigaction(i, &sact1, 0);
  162.       }
  163.     }
  164.   }
  165.   memcpy_fixed(&sigwait_set,set,sizeof(*set));
  166.   pthread_sigmask(SIG_BLOCK,(sigset_t*) set,(sigset_t*) 0);
  167.   pthread_sigmask(SIG_UNBLOCK,&unblock_mask,(sigset_t*) 0);
  168. }
  169. int sigwait(sigset_t *setp, int *sigp)
  170. {
  171.   if (memcmp(setp,&sigwait_set,sizeof(sigwait_set)))
  172.     sigwait_setup(setp); /* Init or change of set */
  173.   for (;;)
  174.   {
  175.     /*
  176.       This is a fast, not 100% portable implementation to find the signal.
  177.       Because the handler is blocked there should be at most 1 bit set, but
  178.       the specification on this is somewhat shady so we use a set instead a
  179.       single variable.
  180.       */
  181.     ulong *ptr= (ulong*) &px_recd;
  182.     ulong *end=ptr+sizeof(px_recd)/sizeof(ulong);
  183.     for ( ; ptr != end ; ptr++)
  184.     {
  185.       if (*ptr)
  186.       {
  187. ulong set= *ptr;
  188. int found= (int) ((char*) ptr - (char*) &px_recd)*8+1;
  189. while (!(set & 1))
  190. {
  191.   found++;
  192.   set>>=1;
  193. }
  194. *sigp=found;
  195. sigdelset(&px_recd,found);
  196. return 0;
  197.       }
  198.     }
  199.     sigsuspend(&rev_sigwait_set);
  200.   }
  201.   return 0;
  202. }
  203. #else  /* !DONT_USE_SIGSUSPEND */
  204. /****************************************************************************
  205. ** Replacement of sigwait if the system doesn't have one (like BSDI 3.0)
  206. **
  207. ** Note:
  208. ** This version of sigwait() is assumed to called in a loop so the signalmask
  209. ** is permanently modified to reflect the signal set. This is done to get
  210. ** a much faster implementation.
  211. **
  212. ** This implementation uses a extra thread to handle the signals and one
  213. ** must always call sigwait() with the same signal mask!
  214. **
  215. ** BSDI 3.0 NOTE:
  216. **
  217. ** pthread_kill() doesn't work on a thread in a select() or sleep() loop?
  218. ** After adding the sleep to sigwait_thread, all signals are checked and
  219. ** delivered every second. This isn't that terrible performance vice, but
  220. ** someone should report this to BSDI and ask for a fix!
  221. ** Another problem is that when the sleep() ends, every select() in other
  222. ** threads are interrupted!
  223. ****************************************************************************/
  224. static sigset_t pending_set;
  225. static bool inited=0;
  226. static pthread_cond_t  COND_sigwait;
  227. static pthread_mutex_t LOCK_sigwait;
  228. void sigwait_handle_sig(int sig)
  229. {
  230.   pthread_mutex_lock(&LOCK_sigwait);
  231.   sigaddset(&pending_set, sig);
  232.   VOID(pthread_cond_signal(&COND_sigwait)); /* inform sigwait() about signal */
  233.   pthread_mutex_unlock(&LOCK_sigwait);
  234. }
  235. extern pthread_t alarm_thread;
  236. void *sigwait_thread(void *set_arg)
  237. {
  238.   sigset_t *set=(sigset_t*) set_arg;
  239.   int i;
  240.   struct sigaction sact;
  241.   sact.sa_flags = 0;
  242.   sact.sa_handler = sigwait_handle_sig;
  243.   memcpy_fixed(&sact.sa_mask,set,sizeof(*set)); /* handler isn't thread_safe */
  244.   sigemptyset(&pending_set);
  245.   for (i = 1; i <= sizeof(pending_set)*8; i++)
  246.   {
  247.     if (sigismember(set,i))
  248.     {
  249.       sigaction(i, &sact, (struct sigaction*) 0);
  250.     }
  251.   }
  252.   sigaddset(set,THR_CLIENT_ALARM);
  253.   pthread_sigmask(SIG_UNBLOCK,(sigset_t*) set,(sigset_t*) 0);
  254.   alarm_thread=pthread_self(); /* For thr_alarm */
  255.   for (;;)
  256.   { /* Wait for signals */
  257. #ifdef HAVE_NOT_BROKEN_SELECT
  258.     fd_set fd;
  259.     FD_ZERO(&fd);
  260.     select(0,&fd,0,0,0);
  261. #else
  262.     sleep(1); /* Because of broken BSDI */
  263. #endif
  264.   }
  265. }
  266. int sigwait(sigset_t *setp, int *sigp)
  267. {
  268.   if (!inited)
  269.   {
  270.     pthread_attr_t thr_attr;
  271.     pthread_t sigwait_thread_id;
  272.     inited=1;
  273.     sigemptyset(&pending_set);
  274.     pthread_mutex_init(&LOCK_sigwait,NULL);
  275.     pthread_cond_init(&COND_sigwait,NULL);
  276.     pthread_attr_init(&thr_attr);
  277.     pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS);
  278.     pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
  279.     pthread_attr_setstacksize(&thr_attr,8196);
  280.     my_pthread_attr_setprio(&thr_attr,100); /* Very high priority */
  281.     VOID(pthread_create(&sigwait_thread_id,&thr_attr,sigwait_thread,setp));
  282.     VOID(pthread_attr_destroy(&thr_attr));
  283.   }
  284.   pthread_mutex_lock(&LOCK_sigwait);
  285.   for (;;)
  286.   {
  287.     ulong *ptr= (ulong*) &pending_set;
  288.     ulong *end=ptr+sizeof(pending_set)/sizeof(ulong);
  289.     for ( ; ptr != end ; ptr++)
  290.     {
  291.       if (*ptr)
  292.       {
  293. ulong set= *ptr;
  294. int found= (int) ((char*) ptr - (char*) &pending_set)*8+1;
  295. while (!(set & 1))
  296. {
  297.   found++;
  298.   set>>=1;
  299. }
  300. *sigp=found;
  301. sigdelset(&pending_set,found);
  302. pthread_mutex_unlock(&LOCK_sigwait);
  303. return 0;
  304.       }
  305.     }
  306.     VOID(pthread_cond_wait(&COND_sigwait,&LOCK_sigwait));
  307.   }
  308.   return 0;
  309. }
  310. #endif /* DONT_USE_SIGSUSPEND */
  311. #endif /* HAVE_SIGWAIT */
  312. /*****************************************************************************
  313. ** Implement pthread_signal for systems that can't use signal() with threads
  314. ** Currently this is only used with BSDI 3.0
  315. *****************************************************************************/
  316. #ifdef USE_PTHREAD_SIGNAL
  317. int pthread_signal(int sig, void (*func)())
  318. {
  319.   struct sigaction sact;
  320.   sact.sa_flags= 0;
  321.   sact.sa_handler= func;
  322.   sigemptyset(&sact.sa_mask);
  323.   sigaction(sig, &sact, (struct sigaction*) 0);
  324.   return 0;
  325. }
  326. #endif
  327. /*****************************************************************************
  328. ** Patches for AIX and DEC OSF/1 3.2
  329. *****************************************************************************/
  330. #if (defined(HAVE_NONPOSIX_PTHREAD_MUTEX_INIT) && !defined(HAVE_UNIXWARE7_THREADS)) || defined(HAVE_DEC_3_2_THREADS)
  331. #undef pthread_mutex_init
  332. #undef pthread_cond_init
  333. #include <netdb.h>
  334. int my_pthread_mutex_init(pthread_mutex_t *mp, const pthread_mutexattr_t *attr)
  335. {
  336.   int error;
  337.   if (!attr)
  338.     error=pthread_mutex_init(mp,pthread_mutexattr_default);
  339.   else
  340.     error=pthread_mutex_init(mp,*attr);
  341.   return error;
  342. }
  343. int my_pthread_cond_init(pthread_cond_t *mp, const pthread_condattr_t *attr)
  344. {
  345.   int error;
  346.   if (!attr)
  347.     error=pthread_cond_init(mp,pthread_condattr_default);
  348.   else
  349.     error=pthread_cond_init(mp,*attr);
  350.   return error;
  351. }
  352. #endif
  353. /*
  354. ** Emulate SOLARIS style calls, not because it's better, but just to make the
  355. ** usage of getbostbyname_r simpler.
  356. */
  357. #if !defined(my_gethostbyname_r) && defined(HAVE_GETHOSTBYNAME_R)
  358. #if defined(HAVE_GETHOSTBYNAME_R_GLIBC2_STYLE)
  359. struct hostent *my_gethostbyname_r(const char *name,
  360.    struct hostent *result, char *buffer,
  361.    int buflen, int *h_errnop)
  362. {
  363.   struct hostent *hp;
  364.   dbug_assert((size_t) buflen >= sizeof(*result));
  365.   if (gethostbyname_r(name,result, buffer, (size_t) buflen, &hp, h_errnop))
  366.     return 0;
  367.   return hp;
  368. }
  369. #elif defined(HAVE_GETHOSTBYNAME_R_RETURN_INT)
  370. struct hostent *my_gethostbyname_r(const char *name,
  371.    struct hostent *result, char *buffer,
  372.    int buflen, int *h_errnop)
  373. {
  374.   dbug_assert(buflen >= sizeof(struct hostent_data));
  375.   if (gethostbyname_r(name,result,(struct hostent_data *) buffer) == -1)
  376.   {
  377.     *h_errnop= errno;
  378.     return 0;
  379.   }
  380.   return result;
  381. }
  382. #else
  383. struct hostent *my_gethostbyname_r(const char *name,
  384.    struct hostent *result, char *buffer,
  385.    int buflen, int *h_errnop)
  386. {
  387.   struct hostent *hp;
  388.   dbug_assert(buflen >= sizeof(struct hostent_data));
  389.   hp= gethostbyname_r(name,result,(struct hostent_data *) buffer);
  390.   *h_errnop= errno;
  391.   return hp;
  392. }
  393. #endif /* GLIBC2_STYLE_GETHOSTBYNAME_R */
  394. #endif
  395. /* Some help functions */
  396. int pthread_no_free(void *not_used __attribute__((unused)))
  397. {
  398.   return 0;
  399. }
  400. int pthread_dummy(int ret)
  401. {
  402.   return ret;
  403. }
  404. #endif /* THREAD */