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