* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/port/unix_latch.c,v 1.3 2010/09/13 18:01:20 heikki Exp $
+ * $PostgreSQL: pgsql/src/backend/port/unix_latch.c,v 1.4 2010/09/15 10:06:21 heikki Exp $
*
*-------------------------------------------------------------------------
*/
* is initially owned by no-one, use OwnLatch to associate it with the
* current process.
*
- * NB: When you introduce a new shared latch, you must increase the shared
- * latch count in NumSharedLatches in win32_latch.c!
+ * InitSharedLatch needs to be called in postmaster before forking child
+ * processes, usually right after allocating the shared memory block
+ * containing the latch with ShmemInitStruct. The Unix implementation
+ * doesn't actually require that, but the Windows one does.
*/
void
InitSharedLatch(volatile Latch *latch)
}
/*
- * LatchShmemSize
- * Compute space needed for latch's shared memory
- *
- * Not needed for Unix implementation.
- */
-Size
-LatchShmemSize(void)
-{
- return 0;
-}
-
-/*
- * LatchShmemInit
- * Allocate and initialize shared memory needed for latches
- *
- * Not needed for Unix implementation.
- */
-void
-LatchShmemInit(void)
-{
-}
-
-/*
* SetLatch uses SIGUSR1 to wake up the process waiting on the latch. Wake
* up WaitLatch.
*/
* win32_latch.c
* Windows implementation of latches.
*
- * The Windows implementation uses Windows events. See unix_latch.c for
- * information on usage.
+ * See unix_latch.c for information on usage.
+ *
+ * The Windows implementation uses Windows events that are inherited by
+ * all postmaster child processes.
*
* Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/port/win32_latch.c,v 1.1 2010/09/11 15:48:04 heikki Exp $
+ * $PostgreSQL: pgsql/src/backend/port/win32_latch.c,v 1.2 2010/09/15 10:06:21 heikki Exp $
*
*-------------------------------------------------------------------------
*/
#include "replication/walsender.h"
#include "storage/latch.h"
#include "storage/shmem.h"
-#include "storage/spin.h"
-
-/*
- * Shared latches are implemented with Windows events that are shared by
- * all postmaster child processes. At postmaster startup we create enough
- * Event objects, and mark them as inheritable so that they are accessible
- * in child processes. The handles are stored in sharedHandles.
- */
-typedef struct
-{
- slock_t mutex; /* protects all the other fields */
- int maxhandles; /* number of shared handles created */
- int nfreehandles; /* number of free handles in array */
- HANDLE handles[1]; /* free handles, variable length */
-} SharedEventHandles;
-
-static SharedEventHandles *sharedHandles;
void
InitLatch(volatile Latch *latch)
{
- latch->event = CreateEvent(NULL, TRUE, FALSE, NULL);
- latch->is_shared = false;
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 %d", (int) GetLastError());
}
void
InitSharedLatch(volatile Latch *latch)
{
- latch->is_shared = true;
+ SECURITY_ATTRIBUTES sa;
+
latch->is_set = false;
- latch->event = NULL;
+ 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 %d", (int) GetLastError());
}
void
OwnLatch(volatile Latch *latch)
{
- HANDLE event;
-
/* Sanity checks */
Assert(latch->is_shared);
- if (latch->event != 0)
+ if (latch->owner_pid != 0)
elog(ERROR, "latch already owned");
- /* Reserve an event handle from the shared handles array */
- SpinLockAcquire(&sharedHandles->mutex);
- if (sharedHandles->nfreehandles <= 0)
- {
- SpinLockRelease(&sharedHandles->mutex);
- elog(ERROR, "out of shared event objects");
- }
- sharedHandles->nfreehandles--;
- event = sharedHandles->handles[sharedHandles->nfreehandles];
- SpinLockRelease(&sharedHandles->mutex);
-
- latch->event = event;
+ latch->owner_pid = MyProcPid;
}
void
DisownLatch(volatile Latch *latch)
{
Assert(latch->is_shared);
- Assert(latch->event != NULL);
-
- /* Put the event handle back to the pool */
- SpinLockAcquire(&sharedHandles->mutex);
- if (sharedHandles->nfreehandles >= sharedHandles->maxhandles)
- {
- SpinLockRelease(&sharedHandles->mutex);
- elog(PANIC, "too many free event handles");
- }
- sharedHandles->handles[sharedHandles->nfreehandles] = latch->event;
- sharedHandles->nfreehandles++;
- SpinLockRelease(&sharedHandles->mutex);
+ Assert(latch->owner_pid == MyProcPid);
- latch->event = NULL;
+ latch->owner_pid = 0;
}
bool
{
latch->is_set = false;
}
-
-/*
- * Number of shared latches, used to allocate the right number of shared
- * Event handles at postmaster startup. You must update this if you
- * introduce a new shared latch!
- */
-static int
-NumSharedLatches(void)
-{
- int numLatches = 0;
-
- /* Each walsender needs one latch */
- numLatches += max_wal_senders;
-
- return numLatches;
-}
-
-/*
- * LatchShmemSize
- * Compute space needed for latch's shared memory
- */
-Size
-LatchShmemSize(void)
-{
- return offsetof(SharedEventHandles, handles) +
- NumSharedLatches() * sizeof(HANDLE);
-}
-
-/*
- * LatchShmemInit
- * Allocate and initialize shared memory needed for latches
- */
-void
-LatchShmemInit(void)
-{
- Size size = LatchShmemSize();
- bool found;
-
- sharedHandles = ShmemInitStruct("SharedEventHandles", size, &found);
-
- /* If we're first, initialize the struct and allocate handles */
- if (!found)
- {
- int i;
- 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;
-
- SpinLockInit(&sharedHandles->mutex);
- sharedHandles->maxhandles = NumSharedLatches();
- sharedHandles->nfreehandles = sharedHandles->maxhandles;
- for (i = 0; i < sharedHandles->maxhandles; i++)
- {
- sharedHandles->handles[i] = CreateEvent(&sa, TRUE, FALSE, NULL);
- if (sharedHandles->handles[i] == NULL)
- elog(ERROR, "CreateEvent failed: error code %d", (int) GetLastError());
- }
- }
-}