00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "postgres.h"
00021
00022 #include <fcntl.h>
00023 #include <limits.h>
00024 #include <signal.h>
00025 #include <unistd.h>
00026
00027 #include "miscadmin.h"
00028 #include "portability/instr_time.h"
00029 #include "postmaster/postmaster.h"
00030 #include "storage/latch.h"
00031 #include "storage/pmsignal.h"
00032 #include "storage/shmem.h"
00033
00034
00035 void
00036 InitializeLatchSupport(void)
00037 {
00038
00039 }
00040
00041 void
00042 InitLatch(volatile Latch *latch)
00043 {
00044 latch->is_set = false;
00045 latch->owner_pid = MyProcPid;
00046 latch->is_shared = false;
00047
00048 latch->event = CreateEvent(NULL, TRUE, FALSE, NULL);
00049 if (latch->event == NULL)
00050 elog(ERROR, "CreateEvent failed: error code %lu", GetLastError());
00051 }
00052
00053 void
00054 InitSharedLatch(volatile Latch *latch)
00055 {
00056 SECURITY_ATTRIBUTES sa;
00057
00058 latch->is_set = false;
00059 latch->owner_pid = 0;
00060 latch->is_shared = true;
00061
00062
00063
00064
00065 ZeroMemory(&sa, sizeof(sa));
00066 sa.nLength = sizeof(sa);
00067 sa.bInheritHandle = TRUE;
00068
00069 latch->event = CreateEvent(&sa, TRUE, FALSE, NULL);
00070 if (latch->event == NULL)
00071 elog(ERROR, "CreateEvent failed: error code %lu", GetLastError());
00072 }
00073
00074 void
00075 OwnLatch(volatile Latch *latch)
00076 {
00077
00078 Assert(latch->is_shared);
00079 if (latch->owner_pid != 0)
00080 elog(ERROR, "latch already owned");
00081
00082 latch->owner_pid = MyProcPid;
00083 }
00084
00085 void
00086 DisownLatch(volatile Latch *latch)
00087 {
00088 Assert(latch->is_shared);
00089 Assert(latch->owner_pid == MyProcPid);
00090
00091 latch->owner_pid = 0;
00092 }
00093
00094 int
00095 WaitLatch(volatile Latch *latch, int wakeEvents, long timeout)
00096 {
00097 return WaitLatchOrSocket(latch, wakeEvents, PGINVALID_SOCKET, timeout);
00098 }
00099
00100 int
00101 WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
00102 long timeout)
00103 {
00104 DWORD rc;
00105 instr_time start_time,
00106 cur_time;
00107 long cur_timeout;
00108 HANDLE events[4];
00109 HANDLE latchevent;
00110 HANDLE sockevent = WSA_INVALID_EVENT;
00111 int numevents;
00112 int result = 0;
00113 int pmdeath_eventno = 0;
00114
00115
00116 if (sock == PGINVALID_SOCKET)
00117 wakeEvents &= ~(WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE);
00118
00119 Assert(wakeEvents != 0);
00120
00121 Assert((wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE)) != WL_SOCKET_WRITEABLE);
00122
00123 if ((wakeEvents & WL_LATCH_SET) && latch->owner_pid != MyProcPid)
00124 elog(ERROR, "cannot wait on a latch owned by another process");
00125
00126
00127
00128
00129
00130
00131 if (wakeEvents & WL_TIMEOUT)
00132 {
00133 INSTR_TIME_SET_CURRENT(start_time);
00134 Assert(timeout >= 0 && timeout <= INT_MAX);
00135 cur_timeout = timeout;
00136 }
00137 else
00138 cur_timeout = INFINITE;
00139
00140
00141
00142
00143
00144
00145
00146
00147 latchevent = latch->event;
00148
00149 events[0] = pgwin32_signal_event;
00150 events[1] = latchevent;
00151 numevents = 2;
00152 if (wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE))
00153 {
00154
00155 int flags = 0;
00156
00157 if (wakeEvents & WL_SOCKET_READABLE)
00158 flags |= (FD_READ | FD_CLOSE);
00159 if (wakeEvents & WL_SOCKET_WRITEABLE)
00160 flags |= FD_WRITE;
00161
00162 sockevent = WSACreateEvent();
00163 if (sockevent == WSA_INVALID_EVENT)
00164 elog(ERROR, "failed to create event for socket: error code %u",
00165 WSAGetLastError());
00166 if (WSAEventSelect(sock, sockevent, flags) != 0)
00167 elog(ERROR, "failed to set up event for socket: error code %u",
00168 WSAGetLastError());
00169
00170 events[numevents++] = sockevent;
00171 }
00172 if (wakeEvents & WL_POSTMASTER_DEATH)
00173 {
00174 pmdeath_eventno = numevents;
00175 events[numevents++] = PostmasterHandle;
00176 }
00177
00178
00179 pgwin32_dispatch_queued_signals();
00180
00181 do
00182 {
00183
00184
00185
00186
00187
00188
00189 if (!ResetEvent(latchevent))
00190 elog(ERROR, "ResetEvent failed: error code %lu", GetLastError());
00191
00192 if ((wakeEvents & WL_LATCH_SET) && latch->is_set)
00193 {
00194 result |= WL_LATCH_SET;
00195
00196
00197
00198
00199
00200 break;
00201 }
00202
00203 rc = WaitForMultipleObjects(numevents, events, FALSE, cur_timeout);
00204
00205 if (rc == WAIT_FAILED)
00206 elog(ERROR, "WaitForMultipleObjects() failed: error code %lu",
00207 GetLastError());
00208 else if (rc == WAIT_TIMEOUT)
00209 {
00210 result |= WL_TIMEOUT;
00211 }
00212 else if (rc == WAIT_OBJECT_0)
00213 {
00214
00215 pgwin32_dispatch_queued_signals();
00216 }
00217 else if (rc == WAIT_OBJECT_0 + 1)
00218 {
00219
00220
00221
00222
00223 continue;
00224 }
00225 else if ((wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE)) &&
00226 rc == WAIT_OBJECT_0 + 2)
00227 {
00228 WSANETWORKEVENTS resEvents;
00229
00230 ZeroMemory(&resEvents, sizeof(resEvents));
00231 if (WSAEnumNetworkEvents(sock, sockevent, &resEvents) != 0)
00232 elog(ERROR, "failed to enumerate network events: error code %u",
00233 WSAGetLastError());
00234 if ((wakeEvents & WL_SOCKET_READABLE) &&
00235 (resEvents.lNetworkEvents & (FD_READ | FD_CLOSE)))
00236 {
00237 result |= WL_SOCKET_READABLE;
00238 }
00239 if ((wakeEvents & WL_SOCKET_WRITEABLE) &&
00240 (resEvents.lNetworkEvents & FD_WRITE))
00241 {
00242 result |= WL_SOCKET_WRITEABLE;
00243 }
00244 }
00245 else if ((wakeEvents & WL_POSTMASTER_DEATH) &&
00246 rc == WAIT_OBJECT_0 + pmdeath_eventno)
00247 {
00248
00249
00250
00251
00252
00253
00254
00255 if (!PostmasterIsAlive())
00256 result |= WL_POSTMASTER_DEATH;
00257 }
00258 else
00259 elog(ERROR, "unexpected return code from WaitForMultipleObjects(): %lu", rc);
00260
00261
00262 if (result == 0 && cur_timeout != INFINITE)
00263 {
00264 INSTR_TIME_SET_CURRENT(cur_time);
00265 INSTR_TIME_SUBTRACT(cur_time, start_time);
00266 cur_timeout = timeout - (long) INSTR_TIME_GET_MILLISEC(cur_time);
00267 if (cur_timeout < 0)
00268 cur_timeout = 0;
00269 }
00270 } while (result == 0);
00271
00272
00273 if (sockevent != WSA_INVALID_EVENT)
00274 {
00275 WSAEventSelect(sock, NULL, 0);
00276 WSACloseEvent(sockevent);
00277 }
00278
00279 return result;
00280 }
00281
00282
00283
00284
00285
00286 void
00287 SetLatch(volatile Latch *latch)
00288 {
00289 HANDLE handle;
00290
00291
00292 if (latch->is_set)
00293 return;
00294
00295 latch->is_set = true;
00296
00297
00298
00299
00300
00301
00302
00303
00304 handle = latch->event;
00305 if (handle)
00306 {
00307 SetEvent(handle);
00308
00309
00310
00311
00312
00313 }
00314 }
00315
00316 void
00317 ResetLatch(volatile Latch *latch)
00318 {
00319
00320 Assert(latch->owner_pid == MyProcPid);
00321
00322 latch->is_set = false;
00323 }