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

MySQL数据库

开发平台:

Visual C++

  1. /* Copyright (C) 2000-2003 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. /* Functions to get threads more portable */
  14. #define DONT_REMAP_PTHREAD_FUNCTIONS
  15. #include "mysys_priv.h"
  16. #ifdef THREAD
  17. #include <signal.h>
  18. #include <m_string.h>
  19. #include <thr_alarm.h>
  20. #if (defined(__BSD__) || defined(_BSDI_VERSION)) && !defined(HAVE_mit_thread)
  21. #define SCHED_POLICY SCHED_RR
  22. #else
  23. #define SCHED_POLICY SCHED_OTHER
  24. #endif
  25. #ifndef my_pthread_setprio
  26. void my_pthread_setprio(pthread_t thread_id,int prior)
  27. {
  28. #ifdef HAVE_PTHREAD_SETSCHEDPARAM
  29.   struct sched_param tmp_sched_param;
  30.   bzero((char*) &tmp_sched_param,sizeof(tmp_sched_param));
  31.   tmp_sched_param.sched_priority=prior;
  32.   VOID(pthread_setschedparam(thread_id,SCHED_POLICY,&tmp_sched_param));
  33. #endif
  34. }
  35. #endif
  36. #ifndef my_pthread_getprio
  37. int my_pthread_getprio(pthread_t thread_id)
  38. {
  39. #ifdef HAVE_PTHREAD_SETSCHEDPARAM
  40.   struct sched_param tmp_sched_param;
  41.   int policy;
  42.   if (!pthread_getschedparam(thread_id,&policy,&tmp_sched_param))
  43.   {
  44.     DBUG_PRINT("thread",("policy: %d  priority: %d",
  45.  policy,tmp_sched_param.sched_priority));
  46.     return tmp_sched_param.sched_priority;
  47.   }
  48. #endif
  49.   return -1;
  50. }
  51. #endif
  52. #ifndef my_pthread_attr_setprio
  53. void my_pthread_attr_setprio(pthread_attr_t *attr, int priority)
  54. {
  55. #ifdef HAVE_PTHREAD_SETSCHEDPARAM
  56.   struct sched_param tmp_sched_param;
  57.   bzero((char*) &tmp_sched_param,sizeof(tmp_sched_param));
  58.   tmp_sched_param.sched_priority=priority;
  59.   VOID(pthread_attr_setschedparam(attr,&tmp_sched_param));
  60. #endif
  61. }
  62. #endif
  63. /* To allow use of pthread_getspecific with two arguments */
  64. #ifdef HAVE_NONPOSIX_PTHREAD_GETSPECIFIC
  65. #undef pthread_getspecific
  66. #ifdef HAVE_UNIXWARE7_THREADS
  67. #define pthread_getspecific thr_getspecific
  68. #endif
  69. void *my_pthread_getspecific_imp(pthread_key_t key)
  70. {
  71.   void *value;
  72.   if (pthread_getspecific(key,(void *) &value))
  73.     return 0;
  74.   return value;
  75. }
  76. #endif
  77. #ifdef __NETWARE__
  78. /*
  79.   Don't kill the LibC Reaper thread or the main thread
  80. */
  81. #include <nks/thread.h>
  82. #undef pthread_exit
  83. void my_pthread_exit(void *status)
  84. {
  85.   NXThreadId_t tid;
  86.   NXContext_t ctx;
  87.   char name[NX_MAX_OBJECT_NAME_LEN+1] = "";
  88.   tid= NXThreadGetId();
  89.   if (tid == NX_INVALID_THREAD_ID || !tid)
  90.     return;
  91.   if (NXThreadGetContext(tid, &ctx) ||
  92.       NXContextGetName(ctx, name, sizeof(name)-1))
  93.     return;
  94.   /*
  95.     "MYSQLD.NLM's LibC Reaper" or "MYSQLD.NLM's main thread"
  96.     with a debug build of LibC the reaper can have different names
  97.   */
  98.   if (!strindex(name, "'s"))
  99.     pthread_exit(status);
  100. }
  101. #endif
  102. /*
  103.   Some functions for RTS threads, AIX, Siemens Unix and UnixWare 7
  104.   (and DEC OSF/1 3.2 too)
  105. */
  106. int my_pthread_create_detached=1;
  107. #if defined(HAVE_NONPOSIX_SIGWAIT) || defined(HAVE_DEC_3_2_THREADS)
  108. int my_sigwait(const sigset_t *set,int *sig)
  109. {
  110.   int signal=sigwait((sigset_t*) set);
  111.   if (signal < 0)
  112.     return errno;
  113.   *sig=signal;
  114.   return 0;
  115. }
  116. #endif
  117. /* localtime_r for SCO 3.2V4.2 */
  118. #if !defined(HAVE_LOCALTIME_R) || !defined(HAVE_GMTIME_R)
  119. extern pthread_mutex_t LOCK_localtime_r;
  120. #endif
  121. #if !defined(HAVE_LOCALTIME_R)
  122. struct tm *localtime_r(const time_t *clock, struct tm *res)
  123. {
  124.   struct tm *tmp;
  125.   pthread_mutex_lock(&LOCK_localtime_r);
  126.   tmp=localtime(clock);
  127.   *res= *tmp;
  128.   pthread_mutex_unlock(&LOCK_localtime_r);
  129.   return res;
  130. }
  131. #endif
  132. #if !defined(HAVE_GMTIME_R)
  133. /* 
  134.   Reentrant version of standard gmtime() function. 
  135.   Needed on some systems which don't implement it.
  136. */
  137. struct tm *gmtime_r(const time_t *clock, struct tm *res)
  138. {
  139.   struct tm *tmp;
  140.   pthread_mutex_lock(&LOCK_localtime_r);
  141.   tmp= gmtime(clock);
  142.   *res= *tmp;
  143.   pthread_mutex_unlock(&LOCK_localtime_r);
  144.   return res;
  145. }
  146. #endif
  147. /****************************************************************************
  148. ** Replacement of sigwait if the system doesn't have one (like BSDI 3.0)
  149. **
  150. ** Note:
  151. ** This version of sigwait() is assumed to called in a loop so the signalmask
  152. ** is permanently modified to reflect the signal set. This is done to get
  153. ** a much faster implementation.
  154. **
  155. ** This implementation isn't thread safe: It assumes that only one
  156. ** thread is using sigwait.
  157. **
  158. ** If one later supplies a different signal mask, all old signals that
  159. ** was used before are unblocked and set to SIGDFL.
  160. **
  161. ** Author: Gary Wisniewski <garyw@spidereye.com.au>, much modified by Monty
  162. ****************************************************************************/
  163. #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) && !defined(OS2)
  164. #if !defined(DONT_USE_SIGSUSPEND)
  165. static sigset_t sigwait_set,rev_sigwait_set,px_recd;
  166. void px_handle_sig(int sig)
  167. {
  168.   sigaddset(&px_recd, sig);
  169. }
  170. void sigwait_setup(sigset_t *set)
  171. {
  172.   int i;
  173.   struct sigaction sact,sact1;
  174.   sigset_t unblock_mask;
  175.   sact.sa_flags = 0;
  176.   sact.sa_handler = px_handle_sig;
  177.   memcpy_fixed(&sact.sa_mask,set,sizeof(*set)); /* handler isn't thread_safe */
  178.   sigemptyset(&unblock_mask);
  179.   pthread_sigmask(SIG_UNBLOCK,(sigset_t*) 0,&rev_sigwait_set);
  180.   for (i = 1; i <= sizeof(sigwait_set)*8; i++)
  181.   {
  182.     if (sigismember(set,i))
  183.     {
  184.       sigdelset(&rev_sigwait_set,i);
  185.       if (!sigismember(&sigwait_set,i))
  186. sigaction(i, &sact, (struct sigaction*) 0);
  187.     }
  188.     else
  189.     {
  190.       sigdelset(&px_recd,i); /* Don't handle this */
  191.       if (sigismember(&sigwait_set,i))
  192.       { /* Remove the old handler */
  193. sigaddset(&unblock_mask,i);
  194. sigdelset(&rev_sigwait_set,i);
  195. sact1.sa_flags = 0;
  196. sact1.sa_handler = SIG_DFL;
  197. sigemptyset(&sact1.sa_mask);
  198. sigaction(i, &sact1, 0);
  199.       }
  200.     }
  201.   }
  202.   memcpy_fixed(&sigwait_set,set,sizeof(*set));
  203.   pthread_sigmask(SIG_BLOCK,(sigset_t*) set,(sigset_t*) 0);
  204.   pthread_sigmask(SIG_UNBLOCK,&unblock_mask,(sigset_t*) 0);
  205. }
  206. int sigwait(sigset_t *setp, int *sigp)
  207. {
  208.   if (memcmp(setp,&sigwait_set,sizeof(sigwait_set)))
  209.     sigwait_setup(setp); /* Init or change of set */
  210.   for (;;)
  211.   {
  212.     /*
  213.       This is a fast, not 100% portable implementation to find the signal.
  214.       Because the handler is blocked there should be at most 1 bit set, but
  215.       the specification on this is somewhat shady so we use a set instead a
  216.       single variable.
  217.       */
  218.     ulong *ptr= (ulong*) &px_recd;
  219.     ulong *end=ptr+sizeof(px_recd)/sizeof(ulong);
  220.     for ( ; ptr != end ; ptr++)
  221.     {
  222.       if (*ptr)
  223.       {
  224. ulong set= *ptr;
  225. int found= (int) ((char*) ptr - (char*) &px_recd)*8+1;
  226. while (!(set & 1))
  227. {
  228.   found++;
  229.   set>>=1;
  230. }
  231. *sigp=found;
  232. sigdelset(&px_recd,found);
  233. return 0;
  234.       }
  235.     }
  236.     sigsuspend(&rev_sigwait_set);
  237.   }
  238.   return 0;
  239. }
  240. #else  /* !DONT_USE_SIGSUSPEND */
  241. /****************************************************************************
  242. ** Replacement of sigwait if the system doesn't have one (like BSDI 3.0)
  243. **
  244. ** Note:
  245. ** This version of sigwait() is assumed to called in a loop so the signalmask
  246. ** is permanently modified to reflect the signal set. This is done to get
  247. ** a much faster implementation.
  248. **
  249. ** This implementation uses a extra thread to handle the signals and one
  250. ** must always call sigwait() with the same signal mask!
  251. **
  252. ** BSDI 3.0 NOTE:
  253. **
  254. ** pthread_kill() doesn't work on a thread in a select() or sleep() loop?
  255. ** After adding the sleep to sigwait_thread, all signals are checked and
  256. ** delivered every second. This isn't that terrible performance vice, but
  257. ** someone should report this to BSDI and ask for a fix!
  258. ** Another problem is that when the sleep() ends, every select() in other
  259. ** threads are interrupted!
  260. ****************************************************************************/
  261. static sigset_t pending_set;
  262. static bool inited=0;
  263. static pthread_cond_t  COND_sigwait;
  264. static pthread_mutex_t LOCK_sigwait;
  265. void sigwait_handle_sig(int sig)
  266. {
  267.   pthread_mutex_lock(&LOCK_sigwait);
  268.   sigaddset(&pending_set, sig);
  269.   VOID(pthread_cond_signal(&COND_sigwait)); /* inform sigwait() about signal */
  270.   pthread_mutex_unlock(&LOCK_sigwait);
  271. }
  272. extern pthread_t alarm_thread;
  273. void *sigwait_thread(void *set_arg)
  274. {
  275.   sigset_t *set=(sigset_t*) set_arg;
  276.   int i;
  277.   struct sigaction sact;
  278.   sact.sa_flags = 0;
  279.   sact.sa_handler = sigwait_handle_sig;
  280.   memcpy_fixed(&sact.sa_mask,set,sizeof(*set)); /* handler isn't thread_safe */
  281.   sigemptyset(&pending_set);
  282.   for (i = 1; i <= sizeof(pending_set)*8; i++)
  283.   {
  284.     if (sigismember(set,i))
  285.     {
  286.       sigaction(i, &sact, (struct sigaction*) 0);
  287.     }
  288.   }
  289.   sigaddset(set,THR_CLIENT_ALARM);
  290.   pthread_sigmask(SIG_UNBLOCK,(sigset_t*) set,(sigset_t*) 0);
  291.   alarm_thread=pthread_self(); /* For thr_alarm */
  292.   for (;;)
  293.   { /* Wait for signals */
  294. #ifdef HAVE_NOT_BROKEN_SELECT
  295.     fd_set fd;
  296.     FD_ZERO(&fd);
  297.     select(0,&fd,0,0,0);
  298. #else
  299.     sleep(1); /* Because of broken BSDI */
  300. #endif
  301.   }
  302. }
  303. int sigwait(sigset_t *setp, int *sigp)
  304. {
  305.   if (!inited)
  306.   {
  307.     pthread_attr_t thr_attr;
  308.     pthread_t sigwait_thread_id;
  309.     inited=1;
  310.     sigemptyset(&pending_set);
  311.     pthread_mutex_init(&LOCK_sigwait,MY_MUTEX_INIT_FAST);
  312.     pthread_cond_init(&COND_sigwait,NULL);
  313.     pthread_attr_init(&thr_attr);
  314.     pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS);
  315.     pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED);
  316.     pthread_attr_setstacksize(&thr_attr,8196);
  317.     my_pthread_attr_setprio(&thr_attr,100); /* Very high priority */
  318.     VOID(pthread_create(&sigwait_thread_id,&thr_attr,sigwait_thread,setp));
  319.     VOID(pthread_attr_destroy(&thr_attr));
  320.   }
  321.   pthread_mutex_lock(&LOCK_sigwait);
  322.   for (;;)
  323.   {
  324.     ulong *ptr= (ulong*) &pending_set;
  325.     ulong *end=ptr+sizeof(pending_set)/sizeof(ulong);
  326.     for ( ; ptr != end ; ptr++)
  327.     {
  328.       if (*ptr)
  329.       {
  330. ulong set= *ptr;
  331. int found= (int) ((char*) ptr - (char*) &pending_set)*8+1;
  332. while (!(set & 1))
  333. {
  334.   found++;
  335.   set>>=1;
  336. }
  337. *sigp=found;
  338. sigdelset(&pending_set,found);
  339. pthread_mutex_unlock(&LOCK_sigwait);
  340. return 0;
  341.       }
  342.     }
  343.     VOID(pthread_cond_wait(&COND_sigwait,&LOCK_sigwait));
  344.   }
  345.   return 0;
  346. }
  347. #endif /* DONT_USE_SIGSUSPEND */
  348. #endif /* HAVE_SIGWAIT */
  349. /****************************************************************************
  350.  The following functions fixes that all pthread functions should work
  351.  according to latest posix standard
  352. ****************************************************************************/
  353. /* Undefined wrappers set my_pthread.h so that we call os functions */
  354. #undef pthread_mutex_init
  355. #undef pthread_mutex_lock
  356. #undef pthread_mutex_unlock
  357. #undef pthread_mutex_destroy
  358. #undef pthread_mutex_wait
  359. #undef pthread_mutex_timedwait
  360. #undef pthread_mutex_trylock
  361. #undef pthread_mutex_t
  362. #undef pthread_cond_init
  363. #undef pthread_cond_wait
  364. #undef pthread_cond_timedwait
  365. #undef pthread_cond_t
  366. #undef pthread_attr_getstacksize
  367. /*****************************************************************************
  368. ** Patches for AIX and DEC OSF/1 3.2
  369. *****************************************************************************/
  370. #if (defined(HAVE_NONPOSIX_PTHREAD_MUTEX_INIT) && !defined(HAVE_UNIXWARE7_THREADS)) || defined(HAVE_DEC_3_2_THREADS)
  371. #include <netdb.h>
  372. int my_pthread_mutex_init(pthread_mutex_t *mp, const pthread_mutexattr_t *attr)
  373. {
  374.   int error;
  375.   if (!attr)
  376.     error=pthread_mutex_init(mp,pthread_mutexattr_default);
  377.   else
  378.     error=pthread_mutex_init(mp,*attr);
  379.   return error;
  380. }
  381. int my_pthread_cond_init(pthread_cond_t *mp, const pthread_condattr_t *attr)
  382. {
  383.   int error;
  384.   if (!attr)
  385.     error=pthread_cond_init(mp,pthread_condattr_default);
  386.   else
  387.     error=pthread_cond_init(mp,*attr);
  388.   return error;
  389. }
  390. #endif
  391. /*****************************************************************************
  392.   Patches for HPUX
  393.   We need these because the pthread_mutex.. code returns -1 on error,
  394.   instead of the error code.
  395.   Note that currently we only remap pthread_ functions used by MySQL.
  396.   If we are depending on the value for some other pthread_xxx functions,
  397.   this has to be added here.
  398. ****************************************************************************/
  399. #if defined(HPUX10) || defined(HAVE_BROKEN_PTHREAD_COND_TIMEDWAIT)
  400. int my_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
  401.       struct timespec *abstime)
  402. {
  403.   int error=pthread_cond_timedwait(cond, mutex, abstime);
  404.   if (error == -1) /* Safety if the lib is fixed */
  405.   {
  406.     if (!(error=errno))
  407.       error= ETIMEDOUT; /* Can happen on HPUX */
  408.   }
  409.   if (error == EAGAIN) /* Correct errno to Posix */
  410.     error= ETIMEDOUT;
  411.   return error;
  412. }
  413. #endif
  414. #if defined(HPUX10)
  415. void my_pthread_attr_getstacksize(pthread_attr_t *connection_attrib,
  416.   size_t *stack_size)
  417. {
  418.   *stack_size= pthread_attr_getstacksize(*connection_attrib);
  419. }
  420. #endif
  421. #ifdef HAVE_POSIX1003_4a_MUTEX
  422. /*
  423.   In HP-UX-10.20 and other old Posix 1003.4a Draft 4 implementations
  424.   pthread_mutex_trylock returns 1 on success, not 0 like
  425.   pthread_mutex_lock
  426.   From the HP-UX-10.20 man page:
  427.   RETURN VALUES
  428.       If the function fails, errno may be set to one of the following
  429.       values:
  430.            Return | Error    | Description
  431.            _______|__________|_________________________________________
  432.               1   |          | Successful completion.
  433.               0   |          | The mutex is  locked; therefore, it was
  434.                   |          | not acquired.
  435.              -1   | [EINVAL] | The value specified by mutex is invalid.
  436. */
  437. /*
  438.   Convert pthread_mutex_trylock to return values according to latest POSIX
  439.   RETURN VALUES
  440.   0 If we are able successfully lock the mutex.
  441.   EBUSY Mutex was locked by another thread
  442.   # Other error number returned by pthread_mutex_trylock()
  443. (Not likely)  
  444. */
  445. int my_pthread_mutex_trylock(pthread_mutex_t *mutex)
  446. {
  447.   int error= pthread_mutex_trylock(mutex);
  448.   if (error == 1)
  449.     return 0; /* Got lock on mutex */
  450.   if (error == 0) /* Someon else is locking mutex */
  451.     return EBUSY;
  452.   if (error == -1) /* Safety if the lib is fixed */
  453.     error= errno; /* Probably invalid parameter */
  454.    return error;
  455. }
  456. #endif /* HAVE_POSIX1003_4a_MUTEX */
  457. /* Some help functions */
  458. int pthread_no_free(void *not_used __attribute__((unused)))
  459. {
  460.   return 0;
  461. }
  462. int pthread_dummy(int ret)
  463. {
  464.   return ret;
  465. }
  466. #endif /* THREAD */