aboutsummaryrefslogtreecommitdiff
path: root/src/backend/port/win32_latch.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/port/win32_latch.c')
-rw-r--r--src/backend/port/win32_latch.c37
1 files changed, 31 insertions, 6 deletions
diff --git a/src/backend/port/win32_latch.c b/src/backend/port/win32_latch.c
index 0c089fc7ecc..95370d9d58d 100644
--- a/src/backend/port/win32_latch.c
+++ b/src/backend/port/win32_latch.c
@@ -24,6 +24,7 @@
#include <unistd.h>
#include "miscadmin.h"
+#include "portability/instr_time.h"
#include "postmaster/postmaster.h"
#include "storage/latch.h"
#include "storage/pmsignal.h"
@@ -100,6 +101,9 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
long timeout)
{
DWORD rc;
+ instr_time start_time,
+ cur_time;
+ long cur_timeout;
HANDLE events[4];
HANDLE latchevent;
HANDLE sockevent = WSA_INVALID_EVENT;
@@ -118,11 +122,19 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
if ((wakeEvents & WL_LATCH_SET) && latch->owner_pid != MyProcPid)
elog(ERROR, "cannot wait on a latch owned by another process");
- /* Convert timeout to form used by WaitForMultipleObjects() */
+ /*
+ * Initialize timeout if requested. We must record the current time so
+ * that we can determine the remaining timeout if WaitForMultipleObjects
+ * is interrupted.
+ */
if (wakeEvents & WL_TIMEOUT)
+ {
+ INSTR_TIME_SET_CURRENT(start_time);
Assert(timeout >= 0);
+ cur_timeout = timeout;
+ }
else
- timeout = INFINITE;
+ cur_timeout = INFINITE;
/*
* Construct an array of event handles for WaitforMultipleObjects().
@@ -187,7 +199,7 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
break;
}
- rc = WaitForMultipleObjects(numevents, events, FALSE, timeout);
+ rc = WaitForMultipleObjects(numevents, events, FALSE, cur_timeout);
if (rc == WAIT_FAILED)
elog(ERROR, "WaitForMultipleObjects() failed: error code %lu",
@@ -203,7 +215,11 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
}
else if (rc == WAIT_OBJECT_0 + 1)
{
- /* Latch is set, we'll handle that on next iteration of loop */
+ /*
+ * Latch is set. We'll handle that on next iteration of loop, but
+ * let's not waste the cycles to update cur_timeout below.
+ */
+ continue;
}
else if ((wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE)) &&
rc == WAIT_OBJECT_0 + 2) /* socket is at event slot 2 */
@@ -240,8 +256,17 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
}
else
elog(ERROR, "unexpected return code from WaitForMultipleObjects(): %lu", rc);
- }
- while (result == 0);
+
+ /* If we're not done, update cur_timeout for next iteration */
+ if (result == 0 && cur_timeout != INFINITE)
+ {
+ INSTR_TIME_SET_CURRENT(cur_time);
+ INSTR_TIME_SUBTRACT(cur_time, start_time);
+ cur_timeout = timeout - (long) INSTR_TIME_GET_MILLISEC(cur_time);
+ if (cur_timeout < 0)
+ cur_timeout = 0;
+ }
+ } while (result == 0);
/* Clean up the event object we created for the socket */
if (sockevent != WSA_INVALID_EVENT)