]> granicus.if.org Git - postgresql/commitdiff
Fix LWLockAssign() so that it can safely be executed after postmaster
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 7 Oct 2005 21:42:38 +0000 (21:42 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 7 Oct 2005 21:42:38 +0000 (21:42 +0000)
initialization.  Add spinlocking, fix EXEC_BACKEND unsafeness.

src/backend/storage/ipc/shmem.c
src/backend/storage/lmgr/lwlock.c

index 76b3ef26cc4d49eabe216f44bdeb8d4c325de411..d7498389b562a7c97dea5e97945d84ad1cd45713 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.85 2005/08/20 23:26:20 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/storage/ipc/shmem.c,v 1.86 2005/10/07 21:42:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -71,8 +71,7 @@ SHMEM_OFFSET ShmemBase;                       /* start address of shared memory */
 
 static SHMEM_OFFSET ShmemEnd;  /* end+1 address of shared memory */
 
-NON_EXEC_STATIC slock_t *ShmemLock;            /* spinlock for shared memory
-                                                                                * allocation */
+slock_t *ShmemLock;            /* spinlock for shared memory and LWLock allocation */
 
 NON_EXEC_STATIC slock_t *ShmemIndexLock;               /* spinlock for ShmemIndex */
 
index d649e0bd71216166d0fd9ef243e4fb15e77636bf..8b7565a6aa7299957a14ab5cdb685b270758768d 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.31 2005/10/07 20:11:03 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/storage/lmgr/lwlock.c,v 1.32 2005/10/07 21:42:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 #include "storage/spin.h"
 
 
+/* We use the ShmemLock spinlock to protect LWLockAssign */
+extern slock_t *ShmemLock;
+
+
 typedef struct LWLock
 {
        slock_t         mutex;                  /* Protects LWLock and queue of PGPROCs */
@@ -65,9 +69,6 @@ typedef union LWLockPadded
  */
 NON_EXEC_STATIC LWLockPadded *LWLockArray = NULL;
 
-/* shared counter for dynamic allocation of LWLockIds */
-static int *LWLockCounter;
-
 
 /*
  * We use this structure to keep track of locked LWLocks for release
@@ -159,7 +160,7 @@ LWLockShmemSize(void)
        /* Space for the LWLock array. */
        size = mul_size(numLocks, sizeof(LWLockPadded));
 
-       /* Space for shared allocation counter, plus room for alignment. */
+       /* Space for dynamic allocation counter, plus room for alignment. */
        size = add_size(size, 2 * sizeof(int) + LWLOCK_PADDED_SIZE);
 
        return size;
@@ -175,12 +176,16 @@ CreateLWLocks(void)
        int                     numLocks = NumLWLocks();
        Size            spaceLocks = LWLockShmemSize();
        LWLockPadded *lock;
+       int                *LWLockCounter;
        char       *ptr;
        int                     id;
 
        /* Allocate space */
        ptr = (char *) ShmemAlloc(spaceLocks);
 
+       /* Leave room for dynamic allocation counter */
+       ptr += 2 * sizeof(int);
+
        /* Ensure desired alignment of LWLock array */
        ptr += LWLOCK_PADDED_SIZE - ((unsigned long) ptr) % LWLOCK_PADDED_SIZE;
 
@@ -200,9 +205,10 @@ CreateLWLocks(void)
        }
 
        /*
-        * Initialize the dynamic-allocation counter at the end of the array
+        * Initialize the dynamic-allocation counter, which is stored just before
+        * the first LWLock.
         */
-       LWLockCounter = (int *) lock;
+       LWLockCounter = (int *) ((char *) LWLockArray - 2 * sizeof(int));
        LWLockCounter[0] = (int) NumFixedLWLocks;
        LWLockCounter[1] = numLocks;
 }
@@ -211,16 +217,27 @@ CreateLWLocks(void)
 /*
  * LWLockAssign - assign a dynamically-allocated LWLock number
  *
- * NB: we do not currently try to interlock this.  Could perhaps use
- * ShmemLock spinlock if there were any need to assign LWLockIds after
- * shmem setup.
+ * We interlock this using the same spinlock that is used to protect
+ * ShmemAlloc().  Interlocking is not really necessary during postmaster
+ * startup, but it is needed if any user-defined code tries to allocate
+ * LWLocks after startup.
  */
 LWLockId
 LWLockAssign(void)
 {
+       LWLockId        result;
+       int                *LWLockCounter;
+
+       LWLockCounter = (int *) ((char *) LWLockArray - 2 * sizeof(int));
+       SpinLockAcquire(ShmemLock);
        if (LWLockCounter[0] >= LWLockCounter[1])
-               elog(FATAL, "no more LWLockIds available");
-       return (LWLockId) (LWLockCounter[0]++);
+       {
+               SpinLockRelease(ShmemLock);
+               elog(ERROR, "no more LWLockIds available");
+       }
+       result = (LWLockId) (LWLockCounter[0]++);
+       SpinLockRelease(ShmemLock);
+       return result;
 }