diff options
Diffstat (limited to 'mysys/thr_alarm.c')
-rw-r--r-- | mysys/thr_alarm.c | 75 |
1 files changed, 47 insertions, 28 deletions
diff --git a/mysys/thr_alarm.c b/mysys/thr_alarm.c index add5335a7af..1b58a0274ff 100644 --- a/mysys/thr_alarm.c +++ b/mysys/thr_alarm.c @@ -27,6 +27,7 @@ #include <m_string.h> #include <queues.h> #include "thr_alarm.h" +#include <assert.h> #ifdef HAVE_SYS_SELECT_H #include <sys/select.h> /* AIX needs this for fd_set */ @@ -36,7 +37,7 @@ #define ETIME ETIMEDOUT #endif -static my_bool alarm_aborted=1; +static int alarm_aborted=1; /* No alarm thread */ my_bool thr_alarm_inited=0; static sig_handler process_alarm_part2(int sig); @@ -136,19 +137,24 @@ bool thr_alarm(thr_alarm_t *alrm, uint sec, ALARM *alarm_data) now=(ulong) time((time_t*) 0); pthread_sigmask(SIG_BLOCK,&full_signal_set,&old_mask); pthread_mutex_lock(&LOCK_alarm); /* Lock from threads & alarms */ - if (alarm_aborted) + if (alarm_aborted > 0) { /* No signal thread */ DBUG_PRINT("info", ("alarm aborted")); + *alrm= 0; /* No alarm */ pthread_mutex_unlock(&LOCK_alarm); pthread_sigmask(SIG_SETMASK,&old_mask,NULL); DBUG_RETURN(1); } + if (alarm_aborted < 0) + sec= 1; /* Abort mode */ + if (alarm_queue.elements >= max_used_alarms) { if (alarm_queue.elements == alarm_queue.max_elements) { DBUG_PRINT("info", ("alarm queue full")); fprintf(stderr,"Warning: thr_alarm queue is full\n"); + *alrm= 0; /* No alarm */ pthread_mutex_unlock(&LOCK_alarm); pthread_sigmask(SIG_SETMASK,&old_mask,NULL); DBUG_RETURN(1); @@ -219,6 +225,7 @@ void thr_end_alarm(thr_alarm_t *alarmed) break; } } + DBUG_ASSERT(!*alarmed || found); if (!found) { #ifdef MAIN @@ -228,14 +235,7 @@ void thr_end_alarm(thr_alarm_t *alarmed) DBUG_PRINT("warning",("Didn't find alarm %lx in queue\n", (long) *alarmed)); } - if (alarm_aborted && !alarm_queue.elements) - { - delete_queue(&alarm_queue); - pthread_mutex_unlock(&LOCK_alarm); - pthread_mutex_destroy(&LOCK_alarm); - } - else - pthread_mutex_unlock(&LOCK_alarm); + pthread_mutex_unlock(&LOCK_alarm); pthread_sigmask(SIG_SETMASK,&old_mask,NULL); DBUG_VOID_RETURN; } @@ -365,31 +365,49 @@ static sig_handler process_alarm_part2(int sig __attribute__((unused))) /* - Shedule all alarms now. - When all alarms are given, Free alarm memory and don't allow more alarms. + Schedule all alarms now and optionally free all structures + + SYNPOSIS + end_thr_alarm() + free_structures Set to 1 if we should free memory used for + the alarm queue. + When we call this we should KNOW that there + is no active alarms + IMPLEMENTATION + Set alarm_abort to -1 which will change the behavior of alarms as follows: + - All old alarms will be rescheduled at once + - All new alarms will be rescheduled to one second */ -void end_thr_alarm(void) +void end_thr_alarm(my_bool free_structures) { DBUG_ENTER("end_thr_alarm"); - if (!alarm_aborted) + if (alarm_aborted != 1) { - my_bool deleted=0; pthread_mutex_lock(&LOCK_alarm); DBUG_PRINT("info",("Resheduling %d waiting alarms",alarm_queue.elements)); - alarm_aborted=1; /* mark aborted */ - if (!alarm_queue.elements) - { - deleted= 1; - delete_queue(&alarm_queue); - } + alarm_aborted= -1; /* mark aborted */ if (pthread_equal(pthread_self(),alarm_thread)) alarm(1); /* Shut down everything soon */ else reschedule_alarms(); - pthread_mutex_unlock(&LOCK_alarm); - if (deleted) - pthread_mutex_destroy(&LOCK_alarm); + if (free_structures) + { + /* + The following test is just for safety, the caller should not + depend on this + */ + DBUG_ASSERT(!alarm_queue.elements); + if (!alarm_queue.elements) + { + delete_queue(&alarm_queue); + alarm_aborted= 1; + pthread_mutex_unlock(&LOCK_alarm); + pthread_mutex_destroy(&LOCK_alarm); + } + } + else + pthread_mutex_unlock(&LOCK_alarm); } DBUG_VOID_RETURN; } @@ -629,7 +647,7 @@ void thr_end_alarm(thr_alarm_t *alrm_ptr) } } -void end_thr_alarm(void) +void end_thr_alarm(my_bool free_structures) { DBUG_ENTER("end_thr_alarm"); alarm_aborted=1; /* No more alarms */ @@ -708,7 +726,7 @@ void thr_end_alarm(thr_alarm_t *alrm_ptr) } } -void end_thr_alarm(void) +void end_thr_alarm(my_bool free_structures) { DBUG_ENTER("end_thr_alarm"); alarm_aborted=1; /* No more alarms */ @@ -907,7 +925,7 @@ static void *signal_hand(void *arg __attribute__((unused))) case SIGHUP: #endif printf("Aborting nicely\n"); - end_thr_alarm(); + end_thr_alarm(0); break; #ifdef SIGTSTP case SIGTSTP: @@ -1004,10 +1022,11 @@ int main(int argc __attribute__((unused)),char **argv __attribute__((unused))) if (thread_count == 1) { printf("Calling end_thr_alarm. This should cancel the last thread\n"); - end_thr_alarm(); + end_thr_alarm(0); } } pthread_mutex_unlock(&LOCK_thread_count); + end_thr_alarm(1); 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, |