1
/*-------------------------------------------------------------------------
4
* Windows implementation of latches.
6
* See unix_latch.c for information on usage.
8
* The Windows implementation uses Windows events that are inherited by
9
* all postmaster child processes.
11
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
12
* Portions Copyright (c) 1994, Regents of the University of California
15
* src/backend/port/win32_latch.c
17
*-------------------------------------------------------------------------
25
#include "miscadmin.h"
26
#include "replication/walsender.h"
27
#include "storage/latch.h"
28
#include "storage/shmem.h"
32
InitLatch(volatile Latch *latch)
34
latch->is_set = false;
35
latch->owner_pid = MyProcPid;
36
latch->is_shared = false;
38
latch->event = CreateEvent(NULL, TRUE, FALSE, NULL);
39
if (latch->event == NULL)
40
elog(ERROR, "CreateEvent failed: error code %d", (int) GetLastError());
44
InitSharedLatch(volatile Latch *latch)
46
SECURITY_ATTRIBUTES sa;
48
latch->is_set = false;
50
latch->is_shared = true;
53
* Set up security attributes to specify that the events are inherited.
55
ZeroMemory(&sa, sizeof(sa));
56
sa.nLength = sizeof(sa);
57
sa.bInheritHandle = TRUE;
59
latch->event = CreateEvent(&sa, TRUE, FALSE, NULL);
60
if (latch->event == NULL)
61
elog(ERROR, "CreateEvent failed: error code %d", (int) GetLastError());
65
OwnLatch(volatile Latch *latch)
68
Assert(latch->is_shared);
69
if (latch->owner_pid != 0)
70
elog(ERROR, "latch already owned");
72
latch->owner_pid = MyProcPid;
76
DisownLatch(volatile Latch *latch)
78
Assert(latch->is_shared);
79
Assert(latch->owner_pid == MyProcPid);
85
WaitLatch(volatile Latch *latch, long timeout)
87
return WaitLatchOrSocket(latch, PGINVALID_SOCKET, false, false, timeout) > 0;
91
WaitLatchOrSocket(volatile Latch *latch, SOCKET sock, bool forRead,
92
bool forWrite, long timeout)
97
HANDLE sockevent = WSA_INVALID_EVENT; /* silence compiler */
101
latchevent = latch->event;
103
events[0] = latchevent;
104
events[1] = pgwin32_signal_event;
106
if (sock != PGINVALID_SOCKET && (forRead || forWrite))
115
sockevent = WSACreateEvent();
116
WSAEventSelect(sock, sockevent, flags);
117
events[numevents++] = sockevent;
123
* Reset the event, and check if the latch is set already. If someone
124
* sets the latch between this and the WaitForMultipleObjects() call
125
* below, the setter will set the event and WaitForMultipleObjects()
126
* will return immediately.
128
if (!ResetEvent(latchevent))
129
elog(ERROR, "ResetEvent failed: error code %d", (int) GetLastError());
136
rc = WaitForMultipleObjects(numevents, events, FALSE,
137
(timeout >= 0) ? (timeout / 1000) : INFINITE);
138
if (rc == WAIT_FAILED)
139
elog(ERROR, "WaitForMultipleObjects() failed: error code %d", (int) GetLastError());
140
else if (rc == WAIT_TIMEOUT)
145
else if (rc == WAIT_OBJECT_0 + 1)
146
pgwin32_dispatch_queued_signals();
147
else if (rc == WAIT_OBJECT_0 + 2)
149
WSANETWORKEVENTS resEvents;
151
Assert(sock != PGINVALID_SOCKET);
153
ZeroMemory(&resEvents, sizeof(resEvents));
154
if (WSAEnumNetworkEvents(sock, sockevent, &resEvents) == SOCKET_ERROR)
156
(errmsg_internal("failed to enumerate network events: %i", (int) GetLastError())));
158
if ((forRead && resEvents.lNetworkEvents & FD_READ) ||
159
(forWrite && resEvents.lNetworkEvents & FD_WRITE))
163
else if (rc != WAIT_OBJECT_0)
164
elog(ERROR, "unexpected return code from WaitForMultipleObjects(): %d", (int) rc);
167
/* Clean up the handle we created for the socket */
168
if (sock != PGINVALID_SOCKET && (forRead || forWrite))
170
WSAEventSelect(sock, sockevent, 0);
171
WSACloseEvent(sockevent);
178
SetLatch(volatile Latch *latch)
182
/* Quick exit if already set */
186
latch->is_set = true;
189
* See if anyone's waiting for the latch. It can be the current process if
190
* we're in a signal handler. Use a local variable here in case the latch
191
* is just disowned between the test and the SetEvent call, and event
194
* Fetch handle field only once, in case the owner simultaneously disowns
195
* the latch and clears handle. This assumes that HANDLE is atomic, which
196
* isn't guaranteed to be true! In practice, it should be, and in the
197
* worst case we end up calling SetEvent with a bogus handle, and SetEvent
198
* will return an error with no harm done.
200
handle = latch->event;
206
* Note that we silently ignore any errors. We might be in a signal
207
* handler or other critical path where it's not safe to call elog().
213
ResetLatch(volatile Latch *latch)
215
latch->is_set = false;