diff options
Diffstat (limited to 'src/backend/port/win32_latch.c')
-rw-r--r-- | src/backend/port/win32_latch.c | 37 |
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) |