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.c49
1 files changed, 25 insertions, 24 deletions
diff --git a/src/backend/port/win32_latch.c b/src/backend/port/win32_latch.c
index 8d59ad493f6..eeb85a96cee 100644
--- a/src/backend/port/win32_latch.c
+++ b/src/backend/port/win32_latch.c
@@ -1,9 +1,10 @@
/*-------------------------------------------------------------------------
*
* win32_latch.c
- * Windows implementation of latches.
+ * Routines for inter-process latches
*
- * See unix_latch.c for information on usage.
+ * See unix_latch.c for header comments for the exported functions;
+ * the API presented here is supposed to be the same as there.
*
* The Windows implementation uses Windows events that are inherited by
* all postmaster child processes.
@@ -24,7 +25,6 @@
#include "miscadmin.h"
#include "postmaster/postmaster.h"
-#include "replication/walsender.h"
#include "storage/latch.h"
#include "storage/shmem.h"
@@ -89,7 +89,7 @@ WaitLatch(volatile Latch *latch, int wakeEvents, long timeout)
}
int
-WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, SOCKET sock,
+WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
long timeout)
{
DWORD rc;
@@ -101,12 +101,15 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, SOCKET sock,
int pmdeath_eventno = 0;
long timeout_ms;
- Assert(wakeEvents != 0);
-
/* Ignore WL_SOCKET_* events if no valid socket is given */
if (sock == PGINVALID_SOCKET)
wakeEvents &= ~(WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE);
+ Assert(wakeEvents != 0); /* must have at least one wake event */
+
+ if ((wakeEvents & WL_LATCH_SET) && latch->owner_pid != MyProcPid)
+ elog(ERROR, "cannot wait on a latch owned by another process");
+
/* Convert timeout to milliseconds for WaitForMultipleObjects() */
if (wakeEvents & WL_TIMEOUT)
{
@@ -122,8 +125,8 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, SOCKET sock,
events[0] = latchevent;
events[1] = pgwin32_signal_event;
numevents = 2;
- if (((wakeEvents & WL_SOCKET_READABLE) ||
- (wakeEvents & WL_SOCKET_WRITEABLE)))
+ if ((wakeEvents & WL_SOCKET_READABLE) ||
+ (wakeEvents & WL_SOCKET_WRITEABLE))
{
int flags = 0;
@@ -152,7 +155,7 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, SOCKET sock,
*/
if (!ResetEvent(latchevent))
elog(ERROR, "ResetEvent failed: error code %d", (int) GetLastError());
- if (latch->is_set && (wakeEvents & WL_LATCH_SET))
+ if ((wakeEvents & WL_LATCH_SET) && latch->is_set)
{
result |= WL_LATCH_SET;
/*
@@ -171,17 +174,17 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, SOCKET sock,
else if (rc == WAIT_OBJECT_0 + 1)
pgwin32_dispatch_queued_signals();
+ else if (rc == WAIT_TIMEOUT)
+ {
+ result |= WL_TIMEOUT;
+ }
else if ((wakeEvents & WL_POSTMASTER_DEATH) &&
- rc == WAIT_OBJECT_0 + pmdeath_eventno)
+ rc == WAIT_OBJECT_0 + pmdeath_eventno)
{
/* Postmaster died */
result |= WL_POSTMASTER_DEATH;
}
- else if (rc == WAIT_TIMEOUT)
- {
- result |= WL_TIMEOUT;
- }
- else if ((wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE)) != 0 &&
+ else if ((wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE)) &&
rc == WAIT_OBJECT_0 + 2) /* socket is at event slot 2 */
{
WSANETWORKEVENTS resEvents;
@@ -206,7 +209,7 @@ WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, SOCKET sock,
else if (rc != WAIT_OBJECT_0)
elog(ERROR, "unexpected return code from WaitForMultipleObjects(): %d", (int) rc);
}
- while(result == 0);
+ while (result == 0);
/* Clean up the handle we created for the socket */
if (sockevent != WSA_INVALID_EVENT)
@@ -231,15 +234,10 @@ SetLatch(volatile Latch *latch)
/*
* See if anyone's waiting for the latch. It can be the current process if
- * we're in a signal handler. Use a local variable here in case the latch
- * is just disowned between the test and the SetEvent call, and event
- * field set to NULL.
+ * we're in a signal handler.
*
- * Fetch handle field only once, in case the owner simultaneously disowns
- * the latch and clears handle. This assumes that HANDLE is atomic, which
- * isn't guaranteed to be true! In practice, it should be, and in the
- * worst case we end up calling SetEvent with a bogus handle, and SetEvent
- * will return an error with no harm done.
+ * Use a local variable here just in case somebody changes the event field
+ * concurrently (which really should not happen).
*/
handle = latch->event;
if (handle)
@@ -256,5 +254,8 @@ SetLatch(volatile Latch *latch)
void
ResetLatch(volatile Latch *latch)
{
+ /* Only the owner should reset the latch */
+ Assert(latch->owner_pid == MyProcPid);
+
latch->is_set = false;
}