Header And Logo

PostgreSQL
| The world's most advanced open source database.

win32_latch.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * win32_latch.c
00004  *    Routines for inter-process latches
00005  *
00006  * See unix_latch.c for header comments for the exported functions;
00007  * the API presented here is supposed to be the same as there.
00008  *
00009  * The Windows implementation uses Windows events that are inherited by
00010  * all postmaster child processes.
00011  *
00012  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00013  * Portions Copyright (c) 1994, Regents of the University of California
00014  *
00015  * IDENTIFICATION
00016  *    src/backend/port/win32_latch.c
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     /* currently, nothing to do here for Windows */
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      * Set up security attributes to specify that the events are inherited.
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     /* Sanity checks */
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     /* Ignore WL_SOCKET_* events if no valid socket is given */
00116     if (sock == PGINVALID_SOCKET)
00117         wakeEvents &= ~(WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE);
00118 
00119     Assert(wakeEvents != 0);    /* must have at least one wake event */
00120     /* Cannot specify WL_SOCKET_WRITEABLE without WL_SOCKET_READABLE */
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      * Initialize timeout if requested.  We must record the current time so
00128      * that we can determine the remaining timeout if WaitForMultipleObjects
00129      * is interrupted.
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      * Construct an array of event handles for WaitforMultipleObjects().
00142      *
00143      * Note: pgwin32_signal_event should be first to ensure that it will be
00144      * reported when multiple events are set.  We want to guarantee that
00145      * pending signals are serviced.
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         /* Need an event object to represent events on the socket */
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     /* Ensure that signals are serviced even if latch is already set */
00179     pgwin32_dispatch_queued_signals();
00180 
00181     do
00182     {
00183         /*
00184          * Reset the event, and check if the latch is set already. If someone
00185          * sets the latch between this and the WaitForMultipleObjects() call
00186          * below, the setter will set the event and WaitForMultipleObjects()
00187          * will return immediately.
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              * Leave loop immediately, avoid blocking again. We don't attempt
00198              * to report any other events that might also be satisfied.
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             /* Service newly-arrived signals */
00215             pgwin32_dispatch_queued_signals();
00216         }
00217         else if (rc == WAIT_OBJECT_0 + 1)
00218         {
00219             /*
00220              * Latch is set.  We'll handle that on next iteration of loop, but
00221              * let's not waste the cycles to update cur_timeout below.
00222              */
00223             continue;
00224         }
00225         else if ((wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE)) &&
00226                  rc == WAIT_OBJECT_0 + 2)       /* socket is at event slot 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              * Postmaster apparently died.  Since the consequences of falsely
00250              * returning WL_POSTMASTER_DEATH could be pretty unpleasant, we
00251              * take the trouble to positively verify this with
00252              * PostmasterIsAlive(), even though there is no known reason to
00253              * think that the event could be falsely set on Windows.
00254              */
00255             if (!PostmasterIsAlive())
00256                 result |= WL_POSTMASTER_DEATH;
00257         }
00258         else
00259             elog(ERROR, "unexpected return code from WaitForMultipleObjects(): %lu", rc);
00260 
00261         /* If we're not done, update cur_timeout for next iteration */
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     /* Clean up the event object we created for the socket */
00273     if (sockevent != WSA_INVALID_EVENT)
00274     {
00275         WSAEventSelect(sock, NULL, 0);
00276         WSACloseEvent(sockevent);
00277     }
00278 
00279     return result;
00280 }
00281 
00282 /*
00283  * The comments above the unix implementation (unix_latch.c) of this function
00284  * apply here as well.
00285  */
00286 void
00287 SetLatch(volatile Latch *latch)
00288 {
00289     HANDLE      handle;
00290 
00291     /* Quick exit if already set */
00292     if (latch->is_set)
00293         return;
00294 
00295     latch->is_set = true;
00296 
00297     /*
00298      * See if anyone's waiting for the latch. It can be the current process if
00299      * we're in a signal handler.
00300      *
00301      * Use a local variable here just in case somebody changes the event field
00302      * concurrently (which really should not happen).
00303      */
00304     handle = latch->event;
00305     if (handle)
00306     {
00307         SetEvent(handle);
00308 
00309         /*
00310          * Note that we silently ignore any errors. We might be in a signal
00311          * handler or other critical path where it's not safe to call elog().
00312          */
00313     }
00314 }
00315 
00316 void
00317 ResetLatch(volatile Latch *latch)
00318 {
00319     /* Only the owner should reset the latch */
00320     Assert(latch->owner_pid == MyProcPid);
00321 
00322     latch->is_set = false;
00323 }