diff options
Diffstat (limited to 'src/backend/utils/misc/timeout.c')
-rw-r--r-- | src/backend/utils/misc/timeout.c | 49 |
1 files changed, 32 insertions, 17 deletions
diff --git a/src/backend/utils/misc/timeout.c b/src/backend/utils/misc/timeout.c index b56259c6920..a2a4bb6f2d5 100644 --- a/src/backend/utils/misc/timeout.c +++ b/src/backend/utils/misc/timeout.c @@ -27,7 +27,8 @@ typedef struct timeout_params { TimeoutId index; /* identifier of timeout reason */ - /* volatile because it may be changed from the signal handler */ + /* volatile because these may be changed from the signal handler */ + volatile bool active; /* true if timeout is in active_timeouts[] */ volatile bool indicator; /* true if timeout has occurred */ /* callback function for timeout, or NULL if timeout not registered */ @@ -105,6 +106,9 @@ insert_timeout(TimeoutId id, int index) elog(FATAL, "timeout index %d out of range 0..%d", index, num_active_timeouts); + Assert(!all_timeouts[id].active); + all_timeouts[id].active = true; + for (i = num_active_timeouts - 1; i >= index; i--) active_timeouts[i + 1] = active_timeouts[i]; @@ -125,6 +129,9 @@ remove_timeout_index(int index) elog(FATAL, "timeout index %d out of range 0..%d", index, num_active_timeouts - 1); + Assert(active_timeouts[index]->active); + active_timeouts[index]->active = false; + for (i = index + 1; i < num_active_timeouts; i++) active_timeouts[i - 1] = active_timeouts[i]; @@ -147,9 +154,8 @@ enable_timeout(TimeoutId id, TimestampTz now, TimestampTz fin_time) * If this timeout was already active, momentarily disable it. We * interpret the call as a directive to reschedule the timeout. */ - i = find_active_timeout(id); - if (i >= 0) - remove_timeout_index(i); + if (all_timeouts[id].active) + remove_timeout_index(find_active_timeout(id)); /* * Find out the index where to insert the new timeout. We sort by @@ -349,6 +355,7 @@ InitializeTimeouts(void) for (i = 0; i < MAX_TIMEOUTS; i++) { all_timeouts[i].index = i; + all_timeouts[i].active = false; all_timeouts[i].indicator = false; all_timeouts[i].timeout_handler = NULL; all_timeouts[i].start_time = 0; @@ -524,8 +531,6 @@ enable_timeouts(const EnableTimeoutParams *timeouts, int count) void disable_timeout(TimeoutId id, bool keep_indicator) { - int i; - /* Assert request is sane */ Assert(all_timeouts_initialized); Assert(all_timeouts[id].timeout_handler != NULL); @@ -534,9 +539,8 @@ disable_timeout(TimeoutId id, bool keep_indicator) disable_alarm(); /* Find the timeout and remove it from the active list. */ - i = find_active_timeout(id); - if (i >= 0) - remove_timeout_index(i); + if (all_timeouts[id].active) + remove_timeout_index(find_active_timeout(id)); /* Mark it inactive, whether it was active or not. */ if (!keep_indicator) @@ -571,13 +575,11 @@ disable_timeouts(const DisableTimeoutParams *timeouts, int count) for (i = 0; i < count; i++) { TimeoutId id = timeouts[i].id; - int idx; Assert(all_timeouts[id].timeout_handler != NULL); - idx = find_active_timeout(id); - if (idx >= 0) - remove_timeout_index(idx); + if (all_timeouts[id].active) + remove_timeout_index(find_active_timeout(id)); if (!timeouts[i].keep_indicator) all_timeouts[id].indicator = false; @@ -595,6 +597,8 @@ disable_timeouts(const DisableTimeoutParams *timeouts, int count) void disable_all_timeouts(bool keep_indicators) { + int i; + disable_alarm(); /* @@ -613,16 +617,27 @@ disable_all_timeouts(bool keep_indicators) num_active_timeouts = 0; - if (!keep_indicators) + for (i = 0; i < MAX_TIMEOUTS; i++) { - int i; - - for (i = 0; i < MAX_TIMEOUTS; i++) + all_timeouts[i].active = false; + if (!keep_indicators) all_timeouts[i].indicator = false; } } /* + * Return true if the timeout is active (enabled and not yet fired) + * + * This is, of course, subject to race conditions, as the timeout could fire + * immediately after we look. + */ +bool +get_timeout_active(TimeoutId id) +{ + return all_timeouts[id].active; +} + +/* * Return the timeout's I've-been-fired indicator * * If reset_indicator is true, reset the indicator when returning true. |