aboutsummaryrefslogtreecommitdiff
path: root/mariadb-connector-c-v_2.3.7/libmariadb/my_pthread.c
diff options
context:
space:
mode:
Diffstat (limited to 'mariadb-connector-c-v_2.3.7/libmariadb/my_pthread.c')
-rw-r--r--mariadb-connector-c-v_2.3.7/libmariadb/my_pthread.c555
1 files changed, 555 insertions, 0 deletions
diff --git a/mariadb-connector-c-v_2.3.7/libmariadb/my_pthread.c b/mariadb-connector-c-v_2.3.7/libmariadb/my_pthread.c
new file mode 100644
index 0000000..ea804c1
--- /dev/null
+++ b/mariadb-connector-c-v_2.3.7/libmariadb/my_pthread.c
@@ -0,0 +1,555 @@
+/* Copyright (C) 2000 MySQL AB
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with this library; if not, write to the Free
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02111-1301, USA */
+
+/* Functions to get threads more portable */
+
+#define DONT_REMAP_PTHREAD_FUNCTIONS
+
+#include "mysys_priv.h"
+#ifdef THREAD
+#include <signal.h>
+#include <m_string.h>
+#include <thr_alarm.h>
+#include <assert.h>
+
+#ifdef _WIN32
+
+int
+pthread_cond_init (pthread_cond_t *cv, const pthread_condattr_t *attr)
+{
+ DBUG_ENTER("pthread_cond_init");
+ /* Initialize the count to 0 */
+ InitializeCriticalSection(&cv->waiters_count_lock);
+ cv->waiting = 0;
+
+ /* Create an auto-reset and manual-reset event */
+ if (!(cv->events[SIGNAL] = CreateEvent (NULL, FALSE, FALSE, NULL)) ||
+ !(cv->events[BROADCAST] = CreateEvent (NULL, TRUE, FALSE, NULL)))
+ {
+ DBUG_RETURN(GetLastError());
+ }
+ DBUG_RETURN(0);
+}
+
+int pthread_cond_timedwait(pthread_cond_t *cond,
+ pthread_mutex_t *mutex,
+ struct timespec *abstime)
+{
+ int result= 0;
+ return result == WAIT_TIMEOUT ? ETIMEDOUT : 0;
+}
+
+int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex)
+{
+ return pthread_cond_timedwait(cv,mutex,NULL);
+}
+
+int pthread_cond_destroy(pthread_cond_t *cv)
+{
+ DeleteCriticalSection(&cv->waiters_count_lock);
+
+ if (CloseHandle(cv->events[SIGNAL]) == 0 ||
+ CloseHandle(cv->events[BROADCAST]) == 0)
+ return EINVAL;
+ return 0;
+}
+
+#endif
+
+#if (defined(__BSD__) || defined(_BSDI_VERSION)) && !defined(HAVE_mit_thread)
+#define SCHED_POLICY SCHED_RR
+#else
+#define SCHED_POLICY SCHED_OTHER
+#endif
+
+#ifndef my_pthread_setprio
+void my_pthread_setprio(pthread_t thread_id,int prior)
+{
+#ifdef HAVE_PTHREAD_SETSCHEDPARAM
+ struct sched_param tmp_sched_param;
+ bzero((char*) &tmp_sched_param,sizeof(tmp_sched_param));
+ tmp_sched_param.sched_priority=prior;
+ VOID(pthread_setschedparam(thread_id,SCHED_POLICY,&tmp_sched_param));
+#endif
+}
+#endif
+
+#ifndef my_pthread_getprio
+int my_pthread_getprio(pthread_t thread_id)
+{
+#ifdef HAVE_PTHREAD_SETSCHEDPARAM
+ struct sched_param tmp_sched_param;
+ int policy;
+ if (!pthread_getschedparam(thread_id,&policy,&tmp_sched_param))
+ {
+ DBUG_PRINT("thread",("policy: %d priority: %d",
+ policy,tmp_sched_param.sched_priority));
+ return tmp_sched_param.sched_priority;
+ }
+#endif
+ return -1;
+}
+#endif
+
+#ifndef my_pthread_attr_setprio
+void my_pthread_attr_setprio(pthread_attr_t *attr, int priority)
+{
+#ifdef HAVE_PTHREAD_SETSCHEDPARAM
+ struct sched_param tmp_sched_param;
+ bzero((char*) &tmp_sched_param,sizeof(tmp_sched_param));
+ tmp_sched_param.sched_priority=priority;
+ VOID(pthread_attr_setschedparam(attr,&tmp_sched_param));
+#endif
+}
+#endif
+
+
+/* To allow use of pthread_getspecific with two arguments */
+
+#ifdef HAVE_NONPOSIX_PTHREAD_GETSPECIFIC
+#undef pthread_getspecific
+#ifdef HAVE_UNIXWARE7_THREADS
+#define pthread_getspecific thr_getspecific
+#endif
+
+void *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, AIX, Siemens Unix and UnixWare 7
+ (and DEC OSF/1 3.2 too) */
+
+int my_pthread_create_detached=1;
+
+#if defined(HAVE_NONPOSIX_SIGWAIT) || defined(HAVE_DEC_3_2_THREADS)
+
+int my_sigwait(const sigset_t *set,int *sig)
+{
+ int signal=sigwait((sigset_t*) set);
+ if (signal < 0)
+ return errno;
+ *sig=signal;
+ return 0;
+}
+#endif
+
+/* localtime_r for SCO 3.2V4.2 */
+
+#ifndef HAVE_LOCALTIME_R
+
+extern pthread_mutex_t LOCK_localtime_r;
+
+struct tm *localtime_r(const time_t *clock, struct tm *res)
+{
+ struct tm *tmp;
+ pthread_mutex_lock(&LOCK_localtime_r);
+ tmp=localtime(clock);
+ *res= *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) && !defined(HAVE_NONPOSIX_SIGWAIT) && !defined(HAVE_DEC_3_2_THREADS) && !defined(OS2)
+
+#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_fixed(&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_fixed(&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_fixed(&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,MY_MUTEX_INIT_FAST);
+ pthread_cond_init(&COND_sigwait,NULL);
+
+ pthread_attr_init(&thr_attr);
+ pthread_attr_setscope(&thr_attr,PTHREAD_SCOPE_PROCESS);
+ 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_SIGNAL
+
+int 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
+
+/****************************************************************************
+ The following functions fixes that all pthread functions should work
+ according to latest posix standard
+****************************************************************************/
+
+/* Undefined wrappers set my_pthread.h so that we call os functions */
+#undef pthread_mutex_init
+#undef pthread_mutex_lock
+#undef pthread_mutex_unlock
+#undef pthread_mutex_destroy
+#undef pthread_mutex_wait
+#undef pthread_mutex_timedwait
+#undef pthread_mutex_trylock
+#undef pthread_mutex_t
+#undef pthread_cond_init
+#undef pthread_cond_wait
+#undef pthread_cond_timedwait
+#undef pthread_cond_t
+
+
+/*****************************************************************************
+** Patches for AIX and DEC OSF/1 3.2
+*****************************************************************************/
+
+#if (defined(HAVE_NONPOSIX_PTHREAD_MUTEX_INIT) && !defined(HAVE_UNIXWARE7_THREADS)) || defined(HAVE_DEC_3_2_THREADS)
+
+#include <netdb.h>
+
+int 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;
+}
+
+#endif
+
+
+/*****************************************************************************
+ Patches for HPUX
+ We need these because the pthread_mutex.. code returns -1 on error,
+ instead of the error code.
+
+ Note that currently we only remap pthread_ functions used by MySQL.
+ If we are depending on the value for some other pthread_xxx functions,
+ this has to be added here.
+****************************************************************************/
+
+#if defined(HPUX) || defined(HAVE_BROKEN_PTHREAD_COND_TIMEDWAIT)
+
+int my_pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
+ struct timespec *abstime)
+{
+ int error=pthread_cond_timedwait(cond, mutex, abstime);
+ if (error == -1) /* Safety if the lib is fixed */
+ {
+ if (!(error=errno))
+ error= ETIMEDOUT; /* Can happen on HPUX */
+ }
+ if (error == EAGAIN) /* Correct errno to Posix */
+ error= ETIMEDOUT;
+ return error;
+}
+#endif
+
+
+#ifdef HAVE_POSIX1003_4a_MUTEX
+/*
+ In HP-UX-10.20 and other old Posix 1003.4a Draft 4 implementations
+ pthread_mutex_trylock returns 1 on success, not 0 like
+ pthread_mutex_lock
+
+ From the HP-UX-10.20 man page:
+ RETURN VALUES
+ If the function fails, errno may be set to one of the following
+ values:
+ Return | Error | Description
+ _______|__________|_________________________________________
+ 1 | | Successful completion.
+ 0 | | The mutex is locked; therefore, it was
+ | | not acquired.
+ -1 | [EINVAL] | The value specified by mutex is invalid.
+
+*/
+
+/*
+ Convert pthread_mutex_trylock to return values according to latest POSIX
+
+ RETURN VALUES
+ 0 If we are able successfully lock the mutex.
+ EBUSY Mutex was locked by another thread
+ # Other error number returned by pthread_mutex_trylock()
+ (Not likely)
+*/
+
+int my_pthread_mutex_trylock(pthread_mutex_t *mutex)
+{
+ int error= pthread_mutex_trylock(mutex);
+ if (error == 1)
+ return 0; /* Got lock on mutex */
+ if (error == 0) /* Someon else is locking mutex */
+ return EBUSY;
+ if (error == -1) /* Safety if the lib is fixed */
+ error= errno; /* Probably invalid parameter */
+ return error;
+}
+#endif /* HAVE_POSIX1003_4a_MUTEX */
+
+/* Some help functions */
+
+int pthread_no_free(void *not_used __attribute__((unused)))
+{
+ return 0;
+}
+
+int pthread_dummy(int ret)
+{
+ return ret;
+}
+#endif /* THREAD */