From 82e861fbe1a1a94f2af34d222db0d7bbf9cbaa3a Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 7 Oct 2005 21:42:38 +0000 Subject: [PATCH] Fix LWLockAssign() so that it can safely be executed after postmaster initialization. Add spinlocking, fix EXEC_BACKEND unsafeness. --- src/backend/storage/ipc/shmem.c | 5 ++-- src/backend/storage/lmgr/lwlock.c | 41 ++++++++++++++++++++++--------- 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/src/backend/storage/ipc/shmem.c b/src/backend/storage/ipc/shmem.c index 76b3ef26cc..d7498389b5 100644 --- a/src/backend/storage/ipc/shmem.c +++ b/src/backend/storage/ipc/shmem.c @@ -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 */ diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index d649e0bd71..8b7565a6aa 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -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 $ * *------------------------------------------------------------------------- */ @@ -27,6 +27,10 @@ #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; } -- 2.40.0