aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/lmgr/proc.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2006-06-20 22:52:00 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2006-06-20 22:52:00 +0000
commit27c3e3de0939d93ae8adb50ab7e00c4a5ff2fa0d (patch)
tree49a0c81851952447af7bcace3f37e1d7b77c4854 /src/backend/storage/lmgr/proc.c
parent47a37aeebdbeb5c242141830586e065256a0aaf6 (diff)
downloadpostgresql-27c3e3de0939d93ae8adb50ab7e00c4a5ff2fa0d.tar.gz
postgresql-27c3e3de0939d93ae8adb50ab7e00c4a5ff2fa0d.zip
Remove redundant gettimeofday() calls to the extent practical without
changing semantics too much. statement_timestamp is now set immediately upon receipt of a client command message, and the various places that used to do their own gettimeofday() calls to mark command startup are referenced to that instead. I have also made stats_command_string use that same value for pg_stat_activity.query_start for both the command itself and its eventual replacement by <IDLE> or <idle in transaction>. There was some debate about that, but no argument that seemed convincing enough to justify an extra gettimeofday() call.
Diffstat (limited to 'src/backend/storage/lmgr/proc.c')
-rw-r--r--src/backend/storage/lmgr/proc.c73
1 files changed, 40 insertions, 33 deletions
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 92e870d99ae..6b74c54d5ab 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.174 2006/04/14 03:38:55 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/lmgr/proc.c,v 1.175 2006/06/20 22:52:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -42,6 +42,7 @@
#include "storage/proc.h"
#include "storage/procarray.h"
#include "storage/spin.h"
+#include "utils/timestamp.h"
/* GUC variables */
@@ -73,7 +74,7 @@ static volatile bool deadlock_timeout_active = false;
volatile bool cancel_from_timeout = false;
/* statement_fin_time is valid only if statement_timeout_active is true */
-static struct timeval statement_fin_time;
+static TimestampTz statement_fin_time;
static void RemoveProcFromArray(int code, Datum arg);
@@ -1105,29 +1106,32 @@ ProcSendSignal(int pid)
bool
enable_sig_alarm(int delayms, bool is_statement_timeout)
{
- struct timeval fin_time;
+ TimestampTz fin_time;
struct itimerval timeval;
- /* Compute target timeout time if we will need it */
- if (is_statement_timeout || statement_timeout_active)
- {
- gettimeofday(&fin_time, NULL);
- fin_time.tv_sec += delayms / 1000;
- fin_time.tv_usec += (delayms % 1000) * 1000;
- if (fin_time.tv_usec >= 1000000)
- {
- fin_time.tv_sec++;
- fin_time.tv_usec -= 1000000;
- }
- }
-
if (is_statement_timeout)
{
- /* Begin statement-level timeout */
+ /*
+ * Begin statement-level timeout
+ *
+ * Note that we compute statement_fin_time with reference to the
+ * statement_timestamp, but apply the specified delay without any
+ * correction; that is, we ignore whatever time has elapsed since
+ * statement_timestamp was set. In the normal case only a small
+ * interval will have elapsed and so this doesn't matter, but there
+ * are corner cases (involving multi-statement query strings with
+ * embedded COMMIT or ROLLBACK) where we might re-initialize the
+ * statement timeout long after initial receipt of the message.
+ * In such cases the enforcement of the statement timeout will be
+ * a bit inconsistent. This annoyance is judged not worth the cost
+ * of performing an additional gettimeofday() here.
+ */
Assert(!deadlock_timeout_active);
+ fin_time = GetCurrentStatementStartTimestamp();
+ fin_time = TimestampTzPlusMilliseconds(fin_time, delayms);
statement_fin_time = fin_time;
- statement_timeout_active = true;
cancel_from_timeout = false;
+ statement_timeout_active = true;
}
else if (statement_timeout_active)
{
@@ -1145,10 +1149,10 @@ enable_sig_alarm(int delayms, bool is_statement_timeout)
* to the state variables. The deadlock checker may get run earlier
* than normal, but that does no harm.
*/
+ fin_time = GetCurrentTimestamp();
+ fin_time = TimestampTzPlusMilliseconds(fin_time, delayms);
deadlock_timeout_active = true;
- if (fin_time.tv_sec > statement_fin_time.tv_sec ||
- (fin_time.tv_sec == statement_fin_time.tv_sec &&
- fin_time.tv_usec >= statement_fin_time.tv_usec))
+ if (fin_time >= statement_fin_time)
return true;
}
else
@@ -1225,16 +1229,14 @@ disable_sig_alarm(bool is_statement_timeout)
static bool
CheckStatementTimeout(void)
{
- struct timeval now;
+ TimestampTz now;
if (!statement_timeout_active)
return true; /* do nothing if not active */
- gettimeofday(&now, NULL);
+ now = GetCurrentTimestamp();
- if (now.tv_sec > statement_fin_time.tv_sec ||
- (now.tv_sec == statement_fin_time.tv_sec &&
- now.tv_usec >= statement_fin_time.tv_usec))
+ if (now >= statement_fin_time)
{
/* Time to die */
statement_timeout_active = false;
@@ -1244,16 +1246,21 @@ CheckStatementTimeout(void)
else
{
/* Not time yet, so (re)schedule the interrupt */
+ long secs;
+ int usecs;
struct itimerval timeval;
+ TimestampDifference(now, statement_fin_time,
+ &secs, &usecs);
+ /*
+ * It's possible that the difference is less than a microsecond;
+ * ensure we don't cancel, rather than set, the interrupt.
+ */
+ if (secs == 0 && usecs == 0)
+ usecs = 1;
MemSet(&timeval, 0, sizeof(struct itimerval));
- timeval.it_value.tv_sec = statement_fin_time.tv_sec - now.tv_sec;
- timeval.it_value.tv_usec = statement_fin_time.tv_usec - now.tv_usec;
- if (timeval.it_value.tv_usec < 0)
- {
- timeval.it_value.tv_sec--;
- timeval.it_value.tv_usec += 1000000;
- }
+ timeval.it_value.tv_sec = secs;
+ timeval.it_value.tv_usec = usecs;
if (setitimer(ITIMER_REAL, &timeval, NULL))
return false;
}