PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
timeout.c File Reference
#include "postgres.h"
#include <sys/time.h>
#include "miscadmin.h"
#include "storage/proc.h"
#include "utils/timeout.h"
#include "utils/timestamp.h"
Include dependency graph for timeout.c:

Go to the source code of this file.

Data Structures

struct  timeout_params
 

Macros

#define disable_alarm()   (alarm_enabled = false)
 
#define enable_alarm()   (alarm_enabled = true)
 

Typedefs

typedef struct timeout_params timeout_params
 

Functions

static int find_active_timeout (TimeoutId id)
 
static void insert_timeout (TimeoutId id, int index)
 
static void remove_timeout_index (int index)
 
static void enable_timeout (TimeoutId id, TimestampTz now, TimestampTz fin_time)
 
static void schedule_alarm (TimestampTz now)
 
static void handle_sig_alarm (SIGNAL_ARGS)
 
void InitializeTimeouts (void)
 
TimeoutId RegisterTimeout (TimeoutId id, timeout_handler_proc handler)
 
void reschedule_timeouts (void)
 
void enable_timeout_after (TimeoutId id, int delay_ms)
 
void enable_timeout_at (TimeoutId id, TimestampTz fin_time)
 
void enable_timeouts (const EnableTimeoutParams *timeouts, int count)
 
void disable_timeout (TimeoutId id, bool keep_indicator)
 
void disable_timeouts (const DisableTimeoutParams *timeouts, int count)
 
void disable_all_timeouts (bool keep_indicators)
 
bool get_timeout_indicator (TimeoutId id, bool reset_indicator)
 
TimestampTz get_timeout_start_time (TimeoutId id)
 
TimestampTz get_timeout_finish_time (TimeoutId id)
 

Variables

static timeout_params all_timeouts [MAX_TIMEOUTS]
 
static bool all_timeouts_initialized = false
 
static volatile int num_active_timeouts = 0
 
static timeout_params *volatile active_timeouts [MAX_TIMEOUTS]
 
static volatile sig_atomic_t alarm_enabled = false
 

Macro Definition Documentation

#define enable_alarm ( )    (alarm_enabled = true)

Definition at line 65 of file timeout.c.

Referenced by schedule_alarm().

Typedef Documentation

Function Documentation

void disable_all_timeouts ( bool  keep_indicators)

Definition at line 596 of file timeout.c.

References disable_alarm, elog, FATAL, i, ITIMER_REAL, MAX_TIMEOUTS, MemSet, num_active_timeouts, and setitimer().

Referenced by AutoVacLauncherMain(), PostgresMain(), ResolveRecoveryConflictWithBufferPin(), and ResolveRecoveryConflictWithLock().

597 {
598  disable_alarm();
599 
600  /*
601  * Only bother to reset the timer if we think it's active. We could just
602  * let the interrupt happen anyway, but it's probably a bit cheaper to do
603  * setitimer() than to let the useless interrupt happen.
604  */
605  if (num_active_timeouts > 0)
606  {
607  struct itimerval timeval;
608 
609  MemSet(&timeval, 0, sizeof(struct itimerval));
610  if (setitimer(ITIMER_REAL, &timeval, NULL) != 0)
611  elog(FATAL, "could not disable SIGALRM timer: %m");
612  }
613 
615 
616  if (!keep_indicators)
617  {
618  int i;
619 
620  for (i = 0; i < MAX_TIMEOUTS; i++)
621  all_timeouts[i].indicator = false;
622  }
623 }
#define ITIMER_REAL
Definition: win32.h:218
#define MemSet(start, val, len)
Definition: c.h:863
#define disable_alarm()
Definition: timeout.c:64
#define FATAL
Definition: elog.h:52
static timeout_params all_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:43
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue)
Definition: timer.c:86
int i
#define elog
Definition: elog.h:219
static volatile int num_active_timeouts
Definition: timeout.c:50
void disable_timeout ( TimeoutId  id,
bool  keep_indicator 
)

Definition at line 525 of file timeout.c.

References all_timeouts_initialized, Assert, disable_alarm, find_active_timeout(), GetCurrentTimestamp(), i, timeout_params::indicator, num_active_timeouts, remove_timeout_index(), and schedule_alarm().

Referenced by BackendInitialize(), disable_statement_timeout(), enable_statement_timeout(), PerformAuthentication(), PostgresMain(), ProcSleep(), and StandbyTimeoutHandler().

526 {
527  int i;
528 
529  /* Assert request is sane */
531  Assert(all_timeouts[id].timeout_handler != NULL);
532 
533  /* Disable timeout interrupts for safety. */
534  disable_alarm();
535 
536  /* Find the timeout and remove it from the active list. */
537  i = find_active_timeout(id);
538  if (i >= 0)
540 
541  /* Mark it inactive, whether it was active or not. */
542  if (!keep_indicator)
543  all_timeouts[id].indicator = false;
544 
545  /* Reschedule the interrupt, if any timeouts remain active. */
546  if (num_active_timeouts > 0)
548 }
static bool all_timeouts_initialized
Definition: timeout.c:44
static void remove_timeout_index(int index)
Definition: timeout.c:120
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1570
#define disable_alarm()
Definition: timeout.c:64
volatile bool indicator
Definition: timeout.c:31
static timeout_params all_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:43
static void schedule_alarm(TimestampTz now)
Definition: timeout.c:185
#define Assert(condition)
Definition: c.h:681
static int find_active_timeout(TimeoutId id)
Definition: timeout.c:82
int i
static volatile int num_active_timeouts
Definition: timeout.c:50
void disable_timeouts ( const DisableTimeoutParams timeouts,
int  count 
)

Definition at line 561 of file timeout.c.

References all_timeouts_initialized, Assert, disable_alarm, find_active_timeout(), GetCurrentTimestamp(), i, DisableTimeoutParams::id, idx(), timeout_params::indicator, num_active_timeouts, remove_timeout_index(), and schedule_alarm().

Referenced by LockErrorCleanup(), and ProcSleep().

562 {
563  int i;
564 
566 
567  /* Disable timeout interrupts for safety. */
568  disable_alarm();
569 
570  /* Cancel the timeout(s). */
571  for (i = 0; i < count; i++)
572  {
573  TimeoutId id = timeouts[i].id;
574  int idx;
575 
576  Assert(all_timeouts[id].timeout_handler != NULL);
577 
578  idx = find_active_timeout(id);
579  if (idx >= 0)
581 
582  if (!timeouts[i].keep_indicator)
583  all_timeouts[id].indicator = false;
584  }
585 
586  /* Reschedule the interrupt, if any timeouts remain active. */
587  if (num_active_timeouts > 0)
589 }
static bool all_timeouts_initialized
Definition: timeout.c:44
static void remove_timeout_index(int index)
Definition: timeout.c:120
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1570
#define disable_alarm()
Definition: timeout.c:64
Datum idx(PG_FUNCTION_ARGS)
Definition: _int_op.c:264
volatile bool indicator
Definition: timeout.c:31
TimeoutId id
Definition: timeout.h:65
static timeout_params all_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:43
static void schedule_alarm(TimestampTz now)
Definition: timeout.c:185
#define Assert(condition)
Definition: c.h:681
TimeoutId
Definition: timeout.h:23
static int find_active_timeout(TimeoutId id)
Definition: timeout.c:82
int i
static volatile int num_active_timeouts
Definition: timeout.c:50
static void enable_timeout ( TimeoutId  id,
TimestampTz  now,
TimestampTz  fin_time 
)
static

Definition at line 138 of file timeout.c.

References all_timeouts_initialized, Assert, timeout_params::fin_time, find_active_timeout(), i, timeout_params::indicator, insert_timeout(), now(), num_active_timeouts, remove_timeout_index(), and timeout_params::start_time.

Referenced by enable_timeout_after(), enable_timeout_at(), and enable_timeouts().

139 {
140  int i;
141 
142  /* Assert request is sane */
144  Assert(all_timeouts[id].timeout_handler != NULL);
145 
146  /*
147  * If this timeout was already active, momentarily disable it. We
148  * interpret the call as a directive to reschedule the timeout.
149  */
150  i = find_active_timeout(id);
151  if (i >= 0)
153 
154  /*
155  * Find out the index where to insert the new timeout. We sort by
156  * fin_time, and for equal fin_time by priority.
157  */
158  for (i = 0; i < num_active_timeouts; i++)
159  {
160  timeout_params *old_timeout = active_timeouts[i];
161 
162  if (fin_time < old_timeout->fin_time)
163  break;
164  if (fin_time == old_timeout->fin_time && id < old_timeout->index)
165  break;
166  }
167 
168  /*
169  * Mark the timeout active, and insert it into the active list.
170  */
171  all_timeouts[id].indicator = false;
173  all_timeouts[id].fin_time = fin_time;
174 
175  insert_timeout(id, i);
176 }
static bool all_timeouts_initialized
Definition: timeout.c:44
static void remove_timeout_index(int index)
Definition: timeout.c:120
TimestampTz fin_time
Definition: timeout.c:37
volatile bool indicator
Definition: timeout.c:31
Definition: type.h:89
static timeout_params all_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:43
TimestampTz start_time
Definition: timeout.c:36
static void insert_timeout(TimeoutId id, int index)
Definition: timeout.c:100
#define Assert(condition)
Definition: c.h:681
static timeout_params *volatile active_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:51
static int find_active_timeout(TimeoutId id)
Definition: timeout.c:82
int i
static volatile int num_active_timeouts
Definition: timeout.c:50
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1534
void enable_timeout_after ( TimeoutId  id,
int  delay_ms 
)

Definition at line 428 of file timeout.c.

References disable_alarm, enable_timeout(), GetCurrentTimestamp(), now(), schedule_alarm(), and TimestampTzPlusMilliseconds.

Referenced by BackendInitialize(), enable_statement_timeout(), PerformAuthentication(), PostgresMain(), ProcSleep(), and ResolveRecoveryConflictWithBufferPin().

429 {
431  TimestampTz fin_time;
432 
433  /* Disable timeout interrupts for safety. */
434  disable_alarm();
435 
436  /* Queue the timeout at the appropriate time. */
437  now = GetCurrentTimestamp();
438  fin_time = TimestampTzPlusMilliseconds(now, delay_ms);
439  enable_timeout(id, now, fin_time);
440 
441  /* Set the timer interrupt. */
442  schedule_alarm(now);
443 }
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1570
int64 TimestampTz
Definition: timestamp.h:39
#define disable_alarm()
Definition: timeout.c:64
static void enable_timeout(TimeoutId id, TimestampTz now, TimestampTz fin_time)
Definition: timeout.c:138
static void schedule_alarm(TimestampTz now)
Definition: timeout.c:185
#define TimestampTzPlusMilliseconds(tz, ms)
Definition: timestamp.h:56
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1534
void enable_timeout_at ( TimeoutId  id,
TimestampTz  fin_time 
)

Definition at line 453 of file timeout.c.

References disable_alarm, enable_timeout(), GetCurrentTimestamp(), now(), and schedule_alarm().

454 {
456 
457  /* Disable timeout interrupts for safety. */
458  disable_alarm();
459 
460  /* Queue the timeout at the appropriate time. */
461  now = GetCurrentTimestamp();
462  enable_timeout(id, now, fin_time);
463 
464  /* Set the timer interrupt. */
465  schedule_alarm(now);
466 }
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1570
int64 TimestampTz
Definition: timestamp.h:39
#define disable_alarm()
Definition: timeout.c:64
static void enable_timeout(TimeoutId id, TimestampTz now, TimestampTz fin_time)
Definition: timeout.c:138
static void schedule_alarm(TimestampTz now)
Definition: timeout.c:185
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1534
void enable_timeouts ( const EnableTimeoutParams timeouts,
int  count 
)

Definition at line 476 of file timeout.c.

References disable_alarm, elog, enable_timeout(), ERROR, GetCurrentTimestamp(), i, EnableTimeoutParams::id, now(), schedule_alarm(), TimestampTzPlusMilliseconds, TMPARAM_AFTER, and TMPARAM_AT.

Referenced by ProcSleep(), ResolveRecoveryConflictWithBufferPin(), and ResolveRecoveryConflictWithLock().

477 {
479  int i;
480 
481  /* Disable timeout interrupts for safety. */
482  disable_alarm();
483 
484  /* Queue the timeout(s) at the appropriate times. */
485  now = GetCurrentTimestamp();
486 
487  for (i = 0; i < count; i++)
488  {
489  TimeoutId id = timeouts[i].id;
490  TimestampTz fin_time;
491 
492  switch (timeouts[i].type)
493  {
494  case TMPARAM_AFTER:
495  fin_time = TimestampTzPlusMilliseconds(now,
496  timeouts[i].delay_ms);
497  enable_timeout(id, now, fin_time);
498  break;
499 
500  case TMPARAM_AT:
501  enable_timeout(id, now, timeouts[i].fin_time);
502  break;
503 
504  default:
505  elog(ERROR, "unrecognized timeout type %d",
506  (int) timeouts[i].type);
507  break;
508  }
509  }
510 
511  /* Set the timer interrupt. */
512  schedule_alarm(now);
513 }
TimeoutId id
Definition: timeout.h:54
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1570
int64 TimestampTz
Definition: timestamp.h:39
#define disable_alarm()
Definition: timeout.c:64
#define ERROR
Definition: elog.h:43
static void enable_timeout(TimeoutId id, TimestampTz now, TimestampTz fin_time)
Definition: timeout.c:138
static void schedule_alarm(TimestampTz now)
Definition: timeout.c:185
#define TimestampTzPlusMilliseconds(tz, ms)
Definition: timestamp.h:56
TimeoutId
Definition: timeout.h:23
int i
#define elog
Definition: elog.h:219
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1534
static int find_active_timeout ( TimeoutId  id)
static

Definition at line 82 of file timeout.c.

References i, and num_active_timeouts.

Referenced by disable_timeout(), disable_timeouts(), and enable_timeout().

83 {
84  int i;
85 
86  for (i = 0; i < num_active_timeouts; i++)
87  {
88  if (active_timeouts[i]->index == id)
89  return i;
90  }
91 
92  return -1;
93 }
Definition: type.h:89
static timeout_params *volatile active_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:51
int i
static volatile int num_active_timeouts
Definition: timeout.c:50
TimestampTz get_timeout_finish_time ( TimeoutId  id)

Definition at line 667 of file timeout.c.

References timeout_params::fin_time.

Referenced by ProcessInterrupts().

668 {
669  return all_timeouts[id].fin_time;
670 }
TimestampTz fin_time
Definition: timeout.c:37
static timeout_params all_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:43
bool get_timeout_indicator ( TimeoutId  id,
bool  reset_indicator 
)

Definition at line 633 of file timeout.c.

References timeout_params::indicator.

Referenced by ProcessInterrupts().

634 {
635  if (all_timeouts[id].indicator)
636  {
637  if (reset_indicator)
638  all_timeouts[id].indicator = false;
639  return true;
640  }
641  return false;
642 }
volatile bool indicator
Definition: timeout.c:31
static timeout_params all_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:43
TimestampTz get_timeout_start_time ( TimeoutId  id)

Definition at line 653 of file timeout.c.

References timeout_params::start_time.

Referenced by ProcSleep().

654 {
655  return all_timeouts[id].start_time;
656 }
static timeout_params all_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:43
TimestampTz start_time
Definition: timeout.c:36
static void handle_sig_alarm ( SIGNAL_ARGS  )
static

Definition at line 259 of file timeout.c.

References alarm_enabled, disable_alarm, GetCurrentTimestamp(), HOLD_INTERRUPTS, timeout_params::indicator, MyLatch, now(), num_active_timeouts, remove_timeout_index(), RESUME_INTERRUPTS, schedule_alarm(), SetLatch(), and timeout_params::timeout_handler.

Referenced by InitializeTimeouts().

260 {
261  int save_errno = errno;
262 
263  /*
264  * Bump the holdoff counter, to make sure nothing we call will process
265  * interrupts directly. No timeout handler should do that, but these
266  * failures are hard to debug, so better be sure.
267  */
268  HOLD_INTERRUPTS();
269 
270  /*
271  * SIGALRM is always cause for waking anything waiting on the process
272  * latch.
273  */
274  SetLatch(MyLatch);
275 
276  /*
277  * Fire any pending timeouts, but only if we're enabled to do so.
278  */
279  if (alarm_enabled)
280  {
281  /*
282  * Disable alarms, just in case this platform allows signal handlers
283  * to interrupt themselves. schedule_alarm() will re-enable if
284  * appropriate.
285  */
286  disable_alarm();
287 
288  if (num_active_timeouts > 0)
289  {
291 
292  /* While the first pending timeout has been reached ... */
293  while (num_active_timeouts > 0 &&
294  now >= active_timeouts[0]->fin_time)
295  {
296  timeout_params *this_timeout = active_timeouts[0];
297 
298  /* Remove it from the active list */
300 
301  /* Mark it as fired */
302  this_timeout->indicator = true;
303 
304  /* And call its handler function */
305  this_timeout->timeout_handler();
306 
307  /*
308  * The handler might not take negligible time (CheckDeadLock
309  * for instance isn't too cheap), so let's update our idea of
310  * "now" after each one.
311  */
312  now = GetCurrentTimestamp();
313  }
314 
315  /* Done firing timeouts, so reschedule next interrupt if any */
316  schedule_alarm(now);
317  }
318  }
319 
321 
322  errno = save_errno;
323 }
static void remove_timeout_index(int index)
Definition: timeout.c:120
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1570
int64 TimestampTz
Definition: timestamp.h:39
#define disable_alarm()
Definition: timeout.c:64
timeout_handler_proc timeout_handler
Definition: timeout.c:34
volatile bool indicator
Definition: timeout.c:31
#define RESUME_INTERRUPTS()
Definition: miscadmin.h:117
static volatile sig_atomic_t alarm_enabled
Definition: timeout.c:62
static void schedule_alarm(TimestampTz now)
Definition: timeout.c:185
void SetLatch(volatile Latch *latch)
Definition: latch.c:414
static timeout_params *volatile active_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:51
#define HOLD_INTERRUPTS()
Definition: miscadmin.h:115
struct Latch * MyLatch
Definition: globals.c:52
static volatile int num_active_timeouts
Definition: timeout.c:50
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1534
void InitializeTimeouts ( void  )

Definition at line 340 of file timeout.c.

References all_timeouts_initialized, disable_alarm, timeout_params::fin_time, handle_sig_alarm(), i, timeout_params::index, timeout_params::indicator, MAX_TIMEOUTS, num_active_timeouts, pqsignal(), SIGALRM, timeout_params::start_time, and timeout_params::timeout_handler.

Referenced by AutoVacLauncherMain(), AutoVacWorkerMain(), BackendInitialize(), PostgresMain(), StartBackgroundWorker(), StartupProcessMain(), and WalSndSignals().

341 {
342  int i;
343 
344  /* Initialize, or re-initialize, all local state */
345  disable_alarm();
346 
348 
349  for (i = 0; i < MAX_TIMEOUTS; i++)
350  {
351  all_timeouts[i].index = i;
352  all_timeouts[i].indicator = false;
355  all_timeouts[i].fin_time = 0;
356  }
357 
359 
360  /* Now establish the signal handler */
362 }
static bool all_timeouts_initialized
Definition: timeout.c:44
TimestampTz fin_time
Definition: timeout.c:37
#define disable_alarm()
Definition: timeout.c:64
timeout_handler_proc timeout_handler
Definition: timeout.c:34
volatile bool indicator
Definition: timeout.c:31
static timeout_params all_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:43
TimestampTz start_time
Definition: timeout.c:36
pqsigfunc pqsignal(int signum, pqsigfunc handler)
Definition: signal.c:168
TimeoutId index
Definition: timeout.c:28
int i
static volatile int num_active_timeouts
Definition: timeout.c:50
#define SIGALRM
Definition: win32.h:194
static void handle_sig_alarm(SIGNAL_ARGS)
Definition: timeout.c:259
static void insert_timeout ( TimeoutId  id,
int  index 
)
static

Definition at line 100 of file timeout.c.

References elog, FATAL, i, and num_active_timeouts.

Referenced by enable_timeout().

101 {
102  int i;
103 
105  elog(FATAL, "timeout index %d out of range 0..%d", index,
106  num_active_timeouts);
107 
108  for (i = num_active_timeouts - 1; i >= index; i--)
109  active_timeouts[i + 1] = active_timeouts[i];
110 
112 
113  num_active_timeouts++;
114 }
Definition: type.h:89
#define FATAL
Definition: elog.h:52
static timeout_params all_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:43
static timeout_params *volatile active_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:51
int i
#define elog
Definition: elog.h:219
static volatile int num_active_timeouts
Definition: timeout.c:50
TimeoutId RegisterTimeout ( TimeoutId  id,
timeout_handler_proc  handler 
)

Definition at line 373 of file timeout.c.

References all_timeouts_initialized, Assert, ereport, errcode(), errmsg(), FATAL, MAX_TIMEOUTS, timeout_params::timeout_handler, and USER_TIMEOUT.

Referenced by BackendInitialize(), InitPostgres(), and StartupProcessMain().

374 {
376 
377  /* There's no need to disable the signal handler here. */
378 
379  if (id >= USER_TIMEOUT)
380  {
381  /* Allocate a user-defined timeout reason */
382  for (id = USER_TIMEOUT; id < MAX_TIMEOUTS; id++)
383  if (all_timeouts[id].timeout_handler == NULL)
384  break;
385  if (id >= MAX_TIMEOUTS)
386  ereport(FATAL,
387  (errcode(ERRCODE_CONFIGURATION_LIMIT_EXCEEDED),
388  errmsg("cannot add more timeout reasons")));
389  }
390 
391  Assert(all_timeouts[id].timeout_handler == NULL);
392 
393  all_timeouts[id].timeout_handler = handler;
394 
395  return id;
396 }
static bool all_timeouts_initialized
Definition: timeout.c:44
int errcode(int sqlerrcode)
Definition: elog.c:575
timeout_handler_proc timeout_handler
Definition: timeout.c:34
#define FATAL
Definition: elog.h:52
static timeout_params all_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:43
#define ereport(elevel, rest)
Definition: elog.h:122
#define Assert(condition)
Definition: c.h:681
int errmsg(const char *fmt,...)
Definition: elog.c:797
static void remove_timeout_index ( int  index)
static

Definition at line 120 of file timeout.c.

References elog, FATAL, i, and num_active_timeouts.

Referenced by disable_timeout(), disable_timeouts(), enable_timeout(), and handle_sig_alarm().

121 {
122  int i;
123 
125  elog(FATAL, "timeout index %d out of range 0..%d", index,
126  num_active_timeouts - 1);
127 
128  for (i = index + 1; i < num_active_timeouts; i++)
129  active_timeouts[i - 1] = active_timeouts[i];
130 
131  num_active_timeouts--;
132 }
Definition: type.h:89
#define FATAL
Definition: elog.h:52
static timeout_params *volatile active_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:51
int i
#define elog
Definition: elog.h:219
static volatile int num_active_timeouts
Definition: timeout.c:50
void reschedule_timeouts ( void  )

Definition at line 408 of file timeout.c.

References all_timeouts_initialized, disable_alarm, GetCurrentTimestamp(), num_active_timeouts, and schedule_alarm().

Referenced by AbortSubTransaction(), and AbortTransaction().

409 {
410  /* For flexibility, allow this to be called before we're initialized. */
412  return;
413 
414  /* Disable timeout interrupts for safety. */
415  disable_alarm();
416 
417  /* Reschedule the interrupt, if any timeouts remain active. */
418  if (num_active_timeouts > 0)
420 }
static bool all_timeouts_initialized
Definition: timeout.c:44
TimestampTz GetCurrentTimestamp(void)
Definition: timestamp.c:1570
#define disable_alarm()
Definition: timeout.c:64
static void schedule_alarm(TimestampTz now)
Definition: timeout.c:185
static volatile int num_active_timeouts
Definition: timeout.c:50
static void schedule_alarm ( TimestampTz  now)
static

Definition at line 185 of file timeout.c.

References elog, enable_alarm, FATAL, itimerval::it_value, ITIMER_REAL, MemSet, num_active_timeouts, setitimer(), and TimestampDifference().

Referenced by disable_timeout(), disable_timeouts(), enable_timeout_after(), enable_timeout_at(), enable_timeouts(), handle_sig_alarm(), and reschedule_timeouts().

186 {
187  if (num_active_timeouts > 0)
188  {
189  struct itimerval timeval;
190  long secs;
191  int usecs;
192 
193  MemSet(&timeval, 0, sizeof(struct itimerval));
194 
195  /* Get the time remaining till the nearest pending timeout */
197  &secs, &usecs);
198 
199  /*
200  * It's possible that the difference is less than a microsecond;
201  * ensure we don't cancel, rather than set, the interrupt.
202  */
203  if (secs == 0 && usecs == 0)
204  usecs = 1;
205 
206  timeval.it_value.tv_sec = secs;
207  timeval.it_value.tv_usec = usecs;
208 
209  /*
210  * We must enable the signal handler before calling setitimer(); if we
211  * did it in the other order, we'd have a race condition wherein the
212  * interrupt could occur before we can set alarm_enabled, so that the
213  * signal handler would fail to do anything.
214  *
215  * Because we didn't bother to reset the timer in disable_alarm(),
216  * it's possible that a previously-set interrupt will fire between
217  * enable_alarm() and setitimer(). This is safe, however. There are
218  * two possible outcomes:
219  *
220  * 1. The signal handler finds nothing to do (because the nearest
221  * timeout event is still in the future). It will re-set the timer
222  * and return. Then we'll overwrite the timer value with a new one.
223  * This will mean that the timer fires a little later than we
224  * intended, but only by the amount of time it takes for the signal
225  * handler to do nothing useful, which shouldn't be much.
226  *
227  * 2. The signal handler executes and removes one or more timeout
228  * events. When it returns, either the queue is now empty or the
229  * frontmost event is later than the one we looked at above. So we'll
230  * overwrite the timer value with one that is too soon (plus or minus
231  * the signal handler's execution time), causing a useless interrupt
232  * to occur. But the handler will then re-set the timer and
233  * everything will still work as expected.
234  *
235  * Since these cases are of very low probability (the window here
236  * being quite narrow), it's not worth adding cycles to the mainline
237  * code to prevent occasional wasted interrupts.
238  */
239  enable_alarm();
240 
241  /* Set the alarm timer */
242  if (setitimer(ITIMER_REAL, &timeval, NULL) != 0)
243  elog(FATAL, "could not enable SIGALRM timer: %m");
244  }
245 }
#define ITIMER_REAL
Definition: win32.h:218
#define enable_alarm()
Definition: timeout.c:65
#define MemSet(start, val, len)
Definition: c.h:863
#define FATAL
Definition: elog.h:52
int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue)
Definition: timer.c:86
static timeout_params *volatile active_timeouts[MAX_TIMEOUTS]
Definition: timeout.c:51
#define elog
Definition: elog.h:219
void TimestampDifference(TimestampTz start_time, TimestampTz stop_time, long *secs, int *microsecs)
Definition: timestamp.c:1624
static volatile int num_active_timeouts
Definition: timeout.c:50
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1534

Variable Documentation

timeout_params* volatile active_timeouts[MAX_TIMEOUTS]
static

Definition at line 51 of file timeout.c.

volatile sig_atomic_t alarm_enabled = false
static

Definition at line 62 of file timeout.c.

Referenced by handle_sig_alarm().

timeout_params all_timeouts[MAX_TIMEOUTS]
static

Definition at line 43 of file timeout.c.

bool all_timeouts_initialized = false
static