?? my_pthread.c
字號:
/* Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB This file is public domain and comes with NO WARRANTY of any kind *//* Functions to get threads more portable */#include "mysys_priv.h"#ifdef THREAD#include <signal.h>#include <m_string.h>#include <thr_alarm.h>pthread_key(int,THR_KEY_my_errno);pthread_key(int,THR_KEY_cmp_length);pthread_key(int,THR_KEY_abort);pthread_mutex_t THR_LOCK_malloc,THR_LOCK_open,THR_LOCK_keycache, THR_LOCK_lock,THR_LOCK_isam;#ifndef HAVE_LOCALTIME_Rpthread_mutex_t LOCK_localtime_r;#endifmy_bool my_thread_global_init(void){ if (pthread_key_create(&THR_KEY_my_errno,free) || pthread_key_create(&THR_KEY_cmp_length,free) || pthread_key_create(&THR_KEY_abort,free)) { fprintf(stderr,"Can't initialize threads: error %d\n",errno); exit(1); } pthread_mutex_init(&THR_LOCK_malloc,NULL); pthread_mutex_init(&THR_LOCK_open,NULL); pthread_mutex_init(&THR_LOCK_keycache,NULL); pthread_mutex_init(&THR_LOCK_lock,NULL); pthread_mutex_init(&THR_LOCK_isam,NULL);#ifndef HAVE_LOCALTIME_R pthread_mutex_init(&LOCK_localtime_r,NULL);#endif return my_thread_init();}my_bool my_thread_init(void){#ifndef __WIN32__ char *tmp; if (!my_pthread_getspecific(int*,THR_KEY_my_errno)) { /* Safequard */ /* We must have 3 calloc() here because these are freed on pthread_exit */ if (!(tmp=calloc(1,sizeof(int))) || pthread_setspecific(THR_KEY_my_errno,tmp) || !(tmp=calloc(1,sizeof(int))) || pthread_setspecific(THR_KEY_cmp_length,tmp) || !(tmp=calloc(1,sizeof(int))) || pthread_setspecific(THR_KEY_abort,tmp)) return 1; }#else THR_KEY_my_errno=THR_KEY_abort=0;#endif return 0;}int *_my_errno(void){ return my_pthread_getspecific(int*,THR_KEY_my_errno);}#ifndef my_pthread_setpriovoid my_pthread_setprio(pthread_t thread_id,int prior){#ifdef HAVE_PTHREAD_SETSCHEDPARAM struct sched_param sched_param; bzero(&sched_param,sizeof(sched_param)); sched_param.sched_priority=prior; VOID(pthread_setschedparam(thread_id,SCHED_OTHER,&sched_param));#endif}#endif#ifndef __WIN32__int my_pthread_getprio(pthread_t thread_id){#ifdef HAVE_PTHREAD_SETSCHEDPARAM struct sched_param sched_param; int policy; if (!pthread_getschedparam(thread_id,&policy,&sched_param)) { DBUG_PRINT("thread",("policy: %d priority: %d", policy,sched_param.sched_priority)); return sched_param.sched_priority; }#endif return -1;}#endif#ifndef my_pthread_attr_setpriovoid my_pthread_attr_setprio(pthread_attr_t *attr, int priority){#ifdef HAVE_PTHREAD_SETSCHEDPARAM struct sched_param sched_param; bzero(&sched_param,sizeof(sched_param)); sched_param.sched_priority=priority; VOID(pthread_attr_setschedparam(attr,&sched_param));#endif}#endif/* To allow use of pthread_getspecific with two arguments */#ifdef HAVE_NONPOSIX_PTHREAD_GETSPECIFIC#undef pthread_getspecificvoid *my_pthread_getspecific_imp(pthread_key_t key){ void *value; if (pthread_getspecific(key,(void *) &value)) return 0; return value;}#endif/* Some functions for RTS threads */#if defined(HAVE_rts_threads) || defined(AIX_3_2)int my_pthread_create_detached=1;int my_sigwait(sigset_t *set,int *sig){ int signal=sigwait(set); if (signal < 0) return errno; *sig=signal; return 0;}#endif/* localtime_r for SCO 3.2V4.2 */#ifndef HAVE_LOCALTIME_Rstruct tm *localtime_r(const time_t *clock, struct tm *res){ struct tm *tmp; pthread_mutex_lock(&LOCK_localtime_r); tmp=localtime(clock); memcpy(res,tmp,sizeof(*tmp)); pthread_mutex_unlock(&LOCK_localtime_r); return res;}#endif/****************************************************************************** Replacement of sigwait if the system doesn't have one (like BSDI 3.0)**** Note:** This version of sigwait() is assumed to called in a loop so the signalmask** is permanently modified to reflect the signal set. This is done to get** a much faster implementation.**** This implementation isn't thread safe: It assumes that only one** thread is using sigwait.**** If one later supplies a different signal mask, all old signals that** was used before are unblocked and set to SIGDFL.**** Author: Gary Wisniewski <garyw@spidereye.com.au>, much modified by Monty****************************************************************************/#if !defined(HAVE_SIGWAIT) && !defined(HAVE_mit_thread) && !defined(sigwait) && !defined(__WIN32__) && !defined(HAVE_rts_threads)#if !defined(DONT_USE_SIGSUSPEND)static sigset_t sigwait_set,rev_sigwait_set,px_recd;void px_handle_sig(int sig){ sigaddset(&px_recd, sig);}void sigwait_setup(sigset_t *set){ int i; struct sigaction sact,sact1; sigset_t unblock_mask; sact.sa_flags = 0; sact.sa_handler = px_handle_sig; memcpy(&sact.sa_mask,set,sizeof(*set)); /* handler isn't thread_safe */ sigemptyset(&unblock_mask); pthread_sigmask(SIG_UNBLOCK,(sigset_t*) 0,&rev_sigwait_set); for (i = 1; i <= sizeof(sigwait_set)*8; i++) { if (sigismember(set,i)) { sigdelset(&rev_sigwait_set,i); if (!sigismember(&sigwait_set,i)) sigaction(i, &sact, (struct sigaction*) 0); } else { sigdelset(&px_recd,i); /* Don't handle this */ if (sigismember(&sigwait_set,i)) { /* Remove the old handler */ sigaddset(&unblock_mask,i); sigdelset(&rev_sigwait_set,i); sact1.sa_flags = 0; sact1.sa_handler = SIG_DFL; sigemptyset(&sact1.sa_mask); sigaction(i, &sact1, 0); } } } memcpy(&sigwait_set,set,sizeof(*set)); pthread_sigmask(SIG_BLOCK,(sigset_t*) set,(sigset_t*) 0); pthread_sigmask(SIG_UNBLOCK,&unblock_mask,(sigset_t*) 0);}int sigwait(sigset_t *setp, int *sigp){ if (memcmp(setp,&sigwait_set,sizeof(sigwait_set))) sigwait_setup(setp); /* Init or change of set */ for (;;) { /* This is a fast, not 100% portable implementation to find the signal. Because the handler is blocked there should be at most 1 bit set, but the specification on this is somewhat shady so we use a set instead a single variable. */ ulong *ptr= (ulong*) &px_recd; ulong *end=ptr+sizeof(px_recd)/sizeof(ulong); for ( ; ptr != end ; ptr++) { if (*ptr) { ulong set= *ptr; int found= (int) ((char*) ptr - (char*) &px_recd)*8+1; while (!(set & 1)) { found++; set>>=1; } *sigp=found; sigdelset(&px_recd,found); return 0; } } sigsuspend(&rev_sigwait_set); } return 0;}#else /* !DONT_USE_SIGSUSPEND *//****************************************************************************** Replacement of sigwait if the system doesn't have one (like BSDI 3.0)**** Note:** This version of sigwait() is assumed to called in a loop so the signalmask** is permanently modified to reflect the signal set. This is done to get** a much faster implementation.**** This implementation uses a extra thread to handle the signals and one** must always call sigwait() with the same signal mask!**** BSDI 3.0 NOTE:**** pthread_kill() doesn't work on a thread in a select() or sleep() loop?** After adding the sleep to sigwait_thread, all signals are checked and** delivered every second. This isn't that terrible performance vice, but** someone should report this to BSDI and ask for a fix!** Another problem is that when the sleep() ends, every select() in other** threads are interrupted!****************************************************************************/static sigset_t pending_set;static bool inited=0;static pthread_cond_t COND_sigwait;static pthread_mutex_t LOCK_sigwait;void sigwait_handle_sig(int sig){ pthread_mutex_lock(&LOCK_sigwait); sigaddset(&pending_set, sig); VOID(pthread_cond_signal(&COND_sigwait)); /* inform sigwait() about signal */ pthread_mutex_unlock(&LOCK_sigwait);}extern pthread_t alarm_thread;void *sigwait_thread(void *set_arg){ sigset_t *set=(sigset_t*) set_arg; int i; struct sigaction sact; sact.sa_flags = 0; sact.sa_handler = sigwait_handle_sig; memcpy(&sact.sa_mask,set,sizeof(*set)); /* handler isn't thread_safe */ sigemptyset(&pending_set); for (i = 1; i <= sizeof(pending_set)*8; i++) { if (sigismember(set,i)) { sigaction(i, &sact, (struct sigaction*) 0); } } sigaddset(set,THR_CLIENT_ALARM); pthread_sigmask(SIG_UNBLOCK,(sigset_t*) set,(sigset_t*) 0); alarm_thread=pthread_self(); /* For thr_alarm */ for (;;) { /* Wait for signals */#ifdef HAVE_NOT_BROKEN_SELECT fd_set fd; FD_ZERO(&fd); select(0,&fd,0,0,0);#else sleep(1); /* Because of broken BSDI */#endif }}int sigwait(sigset_t *setp, int *sigp){ if (!inited) { pthread_attr_t thr_attr; pthread_t sigwait_thread_id; inited=1; sigemptyset(&pending_set); pthread_mutex_init(&LOCK_sigwait,NULL); pthread_cond_init(&COND_sigwait,NULL); pthread_attr_init(&thr_attr); pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_SYSTEM); pthread_attr_setdetachstate(&thr_attr,PTHREAD_CREATE_DETACHED); pthread_attr_setstacksize(&thr_attr,8196); my_pthread_attr_setprio(&thr_attr,100); /* Very high priority */ VOID(pthread_create(&sigwait_thread_id,&thr_attr,sigwait_thread,setp)); VOID(pthread_attr_destroy(&thr_attr)); } pthread_mutex_lock(&LOCK_sigwait); for (;;) { ulong *ptr= (ulong*) &pending_set; ulong *end=ptr+sizeof(pending_set)/sizeof(ulong); for ( ; ptr != end ; ptr++) { if (*ptr) { ulong set= *ptr; int found= (int) ((char*) ptr - (char*) &pending_set)*8+1; while (!(set & 1)) { found++; set>>=1; } *sigp=found; sigdelset(&pending_set,found); pthread_mutex_unlock(&LOCK_sigwait); return 0; } } VOID(pthread_cond_wait(&COND_sigwait,&LOCK_sigwait)); } return 0;}#endif /* DONT_USE_SIGSUSPEND */#endif /* HAVE_SIGWAIT *//******************************************************************************* Implement pthread_signal for systems that can't use signal() with threads** Currently this is only used with BSDI 3.0*****************************************************************************/#ifdef USE_PTHREAD_SIGNALint pthread_signal(int sig, void (*func)()){ struct sigaction sact; sact.sa_flags= 0; sact.sa_handler= func; sigemptyset(&sact.sa_mask); sigaction(sig, &sact, (struct sigaction*) 0); return 0;}#endif/******************************************************************************* Patches for AIX*****************************************************************************/#ifdef AIX_3_2#undef pthread_mutex_init#undef pthread_cond_initint my_pthread_mutex_init(pthread_mutex_t *mp, const pthread_mutexattr_t *attr){ int error; if (!attr) error=pthread_mutex_init(mp,pthread_mutexattr_default); else error=pthread_mutex_init(mp,*attr); return error;}int my_pthread_cond_init(pthread_cond_t *mp, const pthread_condattr_t *attr){ int error; if (!attr) error=pthread_cond_init(mp,pthread_condattr_default); else error=pthread_cond_init(mp,*attr); return error;}int pthread_no_free(void *not_used){ return 0;}int pthread_dummy(int ret){ return ret;}#endif#endif /* THREAD */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -