diff options
Diffstat (limited to 'mysys/thr_alarm.c')
-rw-r--r-- | mysys/thr_alarm.c | 184 |
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; } |