SHMEM_IMPLEMENTATION="src/backend/port/win32_shmem.c"
fi
-# Select latch implementation type.
-if test "$PORTNAME" != "win32"; then
- LATCH_IMPLEMENTATION="src/backend/port/unix_latch.c"
-else
- LATCH_IMPLEMENTATION="src/backend/port/win32_latch.c"
-fi
-
# If not set in template file, set bytes to use libc memset()
if test x"$MEMSET_LOOP_LIMIT" = x"" ; then
MEMSET_LOOP_LIMIT=1024
ac_config_files="$ac_config_files GNUmakefile src/Makefile.global"
-ac_config_links="$ac_config_links src/backend/port/dynloader.c:src/backend/port/dynloader/${template}.c src/backend/port/pg_sema.c:${SEMA_IMPLEMENTATION} src/backend/port/pg_shmem.c:${SHMEM_IMPLEMENTATION} src/backend/port/pg_latch.c:${LATCH_IMPLEMENTATION} src/include/dynloader.h:src/backend/port/dynloader/${template}.h src/include/pg_config_os.h:src/include/port/${template}.h src/Makefile.port:src/makefiles/Makefile.${template}"
+ac_config_links="$ac_config_links src/backend/port/dynloader.c:src/backend/port/dynloader/${template}.c src/backend/port/pg_sema.c:${SEMA_IMPLEMENTATION} src/backend/port/pg_shmem.c:${SHMEM_IMPLEMENTATION} src/include/dynloader.h:src/backend/port/dynloader/${template}.h src/include/pg_config_os.h:src/include/port/${template}.h src/Makefile.port:src/makefiles/Makefile.${template}"
if test "$PORTNAME" = "win32"; then
"src/backend/port/dynloader.c") CONFIG_LINKS="$CONFIG_LINKS src/backend/port/dynloader.c:src/backend/port/dynloader/${template}.c" ;;
"src/backend/port/pg_sema.c") CONFIG_LINKS="$CONFIG_LINKS src/backend/port/pg_sema.c:${SEMA_IMPLEMENTATION}" ;;
"src/backend/port/pg_shmem.c") CONFIG_LINKS="$CONFIG_LINKS src/backend/port/pg_shmem.c:${SHMEM_IMPLEMENTATION}" ;;
- "src/backend/port/pg_latch.c") CONFIG_LINKS="$CONFIG_LINKS src/backend/port/pg_latch.c:${LATCH_IMPLEMENTATION}" ;;
"src/include/dynloader.h") CONFIG_LINKS="$CONFIG_LINKS src/include/dynloader.h:src/backend/port/dynloader/${template}.h" ;;
"src/include/pg_config_os.h") CONFIG_LINKS="$CONFIG_LINKS src/include/pg_config_os.h:src/include/port/${template}.h" ;;
"src/Makefile.port") CONFIG_LINKS="$CONFIG_LINKS src/Makefile.port:src/makefiles/Makefile.${template}" ;;
SHMEM_IMPLEMENTATION="src/backend/port/win32_shmem.c"
fi
-# Select latch implementation type.
-if test "$PORTNAME" != "win32"; then
- LATCH_IMPLEMENTATION="src/backend/port/unix_latch.c"
-else
- LATCH_IMPLEMENTATION="src/backend/port/win32_latch.c"
-fi
-
# If not set in template file, set bytes to use libc memset()
if test x"$MEMSET_LOOP_LIMIT" = x"" ; then
MEMSET_LOOP_LIMIT=1024
src/backend/port/dynloader.c:src/backend/port/dynloader/${template}.c
src/backend/port/pg_sema.c:${SEMA_IMPLEMENTATION}
src/backend/port/pg_shmem.c:${SHMEM_IMPLEMENTATION}
- src/backend/port/pg_latch.c:${LATCH_IMPLEMENTATION}
src/include/dynloader.h:src/backend/port/dynloader/${template}.h
src/include/pg_config_os.h:src/include/port/${template}.h
src/Makefile.port:src/makefiles/Makefile.${template}
endif
distclean: clean
- rm -f port/tas.s port/dynloader.c port/pg_sema.c port/pg_shmem.c \
- port/pg_latch.c
+ rm -f port/tas.s port/dynloader.c port/pg_sema.c port/pg_shmem.c
maintainer-clean: distclean
rm -f bootstrap/bootparse.c \
/dynloader.c
-/pg_latch.c
/pg_sema.c
/pg_shmem.c
/tas.s
top_builddir = ../../..
include $(top_builddir)/src/Makefile.global
-OBJS = atomics.o dynloader.o pg_sema.o pg_shmem.o pg_latch.o $(TAS)
+OBJS = atomics.o dynloader.o pg_sema.o pg_shmem.o $(TAS)
ifeq ($(PORTNAME), darwin)
SUBDIRS += darwin
+++ /dev/null
-/*-------------------------------------------------------------------------
- *
- * win32_latch.c
- * Routines for inter-process latches
- *
- * 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.
- *
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * IDENTIFICATION
- * src/backend/port/win32_latch.c
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres.h"
-
-#include <fcntl.h>
-#include <limits.h>
-#include <signal.h>
-#include <unistd.h>
-
-#include "miscadmin.h"
-#include "portability/instr_time.h"
-#include "postmaster/postmaster.h"
-#include "storage/barrier.h"
-#include "storage/latch.h"
-#include "storage/pmsignal.h"
-#include "storage/shmem.h"
-
-
-void
-InitializeLatchSupport(void)
-{
- /* currently, nothing to do here for Windows */
-}
-
-void
-InitLatch(volatile Latch *latch)
-{
- latch->is_set = false;
- latch->owner_pid = MyProcPid;
- latch->is_shared = false;
-
- latch->event = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (latch->event == NULL)
- elog(ERROR, "CreateEvent failed: error code %lu", GetLastError());
-}
-
-void
-InitSharedLatch(volatile Latch *latch)
-{
- SECURITY_ATTRIBUTES sa;
-
- latch->is_set = false;
- latch->owner_pid = 0;
- latch->is_shared = true;
-
- /*
- * Set up security attributes to specify that the events are inherited.
- */
- ZeroMemory(&sa, sizeof(sa));
- sa.nLength = sizeof(sa);
- sa.bInheritHandle = TRUE;
-
- latch->event = CreateEvent(&sa, TRUE, FALSE, NULL);
- if (latch->event == NULL)
- elog(ERROR, "CreateEvent failed: error code %lu", GetLastError());
-}
-
-void
-OwnLatch(volatile Latch *latch)
-{
- /* Sanity checks */
- Assert(latch->is_shared);
- if (latch->owner_pid != 0)
- elog(ERROR, "latch already owned");
-
- latch->owner_pid = MyProcPid;
-}
-
-void
-DisownLatch(volatile Latch *latch)
-{
- Assert(latch->is_shared);
- Assert(latch->owner_pid == MyProcPid);
-
- latch->owner_pid = 0;
-}
-
-int
-WaitLatch(volatile Latch *latch, int wakeEvents, long timeout)
-{
- return WaitLatchOrSocket(latch, wakeEvents, PGINVALID_SOCKET, timeout);
-}
-
-int
-WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
- long timeout)
-{
- DWORD rc;
- instr_time start_time,
- cur_time;
- long cur_timeout;
- HANDLE events[4];
- HANDLE latchevent;
- HANDLE sockevent = WSA_INVALID_EVENT;
- int numevents;
- int result = 0;
- int pmdeath_eventno = 0;
-
- Assert(wakeEvents != 0); /* must have at least one wake event */
-
- /* waiting for socket readiness without a socket indicates a bug */
- if (sock == PGINVALID_SOCKET &&
- (wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE)) != 0)
- elog(ERROR, "cannot wait on socket event without a socket");
-
- if ((wakeEvents & WL_LATCH_SET) && latch->owner_pid != MyProcPid)
- elog(ERROR, "cannot wait on a latch owned by another process");
-
- /*
- * Initialize timeout if requested. We must record the current time so
- * that we can determine the remaining timeout if WaitForMultipleObjects
- * is interrupted.
- */
- if (wakeEvents & WL_TIMEOUT)
- {
- INSTR_TIME_SET_CURRENT(start_time);
- Assert(timeout >= 0 && timeout <= INT_MAX);
- cur_timeout = timeout;
- }
- else
- cur_timeout = INFINITE;
-
- /*
- * Construct an array of event handles for WaitforMultipleObjects().
- *
- * Note: pgwin32_signal_event should be first to ensure that it will be
- * reported when multiple events are set. We want to guarantee that
- * pending signals are serviced.
- */
- latchevent = latch->event;
-
- events[0] = pgwin32_signal_event;
- events[1] = latchevent;
- numevents = 2;
- if (wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE))
- {
- /* Need an event object to represent events on the socket */
- int flags = FD_CLOSE; /* always check for errors/EOF */
-
- if (wakeEvents & WL_SOCKET_READABLE)
- flags |= FD_READ;
- if (wakeEvents & WL_SOCKET_WRITEABLE)
- flags |= FD_WRITE;
-
- sockevent = WSACreateEvent();
- if (sockevent == WSA_INVALID_EVENT)
- elog(ERROR, "failed to create event for socket: error code %u",
- WSAGetLastError());
- if (WSAEventSelect(sock, sockevent, flags) != 0)
- elog(ERROR, "failed to set up event for socket: error code %u",
- WSAGetLastError());
-
- events[numevents++] = sockevent;
- }
- if (wakeEvents & WL_POSTMASTER_DEATH)
- {
- pmdeath_eventno = numevents;
- events[numevents++] = PostmasterHandle;
- }
-
- /* Ensure that signals are serviced even if latch is already set */
- pgwin32_dispatch_queued_signals();
-
- do
- {
- /*
- * The comment in unix_latch.c's equivalent to this applies here as
- * well. At least after mentally replacing self-pipe with windows
- * event. There's no danger of overflowing, as "Setting an event that
- * is already set has no effect.".
- */
- if ((wakeEvents & WL_LATCH_SET) && latch->is_set)
- {
- result |= WL_LATCH_SET;
-
- /*
- * Leave loop immediately, avoid blocking again. We don't attempt
- * to report any other events that might also be satisfied.
- */
- break;
- }
-
- rc = WaitForMultipleObjects(numevents, events, FALSE, cur_timeout);
-
- if (rc == WAIT_FAILED)
- elog(ERROR, "WaitForMultipleObjects() failed: error code %lu",
- GetLastError());
- else if (rc == WAIT_TIMEOUT)
- {
- result |= WL_TIMEOUT;
- }
- else if (rc == WAIT_OBJECT_0)
- {
- /* Service newly-arrived signals */
- pgwin32_dispatch_queued_signals();
- }
- else if (rc == WAIT_OBJECT_0 + 1)
- {
- /*
- * Reset the event. We'll re-check the, potentially, set latch on
- * next iteration of loop, but let's not waste the cycles to
- * update cur_timeout below.
- */
- if (!ResetEvent(latchevent))
- elog(ERROR, "ResetEvent failed: error code %lu", GetLastError());
-
- continue;
- }
- else if ((wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE)) &&
- rc == WAIT_OBJECT_0 + 2) /* socket is at event slot 2 */
- {
- WSANETWORKEVENTS resEvents;
-
- ZeroMemory(&resEvents, sizeof(resEvents));
- if (WSAEnumNetworkEvents(sock, sockevent, &resEvents) != 0)
- elog(ERROR, "failed to enumerate network events: error code %u",
- WSAGetLastError());
- if ((wakeEvents & WL_SOCKET_READABLE) &&
- (resEvents.lNetworkEvents & FD_READ))
- {
- result |= WL_SOCKET_READABLE;
- }
- if ((wakeEvents & WL_SOCKET_WRITEABLE) &&
- (resEvents.lNetworkEvents & FD_WRITE))
- {
- result |= WL_SOCKET_WRITEABLE;
- }
- if (resEvents.lNetworkEvents & FD_CLOSE)
- {
- if (wakeEvents & WL_SOCKET_READABLE)
- result |= WL_SOCKET_READABLE;
- if (wakeEvents & WL_SOCKET_WRITEABLE)
- result |= WL_SOCKET_WRITEABLE;
- }
- }
- else if ((wakeEvents & WL_POSTMASTER_DEATH) &&
- rc == WAIT_OBJECT_0 + pmdeath_eventno)
- {
- /*
- * Postmaster apparently died. Since the consequences of falsely
- * returning WL_POSTMASTER_DEATH could be pretty unpleasant, we
- * take the trouble to positively verify this with
- * PostmasterIsAlive(), even though there is no known reason to
- * think that the event could be falsely set on Windows.
- */
- if (!PostmasterIsAlive())
- result |= WL_POSTMASTER_DEATH;
- }
- else
- elog(ERROR, "unexpected return code from WaitForMultipleObjects(): %lu", rc);
-
- /* If we're not done, update cur_timeout for next iteration */
- if (result == 0 && (wakeEvents & WL_TIMEOUT))
- {
- INSTR_TIME_SET_CURRENT(cur_time);
- INSTR_TIME_SUBTRACT(cur_time, start_time);
- cur_timeout = timeout - (long) INSTR_TIME_GET_MILLISEC(cur_time);
- if (cur_timeout <= 0)
- {
- /* Timeout has expired, no need to continue looping */
- result |= WL_TIMEOUT;
- }
- }
- } while (result == 0);
-
- /* Clean up the event object we created for the socket */
- if (sockevent != WSA_INVALID_EVENT)
- {
- WSAEventSelect(sock, NULL, 0);
- WSACloseEvent(sockevent);
- }
-
- return result;
-}
-
-/*
- * The comments above the unix implementation (unix_latch.c) of this function
- * apply here as well.
- */
-void
-SetLatch(volatile Latch *latch)
-{
- HANDLE handle;
-
- /*
- * The memory barrier has be to be placed here to ensure that any flag
- * variables possibly changed by this process have been flushed to main
- * memory, before we check/set is_set.
- */
- pg_memory_barrier();
-
- /* Quick exit if already set */
- if (latch->is_set)
- return;
-
- latch->is_set = true;
-
- /*
- * 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 just in case somebody changes the event field
- * concurrently (which really should not happen).
- */
- handle = latch->event;
- if (handle)
- {
- SetEvent(handle);
-
- /*
- * Note that we silently ignore any errors. We might be in a signal
- * handler or other critical path where it's not safe to call elog().
- */
- }
-}
-
-void
-ResetLatch(volatile Latch *latch)
-{
- /* Only the owner should reset the latch */
- Assert(latch->owner_pid == MyProcPid);
-
- latch->is_set = false;
-
- /*
- * Ensure that the write to is_set gets flushed to main memory before we
- * examine any flag variables. Otherwise a concurrent SetLatch might
- * falsely conclude that it needn't signal us, even though we have missed
- * seeing some flag updates that SetLatch was supposed to inform us of.
- */
- pg_memory_barrier();
-}
top_builddir = ../../../..
include $(top_builddir)/src/Makefile.global
-OBJS = dsm_impl.o dsm.o ipc.o ipci.o pmsignal.o procarray.o procsignal.o \
- shmem.o shmqueue.o shm_mq.o shm_toc.o sinval.o sinvaladt.o standby.o
+OBJS = dsm_impl.o dsm.o ipc.o ipci.o latch.o pmsignal.o procarray.o \
+ procsignal.o shmem.o shmqueue.o shm_mq.o shm_toc.o sinval.o \
+ sinvaladt.o standby.o
include $(top_srcdir)/src/backend/common.mk
/*-------------------------------------------------------------------------
*
- * unix_latch.c
+ * latch.c
* Routines for inter-process latches
*
* The Unix implementation uses the so-called self-pipe trick to overcome
* process, SIGUSR1 is sent and the signal handler in the waiting process
* writes the byte to the pipe on behalf of the signaling process.
*
+ * The Windows implementation uses Windows events that are inherited by
+ * all postmaster child processes.
+ *
* Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * src/backend/port/unix_latch.c
+ * src/backend/storage/ipc/latch.c
*
*-------------------------------------------------------------------------
*/
* useful to manually specify the used primitive. If desired, just add a
* define somewhere before this block.
*/
-#if defined(LATCH_USE_POLL) || defined(LATCH_USE_SELECT)
+#if defined(LATCH_USE_POLL) || defined(LATCH_USE_SELECT) \
+ || defined(LATCH_USE_WIN32)
/* don't overwrite manual choice */
#elif defined(HAVE_POLL)
#define LATCH_USE_POLL
#elif HAVE_SYS_SELECT_H
#define LATCH_USE_SELECT
+#elif WIN32
+#define LATCH_USE_WIN32
#else
#error "no latch implementation available"
#endif
+#ifndef WIN32
/* Are we currently in WaitLatch? The signal handler would like to know. */
static volatile sig_atomic_t waiting = false;
/* Private function prototypes */
static void sendSelfPipeByte(void);
static void drainSelfPipe(void);
+#endif /* WIN32 */
/*
void
InitializeLatchSupport(void)
{
+#ifndef WIN32
int pipefd[2];
Assert(selfpipe_readfd == -1);
selfpipe_readfd = pipefd[0];
selfpipe_writefd = pipefd[1];
+#else
+ /* currently, nothing to do here for Windows */
+#endif
}
/*
void
InitLatch(volatile Latch *latch)
{
- /* Assert InitializeLatchSupport has been called in this process */
- Assert(selfpipe_readfd >= 0);
-
latch->is_set = false;
latch->owner_pid = MyProcPid;
latch->is_shared = false;
+
+#ifndef WIN32
+ /* Assert InitializeLatchSupport has been called in this process */
+ Assert(selfpipe_readfd >= 0);
+#else
+ latch->event = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (latch->event == NULL)
+ elog(ERROR, "CreateEvent failed: error code %lu", GetLastError());
+#endif /* WIN32 */
}
/*
void
InitSharedLatch(volatile Latch *latch)
{
+#ifdef WIN32
+ SECURITY_ATTRIBUTES sa;
+
+ /*
+ * Set up security attributes to specify that the events are inherited.
+ */
+ ZeroMemory(&sa, sizeof(sa));
+ sa.nLength = sizeof(sa);
+ sa.bInheritHandle = TRUE;
+
+ latch->event = CreateEvent(&sa, TRUE, FALSE, NULL);
+ if (latch->event == NULL)
+ elog(ERROR, "CreateEvent failed: error code %lu", GetLastError());
+#endif
+
latch->is_set = false;
latch->owner_pid = 0;
latch->is_shared = true;
void
OwnLatch(volatile Latch *latch)
{
+ /* Sanity checks */
+ Assert(latch->is_shared);
+
+#ifndef WIN32
/* Assert InitializeLatchSupport has been called in this process */
Assert(selfpipe_readfd >= 0);
+#endif
- Assert(latch->is_shared);
-
- /* sanity check */
if (latch->owner_pid != 0)
elog(ERROR, "latch already owned");
* returning the socket as readable/writable or both, depending on
* WL_SOCKET_READABLE/WL_SOCKET_WRITEABLE being specified.
*/
+#ifndef LATCH_USE_WIN32
int
WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
long timeout)
return result;
}
+#else /* LATCH_USE_WIN32 */
+int
+WaitLatchOrSocket(volatile Latch *latch, int wakeEvents, pgsocket sock,
+ long timeout)
+{
+ DWORD rc;
+ instr_time start_time,
+ cur_time;
+ long cur_timeout;
+ HANDLE events[4];
+ HANDLE latchevent;
+ HANDLE sockevent = WSA_INVALID_EVENT;
+ int numevents;
+ int result = 0;
+ int pmdeath_eventno = 0;
+
+ Assert(wakeEvents != 0); /* must have at least one wake event */
+
+ /* waiting for socket readiness without a socket indicates a bug */
+ if (sock == PGINVALID_SOCKET &&
+ (wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE)) != 0)
+ elog(ERROR, "cannot wait on socket event without a socket");
+
+ if ((wakeEvents & WL_LATCH_SET) && latch->owner_pid != MyProcPid)
+ elog(ERROR, "cannot wait on a latch owned by another process");
+
+ /*
+ * Initialize timeout if requested. We must record the current time so
+ * that we can determine the remaining timeout if WaitForMultipleObjects
+ * is interrupted.
+ */
+ if (wakeEvents & WL_TIMEOUT)
+ {
+ INSTR_TIME_SET_CURRENT(start_time);
+ Assert(timeout >= 0 && timeout <= INT_MAX);
+ cur_timeout = timeout;
+ }
+ else
+ cur_timeout = INFINITE;
+
+ /*
+ * Construct an array of event handles for WaitforMultipleObjects().
+ *
+ * Note: pgwin32_signal_event should be first to ensure that it will be
+ * reported when multiple events are set. We want to guarantee that
+ * pending signals are serviced.
+ */
+ latchevent = latch->event;
+
+ events[0] = pgwin32_signal_event;
+ events[1] = latchevent;
+ numevents = 2;
+ if (wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE))
+ {
+ /* Need an event object to represent events on the socket */
+ int flags = FD_CLOSE; /* always check for errors/EOF */
+
+ if (wakeEvents & WL_SOCKET_READABLE)
+ flags |= FD_READ;
+ if (wakeEvents & WL_SOCKET_WRITEABLE)
+ flags |= FD_WRITE;
+
+ sockevent = WSACreateEvent();
+ if (sockevent == WSA_INVALID_EVENT)
+ elog(ERROR, "failed to create event for socket: error code %u",
+ WSAGetLastError());
+ if (WSAEventSelect(sock, sockevent, flags) != 0)
+ elog(ERROR, "failed to set up event for socket: error code %u",
+ WSAGetLastError());
+
+ events[numevents++] = sockevent;
+ }
+ if (wakeEvents & WL_POSTMASTER_DEATH)
+ {
+ pmdeath_eventno = numevents;
+ events[numevents++] = PostmasterHandle;
+ }
+
+ /* Ensure that signals are serviced even if latch is already set */
+ pgwin32_dispatch_queued_signals();
+
+ do
+ {
+ /*
+ * The comment in the unix version above applies here as well. At
+ * least after mentally replacing self-pipe with windows event.
+ * There's no danger of overflowing, as "Setting an event that is
+ * already set has no effect.".
+ */
+ if ((wakeEvents & WL_LATCH_SET) && latch->is_set)
+ {
+ result |= WL_LATCH_SET;
+
+ /*
+ * Leave loop immediately, avoid blocking again. We don't attempt
+ * to report any other events that might also be satisfied.
+ */
+ break;
+ }
+
+ rc = WaitForMultipleObjects(numevents, events, FALSE, cur_timeout);
+
+ if (rc == WAIT_FAILED)
+ elog(ERROR, "WaitForMultipleObjects() failed: error code %lu",
+ GetLastError());
+ else if (rc == WAIT_TIMEOUT)
+ {
+ result |= WL_TIMEOUT;
+ }
+ else if (rc == WAIT_OBJECT_0)
+ {
+ /* Service newly-arrived signals */
+ pgwin32_dispatch_queued_signals();
+ }
+ else if (rc == WAIT_OBJECT_0 + 1)
+ {
+ /*
+ * Reset the event. We'll re-check the, potentially, set latch on
+ * next iteration of loop, but let's not waste the cycles to
+ * update cur_timeout below.
+ */
+ if (!ResetEvent(latchevent))
+ elog(ERROR, "ResetEvent failed: error code %lu", GetLastError());
+
+ continue;
+ }
+ else if ((wakeEvents & (WL_SOCKET_READABLE | WL_SOCKET_WRITEABLE)) &&
+ rc == WAIT_OBJECT_0 + 2) /* socket is at event slot 2 */
+ {
+ WSANETWORKEVENTS resEvents;
+
+ ZeroMemory(&resEvents, sizeof(resEvents));
+ if (WSAEnumNetworkEvents(sock, sockevent, &resEvents) != 0)
+ elog(ERROR, "failed to enumerate network events: error code %u",
+ WSAGetLastError());
+ if ((wakeEvents & WL_SOCKET_READABLE) &&
+ (resEvents.lNetworkEvents & FD_READ))
+ {
+ result |= WL_SOCKET_READABLE;
+ }
+ if ((wakeEvents & WL_SOCKET_WRITEABLE) &&
+ (resEvents.lNetworkEvents & FD_WRITE))
+ {
+ result |= WL_SOCKET_WRITEABLE;
+ }
+ if (resEvents.lNetworkEvents & FD_CLOSE)
+ {
+ if (wakeEvents & WL_SOCKET_READABLE)
+ result |= WL_SOCKET_READABLE;
+ if (wakeEvents & WL_SOCKET_WRITEABLE)
+ result |= WL_SOCKET_WRITEABLE;
+ }
+ }
+ else if ((wakeEvents & WL_POSTMASTER_DEATH) &&
+ rc == WAIT_OBJECT_0 + pmdeath_eventno)
+ {
+ /*
+ * Postmaster apparently died. Since the consequences of falsely
+ * returning WL_POSTMASTER_DEATH could be pretty unpleasant, we
+ * take the trouble to positively verify this with
+ * PostmasterIsAlive(), even though there is no known reason to
+ * think that the event could be falsely set on Windows.
+ */
+ if (!PostmasterIsAlive())
+ result |= WL_POSTMASTER_DEATH;
+ }
+ else
+ elog(ERROR, "unexpected return code from WaitForMultipleObjects(): %lu", rc);
+
+ /* If we're not done, update cur_timeout for next iteration */
+ if (result == 0 && (wakeEvents & WL_TIMEOUT))
+ {
+ INSTR_TIME_SET_CURRENT(cur_time);
+ INSTR_TIME_SUBTRACT(cur_time, start_time);
+ cur_timeout = timeout - (long) INSTR_TIME_GET_MILLISEC(cur_time);
+ if (cur_timeout <= 0)
+ {
+ /* Timeout has expired, no need to continue looping */
+ result |= WL_TIMEOUT;
+ }
+ }
+ } while (result == 0);
+
+ /* Clean up the event object we created for the socket */
+ if (sockevent != WSA_INVALID_EVENT)
+ {
+ WSAEventSelect(sock, NULL, 0);
+ WSACloseEvent(sockevent);
+ }
+
+ return result;
+}
+#endif /* LATCH_USE_WIN32 */
/*
* Sets a latch and wakes up anyone waiting on it.
void
SetLatch(volatile Latch *latch)
{
+#ifndef WIN32
pid_t owner_pid;
+#else
+ HANDLE handle;
+#endif
/*
* The memory barrier has be to be placed here to ensure that any flag
latch->is_set = true;
+#ifndef WIN32
+
/*
* See if anyone's waiting for the latch. It can be the current process if
* we're in a signal handler. We use the self-pipe to wake up the select()
}
else
kill(owner_pid, SIGUSR1);
+#else
+
+ /*
+ * 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 just in case somebody changes the event field
+ * concurrently (which really should not happen).
+ */
+ handle = latch->event;
+ if (handle)
+ {
+ SetEvent(handle);
+
+ /*
+ * Note that we silently ignore any errors. We might be in a signal
+ * handler or other critical path where it's not safe to call elog().
+ */
+ }
+#endif
+
}
/*
* NB: when calling this in a signal handler, be sure to save and restore
* errno around it.
*/
+#ifndef WIN32
void
latch_sigusr1_handler(void)
{
if (waiting)
sendSelfPipeByte();
}
+#endif /* !WIN32 */
/* Send one byte to the self-pipe, to wake up WaitLatch */
+#ifndef WIN32
static void
sendSelfPipeByte(void)
{
return;
}
}
+#endif /* !WIN32 */
/*
* Read all available data from the self-pipe
* return, it must reset that flag first (though ideally, this will never
* happen).
*/
+#ifndef WIN32
static void
drainSelfPipe(void)
{
/* else buffer wasn't big enough, so read again */
}
}
+#endif /* !WIN32 */
* WaitLatch includes a provision for timeouts (which should be avoided
* when possible, as they incur extra overhead) and a provision for
* postmaster child processes to wake up immediately on postmaster death.
- * See unix_latch.c for detailed specifications for the exported functions.
+ * See latch.c for detailed specifications for the exported functions.
*
* The correct pattern to wait for event(s) is:
*
'src/backend/port/win32_sema.c');
$postgres->ReplaceFile('src/backend/port/pg_shmem.c',
'src/backend/port/win32_shmem.c');
- $postgres->ReplaceFile('src/backend/port/pg_latch.c',
- 'src/backend/port/win32_latch.c');
$postgres->AddFiles('src/port', @pgportfiles);
$postgres->AddFiles('src/common', @pgcommonbkndfiles);
$postgres->AddDir('src/timezone');