summaryrefslogtreecommitdiff
path: root/mysys/thr_alarm.c
diff options
context:
space:
mode:
Diffstat (limited to 'mysys/thr_alarm.c')
-rw-r--r--mysys/thr_alarm.c184
1 files changed, 124 insertions, 60 deletions
diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c
index f51f27b7f51..d1343d4c2d3 100644
--- a/mysys/thr_alarm.c
+++ b/mysys/thr_alarm.c
@@ -1,21 +1,23 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult 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,
+/* Copyright (C) 2000 MySQL AB
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program 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., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-#include <global.h>
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/* To avoid problems with alarms in debug code, we disable DBUG here */
+#undef DBUG_OFF
+#define DBUG_OFF
+#include <my_global.h>
#if defined(THREAD) && !defined(DONT_USE_THR_ALARM)
#include <errno.h>
@@ -37,11 +39,14 @@
static my_bool alarm_aborted=1;
my_bool thr_alarm_inited=0;
+static sig_handler process_alarm_part2(int sig);
+
#if !defined(__WIN__) && !defined(__EMX__) && !defined(OS2)
static pthread_mutex_t LOCK_alarm;
static sigset_t full_signal_set;
static QUEUE alarm_queue;
+static uint max_used_alarms=0;
pthread_t alarm_thread;
#ifdef USE_ALARM_THREAD
@@ -114,10 +119,10 @@ void init_thr_alarm(uint max_alarms)
}
/*
-** Request alarm after sec seconds.
-** A pointer is returned with points to a non-zero int when the alarm has been
-** given. This can't be called from the alarm-handling thread.
-** Returns 0 if no more alarms are allowed (aborted by process)
+ Request alarm after sec seconds.
+ A pointer is returned with points to a non-zero int when the alarm has been
+ given. This can't be called from the alarm-handling thread.
+ Returns 0 if no more alarms are allowed (aborted by process)
*/
bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
@@ -138,13 +143,17 @@ bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
DBUG_RETURN(1);
}
- if (alarm_queue.elements == alarm_queue.max_elements)
+ if (alarm_queue.elements >= max_used_alarms)
{
- DBUG_PRINT("info", ("alarm queue full"));
- fprintf(stderr,"Warning: thr_alarm queue is full\n");
- pthread_mutex_unlock(&LOCK_alarm);
- pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
- DBUG_RETURN(1);
+ if (alarm_queue.elements == alarm_queue.max_elements)
+ {
+ DBUG_PRINT("info", ("alarm queue full"));
+ fprintf(stderr,"Warning: thr_alarm queue is full\n");
+ pthread_mutex_unlock(&LOCK_alarm);
+ pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
+ DBUG_RETURN(1);
+ }
+ max_used_alarms=alarm_queue.elements+1;
}
reschedule= (!alarm_queue.elements ||
(int) (((ALARM*) queue_top(&alarm_queue))->expire_time - now) >
@@ -184,7 +193,7 @@ bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data)
/*
-** Remove alarm from list of alarms
+ Remove alarm from list of alarms
*/
void thr_end_alarm(thr_alarm_t *alarmed)
@@ -216,7 +225,8 @@ void thr_end_alarm(thr_alarm_t *alarmed)
printf("Warning: Didn't find alarm %lx in queue of %d alarms\n",
(long) *alarmed, alarm_queue.elements);
#endif
- DBUG_PRINT("warning",("Didn't find alarm %lx in queue\n",*alarmed));
+ DBUG_PRINT("warning",("Didn't find alarm %lx in queue\n",
+ (long) *alarmed));
}
if (alarm_aborted && !alarm_queue.elements)
delete_queue(&alarm_queue);
@@ -225,20 +235,20 @@ void thr_end_alarm(thr_alarm_t *alarmed)
DBUG_VOID_RETURN;
}
- /*
- Come here when some alarm in queue is due.
- Mark all alarms with are finnished in list.
- Shedule alarms to be sent again after 1-10 sec (many alarms at once)
- If alarm_aborted is set then all alarms are given and resent
- every second.
- */
+/*
+ Come here when some alarm in queue is due.
+ Mark all alarms with are finnished in list.
+ Shedule alarms to be sent again after 1-10 sec (many alarms at once)
+ If alarm_aborted is set then all alarms are given and resent
+ every second.
+*/
sig_handler process_alarm(int sig __attribute__((unused)))
{
sigset_t old_mask;
- ALARM *alarm_data;
- DBUG_ENTER("process_alarm");
- DBUG_PRINT("info",("sig: %d active alarms: %d",sig,alarm_queue.elements));
+/*
+ This must be first as we can't call DBUG inside an alarm for a normal thread
+*/
#if THR_SERVER_ALARM == THR_CLIENT_ALARM
if (!pthread_equal(pthread_self(),alarm_thread))
@@ -249,17 +259,42 @@ sig_handler process_alarm(int sig __attribute__((unused)))
#ifdef DONT_REMEMBER_SIGNAL
sigset(THR_CLIENT_ALARM,process_alarm); /* int. thread system calls */
#endif
- DBUG_VOID_RETURN;
+ return;
}
#endif
-#if defined(MAIN) && !defined(__bsdi__)
- printf("process_alarm\n"); fflush(stdout);
-#endif
+ /*
+ We have to do do the handling of the alarm in a sub function,
+ because otherwise we would get problems with two threads calling
+ DBUG_... functions at the same time (as two threads may call
+ process_alarm() at the same time
+ */
+
#ifndef USE_ALARM_THREAD
pthread_sigmask(SIG_SETMASK,&full_signal_set,&old_mask);
pthread_mutex_lock(&LOCK_alarm);
#endif
+ process_alarm_part2(sig);
+#ifndef USE_ALARM_THREAD
+#if defined(DONT_REMEMBER_SIGNAL) && !defined(USE_ONE_SIGNAL_HAND)
+ sigset(THR_SERVER_ALARM,process_alarm);
+#endif
+ pthread_mutex_unlock(&LOCK_alarm);
+ pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
+#endif
+ return;
+}
+
+
+static sig_handler process_alarm_part2(int sig __attribute__((unused)))
+{
+ ALARM *alarm_data;
+ DBUG_ENTER("process_alarm");
+ DBUG_PRINT("info",("sig: %d active alarms: %d",sig,alarm_queue.elements));
+
+#if defined(MAIN) && !defined(__bsdi__)
+ printf("process_alarm\n"); fflush(stdout);
+#endif
if (alarm_queue.elements)
{
if (alarm_aborted)
@@ -320,20 +355,13 @@ sig_handler process_alarm(int sig __attribute__((unused)))
#endif
}
}
-#ifndef USE_ALARM_THREAD
-#if defined(DONT_REMEMBER_SIGNAL) && !defined(USE_ONE_SIGNAL_HAND)
- sigset(THR_SERVER_ALARM,process_alarm);
-#endif
- pthread_mutex_unlock(&LOCK_alarm);
- pthread_sigmask(SIG_SETMASK,&old_mask,NULL);
-#endif
DBUG_VOID_RETURN;
}
/*
-** Shedule all alarms now.
-** When all alarms are given, Free alarm memory and don't allow more alarms.
+ Shedule all alarms now.
+ When all alarms are given, Free alarm memory and don't allow more alarms.
*/
void end_thr_alarm(void)
@@ -357,7 +385,7 @@ void end_thr_alarm(void)
/*
-** Remove another thread from the alarm
+ Remove another thread from the alarm
*/
void thr_alarm_kill(pthread_t thread_id)
@@ -380,9 +408,25 @@ void thr_alarm_kill(pthread_t thread_id)
}
+void thr_alarm_info(ALARM_INFO *info)
+{
+ pthread_mutex_lock(&LOCK_alarm);
+ info->next_alarm_time= 0;
+ info->max_used_alarms= max_used_alarms;
+ if ((info->active_alarms= alarm_queue.elements))
+ {
+ ulong now=(ulong) time((time_t*) 0);
+ long time_diff;
+ ALARM *alarm_data= (ALARM*) queue_top(&alarm_queue);
+ time_diff= (long) (alarm_data->expire_time - now);
+ info->next_alarm_time= (ulong) (time_diff < 0 ? 0 : time_diff);
+ }
+ pthread_mutex_unlock(&LOCK_alarm);
+}
+
/*
-** This is here for thread to get interruptet from read/write/fcntl
-** ARGSUSED
+ This is here for thread to get interruptet from read/write/fcntl
+ ARGSUSED
*/
#if THR_CLIENT_ALARM != SIGALRM || defined(USE_ALARM_THREAD)
@@ -457,7 +501,7 @@ static void *alarm_handler(void *arg __attribute__((unused)))
#endif /* USE_ALARM_THREAD */
/*****************************************************************************
-** thr_alarm for OS/2
+ thr_alarm for OS/2
*****************************************************************************/
#elif defined(__EMX__) || defined(OS2)
@@ -488,7 +532,7 @@ sig_handler process_alarm(int sig __attribute__((unused)))
/*
-** Remove another thread from the alarm
+ Remove another thread from the alarm
*/
void thr_alarm_kill(pthread_t thread_id)
@@ -586,8 +630,14 @@ void init_thr_alarm(uint max_alarm)
DBUG_VOID_RETURN;
}
+void thr_alarm_info(ALARM_INFO *info)
+{
+ bzero((char*) info, sizeof(*info));
+}
+
+
/*****************************************************************************
-** thr_alarm for win95
+ thr_alarm for win95
*****************************************************************************/
#else /* __WIN__ */
@@ -605,6 +655,7 @@ sig_handler process_alarm(int sig __attribute__((unused)))
bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm)
{
+ (*alrm)= &alarm->alarmed;
if (alarm_aborted)
{
alarm->alarmed.crono=0;
@@ -613,7 +664,6 @@ bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm)
if (!(alarm->alarmed.crono=SetTimer((HWND) NULL,0, sec*1000,
(TIMERPROC) NULL)))
return 1;
- (*alrm)= &alarm->alarmed;
return 0;
}
@@ -638,7 +688,7 @@ bool thr_got_alarm(thr_alarm_t *alrm_ptr)
void thr_end_alarm(thr_alarm_t *alrm_ptr)
{
thr_alarm_t alrm= *alrm_ptr;
- if (alrm->crono)
+ if (alrm && alrm->crono)
{
KillTimer(NULL, alrm->crono);
alrm->crono = 0;
@@ -659,13 +709,18 @@ void init_thr_alarm(uint max_alarm)
DBUG_VOID_RETURN;
}
+void thr_alarm_info(ALARM_INFO *info)
+{
+ bzero((char*) info, sizeof(*info));
+}
+
#endif /* __WIN__ */
#endif /* THREAD */
/****************************************************************************
-** Handling of MAIN
+ Handling of test case (when compiled with -DMAIN)
***************************************************************************/
#ifdef MAIN
@@ -865,6 +920,7 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
pthread_attr_t thr_attr;
int i,*param,error;
sigset_t set;
+ ALARM_INFO alarm_info;
MY_INIT(argv[0]);
if (argc > 1 && argv[1][0] == '-' && argv[1][1] == '#')
@@ -925,6 +981,10 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
pthread_attr_destroy(&thr_attr);
pthread_mutex_lock(&LOCK_thread_count);
+ thr_alarm_info(&alarm_info);
+ printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n",
+ alarm_info.active_alarms, alarm_info.max_used_alarms,
+ alarm_info.next_alarm_time);
while (thread_count)
{
VOID(pthread_cond_wait(&COND_thread_count,&LOCK_thread_count));
@@ -935,6 +995,10 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused)))
}
}
pthread_mutex_unlock(&LOCK_thread_count);
+ thr_alarm_info(&alarm_info);
+ printf("Main_thread: Alarms: %u max_alarms: %u next_alarm_time: %lu\n",
+ alarm_info.active_alarms, alarm_info.max_used_alarms,
+ alarm_info.next_alarm_time);
printf("Test succeeded\n");
return 0;
}