1 /*-------------------------------------------------------------------------
4 * Routines for inter-process latches
6 * See unix_latch.c for header comments for the exported functions;
7 * the API presented here is supposed to be the same as there.
9 * The Windows implementation uses Windows events that are inherited by
10 * all postmaster child processes.
12 * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
13 * Portions Copyright (c) 1994, Regents of the University of California
16 * src/backend/port/win32_latch.c
18 *-------------------------------------------------------------------------
26 #include "miscadmin.h"
27 #include "postmaster/postmaster.h"
28 #include "storage/latch.h"
29 #include "storage/pmsignal.h"
30 #include "storage/shmem.h"
34 InitLatch(volatile Latch *latch)
36 latch->is_set = false;
37 latch->owner_pid = MyProcPid;
38 latch->is_shared = false;
40 latch->event = CreateEvent(NULL, TRUE, FALSE, NULL);
41 if (latch->event == NULL)
42 elog(ERROR, "CreateEvent failed: error code %lu", GetLastError());
46 InitSharedLatch(volatile Latch *latch)
48 SECURITY_ATTRIBUTES sa;
50 latch->is_set = false;
52 latch->is_shared = true;
55 * Set up security attributes to specify that the events are inherited.
57 ZeroMemory(&sa, sizeof(sa));
58 sa.nLength = sizeof(sa);
59 sa.bInheritHandle = TRUE;
61 latch->event = CreateEvent(&sa, TRUE, FALSE, NULL);
62 if (latch->event == NULL)
63 elog(ERROR, "CreateEvent failed: error code %lu", GetLastError());
67 OwnLatch(volatile Latch *latch)
70 Assert(latch->is_shared);
71 if (latch->owner_pid != 0)
72 elog(ERROR, "latch already owned");
74 latch->owner_pid = MyProcPid;
78 DisownLatch(volatile Latch *latch)
80 Assert(latch->is_shared);
81 Assert(latch->owner_pid == MyProcPid);
87 WaitLatch(volatile Latch *latch, int wakeEvents, long timeout)
89 return WaitLatchOrSocket(latch, wakeEvents, PGINVALID_SOCKET, timeout);
93 WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
99 HANDLE sockevent = WSA_INVALID_EVENT;
102 int pmdeath_eventno = 0;
104 /* Ignore WL_SOCKET_* events if no valid socket is given */
105 if (sock == PGINVALID_SOCKET)
106 wakeEvents &= ~(WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE);
108 Assert(wakeEvents != 0); /* must have at least one wake event */
110 if ((wakeEvents & WL_LATCH_SET) && latch->owner_pid != MyProcPid)
111 elog(ERROR, "cannot wait on a latch owned by another process");
113 /* Convert timeout to form used by WaitForMultipleObjects() */
114 if (wakeEvents & WL_TIMEOUT)
115 Assert(timeout >= 0);
120 * Construct an array of event handles for WaitforMultipleObjects().
122 * Note: pgwin32_signal_event should be first to ensure that it will be
123 * reported when multiple events are set. We want to guarantee that
124 * pending signals are serviced.
126 latchevent = latch->event;
128 events[0] = pgwin32_signal_event;
129 events[1] = latchevent;
131 if (wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE))
133 /* Need an event object to represent events on the socket */
136 if (wakeEvents & WL_SOCKET_READABLE)
137 flags |= (FD_READ | FD_CLOSE);
138 if (wakeEvents & WL_SOCKET_WRITEABLE)
141 sockevent = WSACreateEvent();
142 if (sockevent == WSA_INVALID_EVENT)
143 elog(ERROR, "failed to create event for socket: error code %u",
145 if (WSAEventSelect(sock, sockevent, flags) != 0)
146 elog(ERROR, "failed to set up event for socket: error code %u",
149 events[numevents++] = sockevent;
151 if (wakeEvents & WL_POSTMASTER_DEATH)
153 pmdeath_eventno = numevents;
154 events[numevents++] = PostmasterHandle;
157 /* Ensure that signals are serviced even if latch is already set */
158 pgwin32_dispatch_queued_signals();
163 * Reset the event, and check if the latch is set already. If someone
164 * sets the latch between this and the WaitForMultipleObjects() call
165 * below, the setter will set the event and WaitForMultipleObjects()
166 * will return immediately.
168 if (!ResetEvent(latchevent))
169 elog(ERROR, "ResetEvent failed: error code %lu", GetLastError());
171 if ((wakeEvents & WL_LATCH_SET) && latch->is_set)
173 result |= WL_LATCH_SET;
175 * Leave loop immediately, avoid blocking again. We don't attempt
176 * to report any other events that might also be satisfied.
181 rc = WaitForMultipleObjects(numevents, events, FALSE, timeout);
183 if (rc == WAIT_FAILED)
184 elog(ERROR, "WaitForMultipleObjects() failed: error code %lu",
186 else if (rc == WAIT_TIMEOUT)
188 result |= WL_TIMEOUT;
190 else if (rc == WAIT_OBJECT_0)
192 /* Service newly-arrived signals */
193 pgwin32_dispatch_queued_signals();
195 else if (rc == WAIT_OBJECT_0 + 1)
197 /* Latch is set, we'll handle that on next iteration of loop */
199 else if ((wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE)) &&
200 rc == WAIT_OBJECT_0 + 2) /* socket is at event slot 2 */
202 WSANETWORKEVENTS resEvents;
204 ZeroMemory(&resEvents, sizeof(resEvents));
205 if (WSAEnumNetworkEvents(sock, sockevent, &resEvents) != 0)
206 elog(ERROR, "failed to enumerate network events: error code %u",
208 if ((wakeEvents & WL_SOCKET_READABLE) &&
209 (resEvents.lNetworkEvents & (FD_READ | FD_CLOSE)))
211 result |= WL_SOCKET_READABLE;
213 if ((wakeEvents & WL_SOCKET_WRITEABLE) &&
214 (resEvents.lNetworkEvents & FD_WRITE))
216 result |= WL_SOCKET_WRITEABLE;
219 else if ((wakeEvents & WL_POSTMASTER_DEATH) &&
220 rc == WAIT_OBJECT_0 + pmdeath_eventno)
223 * Postmaster apparently died. Since the consequences of falsely
224 * returning WL_POSTMASTER_DEATH could be pretty unpleasant, we
225 * take the trouble to positively verify this with
226 * PostmasterIsAlive(), even though there is no known reason to
227 * think that the event could be falsely set on Windows.
229 if (!PostmasterIsAlive())
230 result |= WL_POSTMASTER_DEATH;
233 elog(ERROR, "unexpected return code from WaitForMultipleObjects(): %lu", rc);
237 /* Clean up the event object we created for the socket */
238 if (sockevent != WSA_INVALID_EVENT)
240 WSAEventSelect(sock, NULL, 0);
241 WSACloseEvent(sockevent);
248 SetLatch(volatile Latch *latch)
252 /* Quick exit if already set */
256 latch->is_set = true;
259 * See if anyone's waiting for the latch. It can be the current process if
260 * we're in a signal handler.
262 * Use a local variable here just in case somebody changes the event field
263 * concurrently (which really should not happen).
265 handle = latch->event;
271 * Note that we silently ignore any errors. We might be in a signal
272 * handler or other critical path where it's not safe to call elog().
278 ResetLatch(volatile Latch *latch)
280 /* Only the owner should reset the latch */
281 Assert(latch->owner_pid == MyProcPid);
283 latch->is_set = false;