Simplify Windows implementation of latches. There's no need to keep a
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Wed, 15 Sep 2010 10:06:21 +0000 (10:06 +0000)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Wed, 15 Sep 2010 10:06:21 +0000 (10:06 +0000)
dynamic pool of event handles, we can permanently assign one for each
shared latch. Thanks to that, we no longer need a separate shared memory
block for latches, and we don't need to know in advance how many shared
latches there is, so you no longer need to remember to update
NumSharedLatches when you introduce a new latch to the system.

src/backend/port/unix_latch.c
src/backend/port/win32_latch.c
src/backend/storage/ipc/ipci.c
src/include/storage/latch.h

index e1cb6f219e98b95c47f87a22b2dc8b7aa97b21be..d5d61432893dbb7cab446811f206992da4b0ff89 100644 (file)
@@ -77,7 +77,7 @@
  * 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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -129,8 +129,10 @@ InitLatch(volatile Latch *latch)
  * 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)
@@ -322,29 +324,6 @@ ResetLatch(volatile Latch *latch)
    latch->is_set = false;
 }
 
-/*
- * 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.
index f6d4920e46553af2f741180d39ad53510bc4998d..a36d1b6ee5b45bedef989d5f9f005ce793a8c939 100644 (file)
@@ -3,14 +3,16 @@
  * 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
@@ -217,68 +196,3 @@ ResetLatch(volatile Latch *latch)
 {
    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());
-       }
-   }
-}
index 881dae830c3a2093ad068e5391a92e246fbce822..666c015deda7901f4da0513c2ced916377d5d153 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.105 2010/09/11 15:48:04 heikki Exp $
+ *   $PostgreSQL: pgsql/src/backend/storage/ipc/ipci.c,v 1.106 2010/09/15 10:06:21 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -30,7 +30,6 @@
 #include "replication/walsender.h"
 #include "storage/bufmgr.h"
 #include "storage/ipc.h"
-#include "storage/latch.h"
 #include "storage/pg_shmem.h"
 #include "storage/pmsignal.h"
 #include "storage/procarray.h"
@@ -118,7 +117,6 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
        size = add_size(size, SInvalShmemSize());
        size = add_size(size, PMSignalShmemSize());
        size = add_size(size, ProcSignalShmemSize());
-       size = add_size(size, LatchShmemSize());
        size = add_size(size, BgWriterShmemSize());
        size = add_size(size, AutoVacuumShmemSize());
        size = add_size(size, WalSndShmemSize());
@@ -219,7 +217,6 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
     */
    PMSignalShmemInit();
    ProcSignalShmemInit();
-   LatchShmemInit();
    BgWriterShmemInit();
    AutoVacuumShmemInit();
    WalSndShmemInit();
index 2c697741e4de464ccc9d834c62c018bf1a89d056..0c0b01ca19c4bd6b0b54eecc40251f8eac5deeba 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/storage/latch.h,v 1.1 2010/09/11 15:48:04 heikki Exp $
+ * $PostgreSQL: pgsql/src/include/storage/latch.h,v 1.2 2010/09/15 10:06:21 heikki Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -25,9 +25,8 @@ typedef struct
 {
    sig_atomic_t    is_set;
    bool            is_shared;
-#ifndef WIN32
    int             owner_pid;
-#else
+#ifdef WIN32
    HANDLE          event;
 #endif
 } Latch;
@@ -46,9 +45,6 @@ extern void SetLatch(volatile Latch *latch);
 extern void ResetLatch(volatile Latch *latch);
 #define TestLatch(latch) (((volatile Latch *) latch)->is_set)
 
-extern Size LatchShmemSize(void);
-extern void LatchShmemInit(void);
-
 /*
  * Unix implementation uses SIGUSR1 for inter-process signaling, Win32 doesn't
  * need this.