clock_gettime_1.patch
application/octet-stream
Filename: clock_gettime_1.patch
Type: application/octet-stream
Part: 0
Patch
Format: unified
| File | + | − |
|---|---|---|
| contrib/pgcrypto/fortuna.c | 8 | 9 |
| contrib/pgcrypto/random.c | 2 | 3 |
| src/backend/access/transam/xlog.c | 5 | 5 |
| src/backend/libpq/auth.c | 7 | 6 |
| src/backend/postmaster/autovacuum.c | 12 | 12 |
| src/backend/postmaster/checkpointer.c | 3 | 3 |
| src/backend/postmaster/postmaster.c | 9 | 9 |
| src/backend/tcop/postgres.c | 7 | 7 |
| src/backend/utils/error/elog.c | 5 | 5 |
| src/backend/utils/misc/pg_rusage.c | 1 | 1 |
| src/bin/pg_basebackup/streamutil.c | 4 | 3 |
| src/bin/pgbench/pgbench.c | 3 | 3 |
| src/bin/pg_dump/pg_dump.c | 2 | 2 |
| src/bin/pg_resetxlog/pg_resetxlog.c | 3 | 3 |
| src/bin/pg_test_fsync/pg_test_fsync.c | 10 | 10 |
| src/include/c.h | 10 | 0 |
| src/include/datatype/timestamp.h | 3 | 0 |
| src/include/pg_config.h.in | 3 | 0 |
| src/include/portability/instr_time.h | 20 | 20 |
| src/include/port.h | 5 | 0 |
| src/include/utils/pg_rusage.h | 1 | 0 |
| src/port/clock_gettime.c | 117 | 0 |
| src/test/isolation/isolationtester.c | 9 | 8 |
| src/tools/msvc/Mkvcbuild.pm | 2 | 2 |
diff --git a/contrib/pgcrypto/fortuna.c b/contrib/pgcrypto/fortuna.c
index 5028203..1654c41 100644
--- a/contrib/pgcrypto/fortuna.c
+++ b/contrib/pgcrypto/fortuna.c
@@ -31,7 +31,6 @@
#include "postgres.h"
-#include <sys/time.h>
#include <time.h>
#include "px.h"
@@ -89,8 +88,8 @@
*/
#define NUM_POOLS 23
-/* in microseconds */
-#define RESEED_INTERVAL 100000 /* 0.1 sec */
+/* in nanoseconds */
+#define RESEED_INTERVAL 100000000 /* 0.1 sec */
/* for one big request, reseed after this many bytes */
#define RESEED_BYTES (1024*1024)
@@ -123,7 +122,7 @@ struct fortuna_state
MD_CTX pool[NUM_POOLS];
CIPH_CTX ciph;
unsigned reseed_count;
- struct timeval last_reseed_time;
+ struct timespec last_reseed_time;
unsigned pool0_bytes;
unsigned rnd_pos;
int tricks_done;
@@ -223,10 +222,10 @@ static int
enough_time_passed(FState *st)
{
int ok;
- struct timeval tv;
- struct timeval *last = &st->last_reseed_time;
+ struct timespec tv;
+ struct timespec *last = &st->last_reseed_time;
- gettimeofday(&tv, NULL);
+ clock_gettime(CLOCK_REALTIME, &tv);
/* check how much time has passed */
ok = 0;
@@ -234,10 +233,10 @@ enough_time_passed(FState *st)
ok = 1;
else if (tv.tv_sec == last->tv_sec + 1)
{
- if (1000000 + tv.tv_usec - last->tv_usec >= RESEED_INTERVAL)
+ if (1000000000 + tv.tv_nsec - last->tv_nsec >= RESEED_INTERVAL)
ok = 1;
}
- else if (tv.tv_usec - last->tv_usec >= RESEED_INTERVAL)
+ else if (tv.tv_nsec - last->tv_nsec >= RESEED_INTERVAL)
ok = 1;
/* reseed will happen, update last_reseed_time */
diff --git a/contrib/pgcrypto/random.c b/contrib/pgcrypto/random.c
index d72679e..34bf40e 100644
--- a/contrib/pgcrypto/random.c
+++ b/contrib/pgcrypto/random.c
@@ -162,7 +162,6 @@ try_win32_perfc(uint8 *dst)
#define TRY_UNIXSTD
#include <sys/types.h>
-#include <sys/time.h>
#include <time.h>
#include <unistd.h>
@@ -178,7 +177,7 @@ try_unix_std(uint8 *dst)
pid_t pid;
int x;
PX_MD *md;
- struct timeval tv;
+ struct timespec tv;
int res;
/* process id */
@@ -187,7 +186,7 @@ try_unix_std(uint8 *dst)
dst += sizeof(pid);
/* time */
- gettimeofday(&tv, NULL);
+ clock_gettime(CLOCK_REALTIME_COARSE, &tv);
memcpy(dst, (uint8 *) &tv, sizeof(tv));
dst += sizeof(tv);
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 2189c22..1e57a27 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -4765,24 +4765,24 @@ BootStrapXLOG(void)
char *recptr;
bool use_existent;
uint64 sysidentifier;
- struct timeval tv;
+ struct timespec tv;
pg_crc32c crc;
/*
* Select a hopefully-unique system identifier code for this installation.
- * We use the result of gettimeofday(), including the fractional seconds
+ * We use the result of clock_gettime(), including the fractional seconds
* field, as being about as unique as we can easily get. (Think not to
* use random(), since it hasn't been seeded and there's no portable way
* to seed it other than the system clock value...) The upper half of the
* uint64 value is just the tv_sec part, while the lower half contains the
- * tv_usec part (which must fit in 20 bits), plus 12 bits from our current
+ * tv_nsec part (which must fit in 20 bits), plus 12 bits from our current
* PID for a little extra uniqueness. A person knowing this encoding can
* determine the initialization time of the installation, which could
* perhaps be useful sometimes.
*/
- gettimeofday(&tv, NULL);
+ clock_gettime(CLOCK_REALTIME_COARSE, &tv);
sysidentifier = ((uint64) tv.tv_sec) << 32;
- sysidentifier |= ((uint64) tv.tv_usec) << 12;
+ sysidentifier |= ((uint64) tv.tv_nsec) << 12;
sysidentifier |= getpid() & 0xFFF;
/* First timeline ID is always 1 */
diff --git a/src/backend/libpq/auth.c b/src/backend/libpq/auth.c
index d907e6b..d0652bb 100644
--- a/src/backend/libpq/auth.c
+++ b/src/backend/libpq/auth.c
@@ -19,6 +19,7 @@
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
+#include <time.h>
#include <unistd.h>
#include "common/ip.h"
@@ -2434,7 +2435,7 @@ CheckRADIUSAuth(Port *port)
char portstr[128];
ACCEPT_TYPE_ARG3 addrsize;
fd_set fdset;
- struct timeval endtime;
+ struct timespec endtime;
int i,
j,
r;
@@ -2622,17 +2623,17 @@ CheckRADIUSAuth(Port *port)
* the latch was set would improve the responsiveness to
* timeouts/cancellations.
*/
- gettimeofday(&endtime, NULL);
+ clock_gettime(CLOCK_REALTIME_COARSE, &endtime);
endtime.tv_sec += RADIUS_TIMEOUT;
while (true)
{
struct timeval timeout;
- struct timeval now;
+ struct timespec now;
int64 timeoutval;
- gettimeofday(&now, NULL);
- timeoutval = (endtime.tv_sec * 1000000 + endtime.tv_usec) - (now.tv_sec * 1000000 + now.tv_usec);
+ clock_gettime(CLOCK_REALTIME, &now);
+ timeoutval = (endtime.tv_sec * 1000000000 + endtime.tv_nsec) - (now.tv_sec * 1000000000 + now.tv_nsec);
if (timeoutval <= 0)
{
ereport(LOG,
@@ -2640,7 +2641,7 @@ CheckRADIUSAuth(Port *port)
closesocket(sock);
return STATUS_ERROR;
}
- timeout.tv_sec = timeoutval / 1000000;
+ timeout.tv_sec = timeoutval / 10000000000;
timeout.tv_usec = timeoutval % 1000000;
FD_ZERO(&fdset);
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 1a92ca1..5b8cee0 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -290,7 +290,7 @@ NON_EXEC_STATIC void AutoVacLauncherMain(int argc, char *argv[]) pg_attribute_no
static Oid do_start_worker(void);
static void launcher_determine_sleep(bool canlaunch, bool recursing,
- struct timeval * nap);
+ struct timespec * nap);
static void launch_worker(TimestampTz now);
static List *get_database_list(void);
static void rebuild_database_list(Oid newdb);
@@ -577,7 +577,7 @@ AutoVacLauncherMain(int argc, char *argv[])
/* loop until shutdown request */
while (!got_SIGTERM)
{
- struct timeval nap;
+ struct timespec nap;
TimestampTz current_time = 0;
bool can_launch;
int rc;
@@ -598,7 +598,7 @@ AutoVacLauncherMain(int argc, char *argv[])
*/
rc = WaitLatch(MyLatch,
WL_LATCH_SET | WL_TIMEOUT | WL_POSTMASTER_DEATH,
- (nap.tv_sec * 1000L) + (nap.tv_usec / 1000L));
+ (nap.tv_sec * 1000L) + (nap.tv_nsec / 1000000L));
ResetLatch(MyLatch);
@@ -790,7 +790,7 @@ shutdown:
* cause a long sleep, which will be interrupted when a worker exits.
*/
static void
-launcher_determine_sleep(bool canlaunch, bool recursing, struct timeval * nap)
+launcher_determine_sleep(bool canlaunch, bool recursing, struct timespec * nap)
{
/*
* We sleep until the next scheduled vacuum. We trust that when the
@@ -801,7 +801,7 @@ launcher_determine_sleep(bool canlaunch, bool recursing, struct timeval * nap)
if (!canlaunch)
{
nap->tv_sec = autovacuum_naptime;
- nap->tv_usec = 0;
+ nap->tv_nsec = 0;
}
else if (!dlist_is_empty(&DatabaseList))
{
@@ -809,21 +809,21 @@ launcher_determine_sleep(bool canlaunch, bool recursing, struct timeval * nap)
TimestampTz next_wakeup;
avl_dbase *avdb;
long secs;
- int usecs;
+ int nsecs;
avdb = dlist_tail_element(avl_dbase, adl_node, &DatabaseList);
next_wakeup = avdb->adl_next_worker;
- TimestampDifference(current_time, next_wakeup, &secs, &usecs);
+ TimestampDifference(current_time, next_wakeup, &secs, &nsecs);
nap->tv_sec = secs;
- nap->tv_usec = usecs;
+ nap->tv_nsec = nsecs;
}
else
{
/* list is empty, sleep for whole autovacuum_naptime seconds */
nap->tv_sec = autovacuum_naptime;
- nap->tv_usec = 0;
+ nap->tv_nsec = 0;
}
/*
@@ -836,7 +836,7 @@ launcher_determine_sleep(bool canlaunch, bool recursing, struct timeval * nap)
* We only recurse once. rebuild_database_list should always return times
* in the future, but it seems best not to trust too much on that.
*/
- if (nap->tv_sec == 0 && nap->tv_usec == 0 && !recursing)
+ if (nap->tv_sec == 0 && nap->tv_nsec == 0 && !recursing)
{
rebuild_database_list(InvalidOid);
launcher_determine_sleep(canlaunch, true, nap);
@@ -844,10 +844,10 @@ launcher_determine_sleep(bool canlaunch, bool recursing, struct timeval * nap)
}
/* The smallest time we'll allow the launcher to sleep. */
- if (nap->tv_sec <= 0 && nap->tv_usec <= MIN_AUTOVAC_SLEEPTIME * 1000)
+ if (nap->tv_sec <= 0 && nap->tv_nsec <= MIN_AUTOVAC_SLEEPTIME * 1000000)
{
nap->tv_sec = 0;
- nap->tv_usec = MIN_AUTOVAC_SLEEPTIME * 1000;
+ nap->tv_nsec = MIN_AUTOVAC_SLEEPTIME * 1000;
}
/*
diff --git a/src/backend/postmaster/checkpointer.c b/src/backend/postmaster/checkpointer.c
index d702a48..eb0668c 100644
--- a/src/backend/postmaster/checkpointer.c
+++ b/src/backend/postmaster/checkpointer.c
@@ -725,7 +725,7 @@ static bool
IsCheckpointOnSchedule(double progress)
{
XLogRecPtr recptr;
- struct timeval now;
+ struct timespec now;
double elapsed_xlogs,
elapsed_time;
@@ -778,9 +778,9 @@ IsCheckpointOnSchedule(double progress)
/*
* Check progress against time elapsed and checkpoint_timeout.
*/
- gettimeofday(&now, NULL);
+ clock_gettime(CLOCK_REALTIME, &now);
elapsed_time = ((double) ((pg_time_t) now.tv_sec - ckpt_start_time) +
- now.tv_usec / 1000000.0) / CheckPointTimeout;
+ now.tv_nsec / 1000000000.0) / CheckPointTimeout;
if (progress < elapsed_time)
{
diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c
index eaf3f61..5277956 100644
--- a/src/backend/postmaster/postmaster.c
+++ b/src/backend/postmaster/postmaster.c
@@ -364,7 +364,7 @@ static volatile bool HaveCrashedWorker = false;
* backend from the postmaster to that backend (via fork).
*/
static unsigned int random_seed = 0;
-static struct timeval random_start_time;
+static struct timespec random_start_time;
#ifdef USE_BONJOUR
static DNSServiceRef bonjour_sdref = NULL;
@@ -1283,7 +1283,7 @@ PostmasterMain(int argc, char *argv[])
*/
PgStartTime = GetCurrentTimestamp();
/* PostmasterRandom wants its own copy */
- gettimeofday(&random_start_time, NULL);
+ clock_gettime(CLOCK_REALTIME, &random_start_time);
/*
* We're ready to rock and roll...
@@ -4208,7 +4208,7 @@ BackendRun(Port *port)
* a new random sequence in the random() library function.
*/
random_seed = 0;
- random_start_time.tv_usec = 0;
+ random_start_time.tv_nsec = 0;
/* slightly hacky way to convert timestamptz into integers */
TimestampDifference(0, port->SessionStartTime, &secs, &usecs);
srandom((unsigned int) (MyProcPid ^ (usecs << 12) ^ secs));
@@ -5111,19 +5111,19 @@ PostmasterRandom(void)
{
do
{
- struct timeval random_stop_time;
+ struct timespec random_stop_time;
- gettimeofday(&random_stop_time, NULL);
+ clock_gettime(CLOCK_REALTIME, &random_stop_time);
/*
- * We are not sure how much precision is in tv_usec, so we swap
+ * We are not sure how much precision is in tv_nsec, so we swap
* the high and low 16 bits of 'random_stop_time' and XOR them
* with 'random_start_time'. On the off chance that the result is
* 0, we loop until it isn't.
*/
- random_seed = random_start_time.tv_usec ^
- ((random_stop_time.tv_usec << 16) |
- ((random_stop_time.tv_usec >> 16) & 0xffff));
+ random_seed = random_start_time.tv_nsec ^
+ ((random_stop_time.tv_nsec << 16) |
+ ((random_stop_time.tv_nsec >> 16) & 0xffff));
}
while (random_seed == 0);
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 98ccbbb..6d6accb 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -4374,13 +4374,13 @@ get_stack_depth_rlimit(void)
static struct rusage Save_r;
-static struct timeval Save_t;
+static struct timespec Save_t;
void
ResetUsage(void)
{
getrusage(RUSAGE_SELF, &Save_r);
- gettimeofday(&Save_t, NULL);
+ clock_gettime(CLOCK_REALTIME, &Save_t);
}
void
@@ -4389,17 +4389,17 @@ ShowUsage(const char *title)
StringInfoData str;
struct timeval user,
sys;
- struct timeval elapse_t;
+ struct timespec elapse_t;
struct rusage r;
getrusage(RUSAGE_SELF, &r);
- gettimeofday(&elapse_t, NULL);
+ clock_gettime(CLOCK_REALTIME, &elapse_t);
memcpy((char *) &user, (char *) &r.ru_utime, sizeof(user));
memcpy((char *) &sys, (char *) &r.ru_stime, sizeof(sys));
- if (elapse_t.tv_usec < Save_t.tv_usec)
+ if (elapse_t.tv_nsec < Save_t.tv_nsec)
{
elapse_t.tv_sec--;
- elapse_t.tv_usec += 1000000;
+ elapse_t.tv_nsec += 1000000000;
}
if (r.ru_utime.tv_usec < Save_r.ru_utime.tv_usec)
{
@@ -4425,7 +4425,7 @@ ShowUsage(const char *title)
appendStringInfo(&str,
"!\t%ld.%06ld elapsed %ld.%06ld user %ld.%06ld system sec\n",
(long) (elapse_t.tv_sec - Save_t.tv_sec),
- (long) (elapse_t.tv_usec - Save_t.tv_usec),
+ (long) (elapse_t.tv_nsec - Save_t.tv_nsec),
(long) (r.ru_utime.tv_sec - Save_r.ru_utime.tv_sec),
(long) (r.ru_utime.tv_usec - Save_r.ru_utime.tv_usec),
(long) (r.ru_stime.tv_sec - Save_r.ru_stime.tv_sec),
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index 224ee78..531aa69 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -147,7 +147,7 @@ static int recursion_depth = 0; /* to detect actual recursion */
* Saved timeval and buffers for formatted timestamps that might be used by
* both log_line_prefix and csv logs.
*/
-static struct timeval saved_timeval;
+static struct timespec saved_timeval;
static bool saved_timeval_set = false;
#define FORMATTED_TS_LEN 128
@@ -2232,7 +2232,7 @@ setup_formatted_log_time(void)
if (!saved_timeval_set)
{
- gettimeofday(&saved_timeval, NULL);
+ clock_gettime(CLOCK_REALTIME_COARSE, &saved_timeval);
saved_timeval_set = true;
}
@@ -2249,7 +2249,7 @@ setup_formatted_log_time(void)
pg_localtime(&stamp_time, log_timezone));
/* 'paste' milliseconds into place... */
- sprintf(msbuf, ".%03d", (int) (saved_timeval.tv_usec / 1000));
+ sprintf(msbuf, ".%03d", (int) (saved_timeval.tv_nsec / 1000000));
memcpy(formatted_log_time + 19, msbuf, 4);
}
@@ -2480,12 +2480,12 @@ log_line_prefix(StringInfo buf, ErrorData *edata)
if (!saved_timeval_set)
{
- gettimeofday(&saved_timeval, NULL);
+ clock_gettime(CLOCK_REALTIME_COARSE, &saved_timeval);
saved_timeval_set = true;
}
sprintf(strfbuf, "%ld.%03d", saved_timeval.tv_sec,
- (int) (saved_timeval.tv_usec / 1000));
+ (int) (saved_timeval.tv_nsec / 1000000));
if (padding != 0)
appendStringInfo(buf, "%*s", padding, strfbuf);
diff --git a/src/backend/utils/misc/pg_rusage.c b/src/backend/utils/misc/pg_rusage.c
index 8781a38..5242dad 100644
--- a/src/backend/utils/misc/pg_rusage.c
+++ b/src/backend/utils/misc/pg_rusage.c
@@ -27,7 +27,7 @@ void
pg_rusage_init(PGRUsage *ru0)
{
getrusage(RUSAGE_SELF, &ru0->ru);
- gettimeofday(&ru0->tv, NULL);
+ clock_gettime(CLOCK_REALTIME, (struct timespec *)&ru0->tv);
}
/*
diff --git a/src/bin/pg_basebackup/streamutil.c b/src/bin/pg_basebackup/streamutil.c
index 595eaff..8481ec5 100644
--- a/src/bin/pg_basebackup/streamutil.c
+++ b/src/bin/pg_basebackup/streamutil.c
@@ -17,6 +17,7 @@
#include <string.h>
#include <sys/time.h>
#include <sys/types.h>
+#include <time.h>
#include <unistd.h>
/* for ntohl/htonl */
@@ -445,14 +446,14 @@ int64
feGetCurrentTimestamp(void)
{
int64 result;
- struct timeval tp;
+ struct timespec tp;
- gettimeofday(&tp, NULL);
+ clock_gettime(CLOCK_REALTIME_COARSE, &tp);
result = (int64) tp.tv_sec -
((POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE) * SECS_PER_DAY);
- result = (result * USECS_PER_SEC) + tp.tv_usec;
+ result = (result * NSECS_PER_SEC) + tp.tv_nsec;
return result;
}
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index ba9c276..9fc3a82 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -1756,7 +1756,7 @@ dumpTableData_copy(Archive *fout, void *dcontext)
* Further discussion ensued, and the proposal was dropped.
*
* For those people who want this feature, it can be implemented using
- * gettimeofday in each loop, calculating the time since last sleep,
+ * clock_gettime in each loop, calculating the time since last sleep,
* multiplying that by the sleep ratio, then if the result is more
* than a preset 'minimum sleep time' (say 100ms), call the 'select'
* function to sleep for a subsecond period ie.
@@ -1764,7 +1764,7 @@ dumpTableData_copy(Archive *fout, void *dcontext)
* select(0, NULL, NULL, NULL, &tvi);
*
* This will return after the interval specified in the structure tvi.
- * Finally, call gettimeofday again to save the 'last sleep time'.
+ * Finally, call clock_gettime again to save the 'last sleep time'.
* ----------
*/
}
diff --git a/src/bin/pg_resetxlog/pg_resetxlog.c b/src/bin/pg_resetxlog/pg_resetxlog.c
index 525b82ba..cc9b03e 100644
--- a/src/bin/pg_resetxlog/pg_resetxlog.c
+++ b/src/bin/pg_resetxlog/pg_resetxlog.c
@@ -535,7 +535,7 @@ static void
GuessControlValues(void)
{
uint64 sysidentifier;
- struct timeval tv;
+ struct timespec tv;
/*
* Set up a completely default set of pg_control values.
@@ -550,9 +550,9 @@ GuessControlValues(void)
* Create a new unique installation identifier, since we can no longer use
* any old XLOG records. See notes in xlog.c about the algorithm.
*/
- gettimeofday(&tv, NULL);
+ clock_gettime(CLOCK_REALTIME_COARSE, &tv);
sysidentifier = ((uint64) tv.tv_sec) << 32;
- sysidentifier |= ((uint64) tv.tv_usec) << 12;
+ sysidentifier |= ((uint64) tv.tv_nsec) << 12;
sysidentifier |= getpid() & 0xFFF;
ControlFile.system_identifier = sysidentifier;
diff --git a/src/bin/pg_test_fsync/pg_test_fsync.c b/src/bin/pg_test_fsync/pg_test_fsync.c
index c842762..ca8206e 100644
--- a/src/bin/pg_test_fsync/pg_test_fsync.c
+++ b/src/bin/pg_test_fsync/pg_test_fsync.c
@@ -26,7 +26,7 @@
#define LABEL_FORMAT " %-30s"
#define NA_FORMAT "%20s"
#define OPS_FORMAT "%13.3f ops/sec %6.0f usecs/op"
-#define USECS_SEC 1000000
+#define NSECS_SEC 1000000000
/* These are macros to avoid timing the function call overhead. */
#ifndef WIN32
@@ -34,7 +34,7 @@
do { \
alarm_triggered = false; \
alarm(secs_per_test); \
- gettimeofday(&start_t, NULL); \
+ clock_gettime(CLOCK_REALTIME, &start_t); \
} while (0)
#else
/* WIN32 doesn't support alarm, so we create a thread and sleep there */
@@ -47,13 +47,13 @@ do { \
fprintf(stderr, "Cannot create thread for alarm\n"); \
exit(1); \
} \
- gettimeofday(&start_t, NULL); \
-} while (0)
+ clock_gettime(CLOCK_REALTIME, &start_t); \
+ } while (0)
#endif
#define STOP_TIMER \
do { \
- gettimeofday(&stop_t, NULL); \
+ clock_gettime(CLOCK_REALTIME, &stop_t); \
print_elapse(start_t, stop_t, ops); \
} while (0)
@@ -65,7 +65,7 @@ static int needs_unlink = 0;
static char full_buf[XLOG_SEG_SIZE],
*buf,
*filename = FSYNC_FILENAME;
-static struct timeval start_t,
+static struct timespec start_t,
stop_t;
static bool alarm_triggered = false;
@@ -89,7 +89,7 @@ static void signal_cleanup(int sig);
#ifdef HAVE_FSYNC_WRITETHROUGH
static int pg_fsync_writethrough(int fd);
#endif
-static void print_elapse(struct timeval start_t, struct timeval stop_t, int ops);
+static void print_elapse(struct timespec start_t, struct timespec stop_t, int ops);
static void die(const char *str);
@@ -568,12 +568,12 @@ pg_fsync_writethrough(int fd)
* print out the writes per second for tests
*/
static void
-print_elapse(struct timeval start_t, struct timeval stop_t, int ops)
+print_elapse(struct timespec start_t, struct timespec stop_t, int ops)
{
double total_time = (stop_t.tv_sec - start_t.tv_sec) +
- (stop_t.tv_usec - start_t.tv_usec) * 0.000001;
+ (stop_t.tv_nsec - start_t.tv_nsec) * 0.000000001;
double per_second = ops / total_time;
- double avg_op_time_us = (total_time / ops) * USECS_SEC;
+ double avg_op_time_us = (total_time / ops) * NSECS_SEC;
printf(OPS_FORMAT "\n", per_second, avg_op_time_us);
}
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index 56c37d5..d10fe51 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -1772,7 +1772,7 @@ doCustom(TState *thread, CState *st, StatsData *agg)
instr_time now;
/*
- * gettimeofday() isn't free, so we get the current timestamp lazily the
+ * clock_gettime() isn't free, so we get the current timestamp lazily the
* first time it's needed, and reuse the same value throughout this
* function after that. This also ensures that e.g. the calculated latency
* reported in the log file and in the totals are the same. Zero means
@@ -2247,11 +2247,11 @@ doLog(TState *thread, CState *st, instr_time *now,
if (skipped)
fprintf(logfile, "%d " INT64_FORMAT " skipped %d %ld %ld",
st->id, st->cnt, st->use_file,
- (long) now->tv_sec, (long) now->tv_usec);
+ (long) now->tv_sec, (long) now->tv_nsec);
else
fprintf(logfile, "%d " INT64_FORMAT " %.0f %d %ld %ld",
st->id, st->cnt, latency, st->use_file,
- (long) now->tv_sec, (long) now->tv_usec);
+ (long) now->tv_sec, (long) now->tv_nsec);
#else
/* On Windows, instr_time doesn't provide a timestamp anyway */
diff --git a/src/include/c.h b/src/include/c.h
index 4ab3f80..020fa30 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -138,6 +138,16 @@
*/
#define gettext_noop(x) (x)
+#if defined(WIN32) || defined(__CYGWIN__)
+typedef struct timespec {
+ long tv_sec;
+ long tv_nsec;
+} timespec;
+
+#define CLOCK_REALTIME 1
+#define CLOCK_REALTIME_COARSE 2
+#endif
+
/* ----------------------------------------------------------------
* Section 1: hacks to cope with non-ANSI C compilers
diff --git a/src/include/datatype/timestamp.h b/src/include/datatype/timestamp.h
index 68a41eb..31d39d8 100644
--- a/src/include/datatype/timestamp.h
+++ b/src/include/datatype/timestamp.h
@@ -105,6 +105,9 @@ typedef struct
#define USECS_PER_MINUTE INT64CONST(60000000)
#define USECS_PER_SEC INT64CONST(1000000)
+#define NSECS_PER_SEC INT64CONST(1000000000)
+#define NSECS_PER_USEC INT64CONST(1000)
+
/*
* We allow numeric timezone offsets up to 15:59:59 either way from Greenwich.
* Currently, the record holders for wackiest offsets in actual use are zones
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index b621ff2..e2efae7 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -231,6 +231,9 @@
/* Define to 1 if you have the `gettimeofday' function. */
#undef HAVE_GETTIMEOFDAY
+/* Define to 1 if you have the `clock_gettime' function. */
+#undef HAVE_CLOCK_GETTIME
+
/* Define to 1 if you have the <gssapi/gssapi.h> header file. */
#undef HAVE_GSSAPI_GSSAPI_H
diff --git a/src/include/port.h b/src/include/port.h
index b81fa4a..a8e80dc 100644
--- a/src/include/port.h
+++ b/src/include/port.h
@@ -319,6 +319,11 @@ extern FILE *pgwin32_popen(const char *command, const char *type);
/* Last parameter not used */
extern int gettimeofday(struct timeval * tp, struct timezone * tzp);
#endif
+/* New versions of MingW have gettimeofday, old mingw and msvc don't */
+#ifndef HAVE_CLOCK_GETTIME
+/* First parameter is not used */
+extern int clock_gettime(int clock_id, struct timespec * tp);
+#endif
#else /* !WIN32 */
/*
diff --git a/src/include/portability/instr_time.h b/src/include/portability/instr_time.h
index 16caf6e..ebcc976 100644
--- a/src/include/portability/instr_time.h
+++ b/src/include/portability/instr_time.h
@@ -4,7 +4,7 @@
* portable high-precision interval timing
*
* This file provides an abstraction layer to hide portability issues in
- * interval timing. On Unix we use gettimeofday(), but on Windows that
+ * interval timing. On Unix we use clock_gettime(), but on Windows that
* gives a low-precision result so we must use QueryPerformanceCounter()
* instead. These macros also give some breathing room to use other
* high-precision-timing APIs on yet other platforms.
@@ -54,24 +54,24 @@
#ifndef WIN32
-#include <sys/time.h>
+#include <time.h>
-typedef struct timeval instr_time;
+typedef struct timespec instr_time;
-#define INSTR_TIME_IS_ZERO(t) ((t).tv_usec == 0 && (t).tv_sec == 0)
+#define INSTR_TIME_IS_ZERO(t) ((t).tv_nsec == 0 && (t).tv_sec == 0)
-#define INSTR_TIME_SET_ZERO(t) ((t).tv_sec = 0, (t).tv_usec = 0)
+#define INSTR_TIME_SET_ZERO(t) ((t).tv_sec = 0, (t).tv_nsec = 0)
-#define INSTR_TIME_SET_CURRENT(t) gettimeofday(&(t), NULL)
+#define INSTR_TIME_SET_CURRENT(t) clock_gettime(CLOCK_REALTIME, &(t))
#define INSTR_TIME_ADD(x,y) \
do { \
(x).tv_sec += (y).tv_sec; \
- (x).tv_usec += (y).tv_usec; \
+ (x).tv_nsec += (y).tv_nsec; \
/* Normalize */ \
- while ((x).tv_usec >= 1000000) \
+ while ((x).tv_nsec >= 1000000000) \
{ \
- (x).tv_usec -= 1000000; \
+ (x).tv_nsec -= 1000000000; \
(x).tv_sec++; \
} \
} while (0)
@@ -79,11 +79,11 @@ typedef struct timeval instr_time;
#define INSTR_TIME_SUBTRACT(x,y) \
do { \
(x).tv_sec -= (y).tv_sec; \
- (x).tv_usec -= (y).tv_usec; \
+ (x).tv_nsec -= (y).tv_nsec; \
/* Normalize */ \
- while ((x).tv_usec < 0) \
+ while ((x).tv_nsec < 0) \
{ \
- (x).tv_usec += 1000000; \
+ (x).tv_nsec += 1000000000; \
(x).tv_sec--; \
} \
} while (0)
@@ -91,28 +91,28 @@ typedef struct timeval instr_time;
#define INSTR_TIME_ACCUM_DIFF(x,y,z) \
do { \
(x).tv_sec += (y).tv_sec - (z).tv_sec; \
- (x).tv_usec += (y).tv_usec - (z).tv_usec; \
+ (x).tv_nsec += (y).tv_nsec - (z).tv_nsec; \
/* Normalize after each add to avoid overflow/underflow of tv_usec */ \
- while ((x).tv_usec < 0) \
+ while ((x).tv_nsec < 0) \
{ \
- (x).tv_usec += 1000000; \
+ (x).tv_nsec += 1000000000; \
(x).tv_sec--; \
} \
- while ((x).tv_usec >= 1000000) \
+ while ((x).tv_nsec >= 1000000000) \
{ \
- (x).tv_usec -= 1000000; \
+ (x).tv_nsec -= 1000000; \
(x).tv_sec++; \
} \
} while (0)
#define INSTR_TIME_GET_DOUBLE(t) \
- (((double) (t).tv_sec) + ((double) (t).tv_usec) / 1000000.0)
+ (((double) (t).tv_sec) + ((double) (t).tv_nsec) / 1000000000.0)
#define INSTR_TIME_GET_MILLISEC(t) \
- (((double) (t).tv_sec * 1000.0) + ((double) (t).tv_usec) / 1000.0)
+ (((double) (t).tv_sec * 1000.0) + ((double) (t).tv_nsec) / 1000000.0)
#define INSTR_TIME_GET_MICROSEC(t) \
- (((uint64) (t).tv_sec * (uint64) 1000000) + (uint64) (t).tv_usec)
+ (((uint64) (t).tv_sec * (uint64) 1000000) + ((double) (t).tv_nsec) / 1000.0)
#else /* WIN32 */
typedef LARGE_INTEGER instr_time;
diff --git a/src/include/utils/pg_rusage.h b/src/include/utils/pg_rusage.h
index 7c264eb..9ca9436 100644
--- a/src/include/utils/pg_rusage.h
+++ b/src/include/utils/pg_rusage.h
@@ -15,6 +15,7 @@
#define PG_RUSAGE_H
#include <sys/time.h>
+#include <time.h>
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/resource.h>
diff --git a/src/port/clock_gettime.c b/src/port/clock_gettime.c
new file mode 100644
index 0000000..05641ad
--- /dev/null
+++ b/src/port/clock_gettime.c
@@ -0,0 +1,117 @@
+/*
+ * clock_gettime.c
+ * Win32 clock_gettime() replacement
+ *
+ * src/port/clock_gettime.c
+ *
+ * Copyright (c) 2003 SRA, Inc.
+ * Copyright (c) 2003 SKC, Inc.
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose, without fee, and without a
+ * written agreement is hereby granted, provided that the above
+ * copyright notice and this paragraph and the following two
+ * paragraphs appear in all copies.
+ *
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
+ * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
+ * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
+ * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS
+ * IS" BASIS, AND THE AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE,
+ * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+ */
+
+#include "c.h"
+
+#include <time.h>
+
+/* FILETIME of Jan 1 1970 00:00:00, the PostgreSQL epoch */
+static const unsigned __int64 epoch = UINT64CONST(116444736000000000);
+
+/*
+ * FILETIME represents the number of 100-nanosecond intervals since
+ * January 1, 1601 (UTC).
+ */
+#define FILETIME_UNITS_PER_SEC 10000000L
+#define FILETIME_UNITS_PER_USEC 10
+
+/*
+ * Both GetSystemTimeAsFileTime and GetSystemTimePreciseAsFileTime share a
+ * signature, so we can just store a pointer to whichever we find. This
+ * is the pointer's type.
+ */
+typedef VOID(WINAPI * PgGetSystemTimeFn) (LPFILETIME);
+
+/* One-time initializer function, must match that signature. */
+static void WINAPI init_clock_gettime(LPFILETIME lpSystemTimeAsFileTime);
+
+/* Storage for the function we pick at runtime */
+static PgGetSystemTimeFn pg_get_system_time = &init_clock_gettime;
+
+/*
+ * One time initializer. Determine whether GetSystemTimePreciseAsFileTime
+ * is available and if so, plan to use it; if not, fall back to
+ * GetSystemTimeAsFileTime.
+ */
+static void WINAPI
+init_clock_gettime(LPFILETIME lpSystemTimeAsFileTime)
+{
+ /*
+ * Because it's guaranteed that kernel32.dll will be linked into our
+ * address space already, we don't need to LoadLibrary it and worry about
+ * closing it afterwards, so we're not using Pg's dlopen/dlsym() wrapper.
+ *
+ * We'll just look up the address of GetSystemTimePreciseAsFileTime if
+ * present.
+ *
+ * While we could look up the Windows version and skip this on Windows
+ * versions below Windows 8 / Windows Server 2012 there isn't much point,
+ * and determining the windows version is its self somewhat Windows
+ * version and development SDK specific...
+ */
+ pg_get_system_time = (PgGetSystemTimeFn) GetProcAddress(
+ GetModuleHandle(TEXT("kernel32.dll")),
+ "GetSystemTimePreciseAsFileTime");
+ if (pg_get_system_time == NULL)
+ {
+ /*
+ * The expected error from GetLastError() is ERROR_PROC_NOT_FOUND, if
+ * the function isn't present. No other error should occur.
+ *
+ * We can't report an error here because this might be running in
+ * frontend code; and even if we're in the backend, it's too early to
+ * elog(...) if we get some unexpected error. Also, it's not a
+ * serious problem, so just silently fall back to
+ * GetSystemTimeAsFileTime irrespective of why the failure occurred.
+ */
+ pg_get_system_time = &GetSystemTimeAsFileTime;
+ }
+
+ (*pg_get_system_time) (lpSystemTimeAsFileTime);
+}
+
+/*
+ * Note: this function is not for Win32 high precision timing purposes. See
+ * elapsed_time().
+ */
+int
+clock_gettime(int clock_id, struct timespec * tp)
+{
+ FILETIME file_time;
+ ULARGE_INTEGER ularge;
+
+ (*pg_get_system_time) (&file_time);
+ ularge.LowPart = file_time.dwLowDateTime;
+ ularge.HighPart = file_time.dwHighDateTime;
+
+ tp->tv_sec = (long) ((ularge.QuadPart - epoch) / FILETIME_UNITS_PER_SEC);
+ tp->tv_nsec = (long) ((((ularge.QuadPart - epoch) % FILETIME_UNITS_PER_SEC)
+ / FILETIME_UNITS_PER_USEC) * 1000);
+
+ return 0;
+}
diff --git a/src/test/isolation/isolationtester.c b/src/test/isolation/isolationtester.c
index db2b559..d31aef5 100644
--- a/src/test/isolation/isolationtester.c
+++ b/src/test/isolation/isolationtester.c
@@ -11,6 +11,7 @@
#include <windows.h>
#endif
#include <sys/time.h>
+#include <time.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
@@ -698,7 +699,7 @@ try_complete_step(Step *step, int flags)
{
PGconn *conn = conns[1 + step->session];
fd_set read_set;
- struct timeval start_time;
+ struct timespec start_time;
struct timeval timeout;
int sock = PQsocket(conn);
int ret;
@@ -711,7 +712,7 @@ try_complete_step(Step *step, int flags)
exit_nicely();
}
- gettimeofday(&start_time, NULL);
+ clock_gettime(CLOCK_REALTIME, &start_time);
FD_ZERO(&read_set);
while (PQisBusy(conn))
@@ -730,7 +731,7 @@ try_complete_step(Step *step, int flags)
}
else if (ret == 0) /* select() timeout: check for lock wait */
{
- struct timeval current_time;
+ struct timespec current_time;
int64 td;
/* If it's OK for the step to block, check whether it has. */
@@ -762,10 +763,10 @@ try_complete_step(Step *step, int flags)
}
/* Figure out how long we've been waiting for this step. */
- gettimeofday(¤t_time, NULL);
+ clock_gettime(CLOCK_REALTIME, ¤t_time);
td = (int64) current_time.tv_sec - (int64) start_time.tv_sec;
- td *= USECS_PER_SEC;
- td += (int64) current_time.tv_usec - (int64) start_time.tv_usec;
+ td *= NSECS_PER_SEC;
+ td += (int64) current_time.tv_nsec - (int64) start_time.tv_nsec;
/*
* After 60 seconds, try to cancel the query.
@@ -776,7 +777,7 @@ try_complete_step(Step *step, int flags)
* presumably lead to this permutation failing, but remaining
* permutations and tests should still be OK.
*/
- if (td > 60 * USECS_PER_SEC && !canceled)
+ if (td > 60 * NSECS_PER_SEC && !canceled)
{
PGcancel *cancel = PQgetCancel(conn);
@@ -799,7 +800,7 @@ try_complete_step(Step *step, int flags)
* later tests to fail. That stinks, but it's better than waiting
* forever for the server to respond to the cancel.
*/
- if (td > 75 * USECS_PER_SEC)
+ if (td > 75 * NSECS_PER_SEC)
{
fprintf(stderr, "step %s timed out after 75 seconds\n",
step->name);
diff --git a/src/tools/msvc/Mkvcbuild.pm b/src/tools/msvc/Mkvcbuild.pm
index 93dfd24..1b16684 100644
--- a/src/tools/msvc/Mkvcbuild.pm
+++ b/src/tools/msvc/Mkvcbuild.pm
@@ -88,8 +88,8 @@ sub mkvcbuild
$solution = CreateSolution($vsVersion, $config);
our @pgportfiles = qw(
- chklocale.c crypt.c fls.c fseeko.c getrusage.c inet_aton.c random.c
- srandom.c getaddrinfo.c gettimeofday.c inet_net_ntop.c kill.c open.c
+ chklocale.c clock_gettime.c crypt.c fls.c fseeko.c getrusage.c inet_aton.c
+ random.c srandom.c getaddrinfo.c gettimeofday.c inet_net_ntop.c kill.c open.c
erand48.c snprintf.c strlcat.c strlcpy.c dirmod.c noblock.c path.c
pgcheckdir.c pgmkdirp.c pgsleep.c pgstrcasecmp.c pqsignal.c
mkdtemp.c qsort.c qsort_arg.c quotes.c system.c