my_pthread.c
上传用户:jmzj888
上传日期:2007-01-02
资源大小:220k
文件大小:11k
源码类别:

MySQL数据库

开发平台:

Visual C++

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