v11-0001-Improve-LWLock-tranche-registration.patch
application/octet-stream
Filename: v11-0001-Improve-LWLock-tranche-registration.patch
Type: application/octet-stream
Part: 0
Patch
Format: format-patch
Series: patch v11-0001
Subject: Improve LWLock tranche registration
| File | + | − |
|---|---|---|
| contrib/pg_prewarm/autoprewarm.c | 1 | 2 |
| doc/src/sgml/xfunc.sgml | 5 | 13 |
| src/backend/postmaster/launch_backend.c | 2 | 2 |
| src/backend/storage/ipc/dsm_registry.c | 3 | 13 |
| src/backend/storage/lmgr/lwlock.c | 106 | 102 |
| src/backend/utils/activity/wait_event_names.txt | 1 | 0 |
| src/include/storage/lwlock.h | 5 | 13 |
| src/include/storage/lwlocklist.h | 1 | 0 |
| src/test/modules/test_dsa/test_dsa.c | 2 | 4 |
| src/test/modules/test_dsm_registry/test_dsm_registry.c | 1 | 2 |
| src/test/modules/test_radixtree/test_radixtree.c | 3 | 6 |
| src/test/modules/test_slru/test_slru.c | 2 | 4 |
| src/test/modules/test_tidstore/test_tidstore.c | 1 | 2 |
From 14426e26138a58c827d0bf95ab42d39e0ab0da1e Mon Sep 17 00:00:00 2001
From: Ubuntu <ubuntu@ip-172-31-31-110.ec2.internal>
Date: Thu, 21 Aug 2025 21:26:52 +0000
Subject: [PATCH v11 1/2] Improve LWLock tranche registration
Previously, tranche tracking was done in a backend local array. If a
backend did not explicitly register a tranche with
LWLockRegisterTranche, querying pg_stat_activity would show
"extension" instead of the tranche name.
This change moves the NamedLWLockTrancheArray into a fixed size
shared memory allocated from MainLWLockArray. Tranche creation is now
centralized, and a user only needs to call LWLockNewTrancheId with a
tranche name, and the tranche is stored in shared memory. Backends
look up tranche IDs locally, syncing their cache from shared memory
on a cache miss.
A new LWLock protects NamedLWLockTrancheArray during reads and
writes, ensuring consistency across backends.
Discussion: https://www.postgresql.org/message-id/CAA5RZ0vvED3naph8My8Szv6DL4AxOVK3eTPS0qXsaKi%3DbVdW2A%40mail.gmail.com
---
contrib/pg_prewarm/autoprewarm.c | 3 +-
doc/src/sgml/xfunc.sgml | 18 +-
src/backend/postmaster/launch_backend.c | 4 +-
src/backend/storage/ipc/dsm_registry.c | 16 +-
src/backend/storage/lmgr/lwlock.c | 208 +++++++++---------
.../utils/activity/wait_event_names.txt | 1 +
src/include/storage/lwlock.h | 18 +-
src/include/storage/lwlocklist.h | 1 +
src/test/modules/test_dsa/test_dsa.c | 6 +-
.../test_dsm_registry/test_dsm_registry.c | 3 +-
.../modules/test_radixtree/test_radixtree.c | 9 +-
src/test/modules/test_slru/test_slru.c | 6 +-
.../modules/test_tidstore/test_tidstore.c | 3 +-
13 files changed, 133 insertions(+), 163 deletions(-)
diff --git a/contrib/pg_prewarm/autoprewarm.c b/contrib/pg_prewarm/autoprewarm.c
index c01b9c7e6a4..880e897796a 100644
--- a/contrib/pg_prewarm/autoprewarm.c
+++ b/contrib/pg_prewarm/autoprewarm.c
@@ -864,7 +864,7 @@ apw_init_state(void *ptr)
{
AutoPrewarmSharedState *state = (AutoPrewarmSharedState *) ptr;
- LWLockInitialize(&state->lock, LWLockNewTrancheId());
+ LWLockInitialize(&state->lock, LWLockNewTrancheId("autoprewarm"));
state->bgworker_pid = InvalidPid;
state->pid_using_dumpfile = InvalidPid;
}
@@ -883,7 +883,6 @@ apw_init_shmem(void)
sizeof(AutoPrewarmSharedState),
apw_init_state,
&found);
- LWLockRegisterTranche(apw_state->lock.tranche, "autoprewarm");
return found;
}
diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml
index f116d0648e5..20b0767f204 100644
--- a/doc/src/sgml/xfunc.sgml
+++ b/doc/src/sgml/xfunc.sgml
@@ -3757,9 +3757,10 @@ LWLockPadded *GetNamedLWLockTranche(const char *tranche_name)
There is another, more flexible method of obtaining LWLocks that can be
done after server startup and outside a
<literal>shmem_request_hook</literal>. To do so, first allocate a
- <literal>tranche_id</literal> by calling:
+ <literal>tranche_id</literal> with an associated <literal>tranche_name</literal>
+ by calling:
<programlisting>
-int LWLockNewTrancheId(void)
+int LWLockNewTrancheId(const char *tranche_name)
</programlisting>
Next, initialize each LWLock, passing the new
<literal>tranche_id</literal> as an argument:
@@ -3777,17 +3778,8 @@ void LWLockInitialize(LWLock *lock, int tranche_id)
</para>
<para>
- Finally, each backend using the <literal>tranche_id</literal> should
- associate it with a <literal>tranche_name</literal> by calling:
-<programlisting>
-void LWLockRegisterTranche(int tranche_id, const char *tranche_name)
-</programlisting>
- </para>
-
- <para>
- A complete usage example of <function>LWLockNewTrancheId</function>,
- <function>LWLockInitialize</function>, and
- <function>LWLockRegisterTranche</function> can be found in
+ A complete usage example of <function>LWLockNewTrancheId</function> and
+ <function>LWLockInitialize</function> can be found in
<filename>contrib/pg_prewarm/autoprewarm.c</filename> in the
<productname>PostgreSQL</productname> source tree.
</para>
diff --git a/src/backend/postmaster/launch_backend.c b/src/backend/postmaster/launch_backend.c
index bf6b55ee830..51832ed19fe 100644
--- a/src/backend/postmaster/launch_backend.c
+++ b/src/backend/postmaster/launch_backend.c
@@ -101,8 +101,8 @@ typedef struct
struct InjectionPointsCtl *ActiveInjectionPoints;
#endif
int NamedLWLockTrancheRequests;
- NamedLWLockTranche *NamedLWLockTrancheArray;
LWLockPadded *MainLWLockArray;
+ const char *NamedLWLockTrancheArray;
slock_t *ProcStructLock;
PROC_HDR *ProcGlobal;
PGPROC *AuxiliaryProcs;
@@ -760,8 +760,8 @@ save_backend_variables(BackendParameters *param,
#endif
param->NamedLWLockTrancheRequests = NamedLWLockTrancheRequests;
- param->NamedLWLockTrancheArray = NamedLWLockTrancheArray;
param->MainLWLockArray = MainLWLockArray;
+ param->NamedLWLockTrancheArray = NamedLWLockTrancheArray;
param->ProcStructLock = ProcStructLock;
param->ProcGlobal = ProcGlobal;
param->AuxiliaryProcs = AuxiliaryProcs;
diff --git a/src/backend/storage/ipc/dsm_registry.c b/src/backend/storage/ipc/dsm_registry.c
index 1682cc6d34c..8f9595e8730 100644
--- a/src/backend/storage/ipc/dsm_registry.c
+++ b/src/backend/storage/ipc/dsm_registry.c
@@ -307,9 +307,8 @@ GetNamedDSA(const char *name, bool *found)
entry->type = DSMR_ENTRY_TYPE_DSA;
/* Initialize the LWLock tranche for the DSA. */
- state->tranche = LWLockNewTrancheId();
+ state->tranche = LWLockNewTrancheId(state->tranche_name);
strcpy(state->tranche_name, name);
- LWLockRegisterTranche(state->tranche, state->tranche_name);
/* Initialize the DSA. */
ret = dsa_create(state->tranche);
@@ -330,9 +329,6 @@ GetNamedDSA(const char *name, bool *found)
ereport(ERROR,
(errmsg("requested DSA already attached to current process")));
- /* Initialize existing LWLock tranche for the DSA. */
- LWLockRegisterTranche(state->tranche, state->tranche_name);
-
/* Attach to existing DSA. */
ret = dsa_attach(state->handle);
dsa_pin_mapping(ret);
@@ -389,14 +385,12 @@ GetNamedDSHash(const char *name, const dshash_parameters *params, bool *found)
entry->type = DSMR_ENTRY_TYPE_DSH;
/* Initialize the LWLock tranche for the DSA. */
- dsa_state->tranche = LWLockNewTrancheId();
+ dsa_state->tranche = LWLockNewTrancheId(dsa_state->tranche_name);
sprintf(dsa_state->tranche_name, "%s%s", name, DSMR_DSA_TRANCHE_SUFFIX);
- LWLockRegisterTranche(dsa_state->tranche, dsa_state->tranche_name);
/* Initialize the LWLock tranche for the dshash table. */
- dsh_state->tranche = LWLockNewTrancheId();
+ dsh_state->tranche = LWLockNewTrancheId(dsh_state->tranche_name);
strcpy(dsh_state->tranche_name, name);
- LWLockRegisterTranche(dsh_state->tranche, dsh_state->tranche_name);
/* Initialize the DSA for the hash table. */
dsa = dsa_create(dsa_state->tranche);
@@ -427,10 +421,6 @@ GetNamedDSHash(const char *name, const dshash_parameters *params, bool *found)
ereport(ERROR,
(errmsg("requested DSHash already attached to current process")));
- /* Initialize existing LWLock tranches for the DSA and dshash table. */
- LWLockRegisterTranche(dsa_state->tranche, dsa_state->tranche_name);
- LWLockRegisterTranche(dsh_state->tranche, dsh_state->tranche_name);
-
/* Attach to existing DSA for the hash table. */
dsa = dsa_attach(dsa_state->handle);
dsa_pin_mapping(dsa);
diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c
index c80b43f1f55..717583d7237 100644
--- a/src/backend/storage/lmgr/lwlock.c
+++ b/src/backend/storage/lmgr/lwlock.c
@@ -105,6 +105,9 @@
#define LW_SHARED_MASK MAX_BACKENDS
#define LW_LOCK_MASK (MAX_BACKENDS | LW_VAL_EXCLUSIVE)
+#define MAX_NAMED_TRANCHES 1024
+#define MAX_NAMED_TRANCHES_NAME_LEN NAMEDATALEN
+
StaticAssertDecl(((MAX_BACKENDS + 1) & MAX_BACKENDS) == 0,
"MAX_BACKENDS + 1 needs to be a power of 2");
@@ -125,9 +128,10 @@ StaticAssertDecl((LW_VAL_EXCLUSIVE & LW_FLAG_MASK) == 0,
* 2. There are some predefined tranches for built-in groups of locks defined
* in lwlocklist.h. We absorb the names of these tranches, too.
*
- * 3. Extensions can create new tranches, via either RequestNamedLWLockTranche
- * or LWLockRegisterTranche. The names of these that are known in the current
- * process appear in LWLockTrancheNames[].
+ * 3. Extensions can create new tranches using either RequestNamedLWLockTranche
+ * or LWLockNewTrancheId. The names of these tranches are first stored in the
+ * shared NamedLWLockTrancheArray, and then cached locally in LWLockTrancheNames[]
+ * to avoid accessing shared memory on every lookup.
*
* All these names are user-visible as wait event names, so choose with care
* ... and do not forget to update the documentation's list of wait events.
@@ -146,11 +150,18 @@ StaticAssertDecl(lengthof(BuiltinTrancheNames) ==
/*
* This is indexed by tranche ID minus LWTRANCHE_FIRST_USER_DEFINED, and
- * stores the names of all dynamically-created tranches known to the current
- * process. Any unused entries in the array will contain NULL.
+ * stores the names of all dynamically created tranches in shared memory.
+ * Any unused entries in the array will contain NULL. This variable is
+ * non-static so that postmaster.c can copy it to child processes in
+ * EXEC_BACKEND builds.
+ */
+const char *NamedLWLockTrancheArray = NULL;
+
+/*
+ * This is a local copy of NamedLWLockTrancheArray to avoid repeated access
+ * to shared memory when lookig up a tranche with GetLWTrancheName.
*/
static const char **LWLockTrancheNames = NULL;
-static int LWLockTrancheNamesAllocated = 0;
/*
* This points to the main array of LWLocks in shared memory. Backends inherit
@@ -179,12 +190,11 @@ static LWLockHandle held_lwlocks[MAX_SIMUL_LWLOCKS];
/* struct representing the LWLock tranche request for named tranche */
typedef struct NamedLWLockTrancheRequest
{
- char tranche_name[NAMEDATALEN];
+ char tranche_name[MAX_NAMED_TRANCHES_NAME_LEN];
int num_lwlocks;
} NamedLWLockTrancheRequest;
static NamedLWLockTrancheRequest *NamedLWLockTrancheRequestArray = NULL;
-static int NamedLWLockTrancheRequestsAllocated = 0;
/*
* NamedLWLockTrancheRequests is both the valid length of the request array,
@@ -194,8 +204,6 @@ static int NamedLWLockTrancheRequestsAllocated = 0;
*/
int NamedLWLockTrancheRequests = 0;
-/* points to data in shared memory: */
-NamedLWLockTranche *NamedLWLockTrancheArray = NULL;
static void InitializeLWLocks(void);
static inline void LWLockReportWaitStart(LWLock *lock);
@@ -391,7 +399,6 @@ Size
LWLockShmemSize(void)
{
Size size;
- int i;
int numLocks = NUM_FIXED_LWLOCKS;
/* Calculate total number of locks needed in the main array. */
@@ -403,19 +410,18 @@ LWLockShmemSize(void)
/* Space for dynamic allocation counter, plus room for alignment. */
size = add_size(size, sizeof(int) + LWLOCK_PADDED_SIZE);
- /* space for named tranches. */
+ /* Space for named tranches. */
size = add_size(size, mul_size(NamedLWLockTrancheRequests, sizeof(NamedLWLockTranche)));
- /* space for name of each tranche. */
- for (i = 0; i < NamedLWLockTrancheRequests; i++)
- size = add_size(size, strlen(NamedLWLockTrancheRequestArray[i].tranche_name) + 1);
+ /* Space for name of each tranche. */
+ size = add_size(size, mul_size(MAX_NAMED_TRANCHES, MAX_NAMED_TRANCHES));
return size;
}
/*
* Allocate shmem space for the main LWLock array and all tranches and
- * initialize it. We also register extension LWLock tranches here.
+ * initialize it.
*/
void
CreateLWLocks(void)
@@ -447,11 +453,6 @@ CreateLWLocks(void)
/* Initialize all LWLocks */
InitializeLWLocks();
}
-
- /* Register named extension LWLock tranches in the current process. */
- for (int i = 0; i < NamedLWLockTrancheRequests; i++)
- LWLockRegisterTranche(NamedLWLockTrancheArray[i].trancheId,
- NamedLWLockTrancheArray[i].trancheName);
}
/*
@@ -485,38 +486,27 @@ InitializeLWLocks(void)
for (id = 0; id < NUM_PREDICATELOCK_PARTITIONS; id++, lock++)
LWLockInitialize(&lock->lock, LWTRANCHE_PREDICATE_LOCK_MANAGER);
- /*
- * Copy the info about any named tranches into shared memory (so that
- * other processes can see it), and initialize the requested LWLocks.
- */
+ NamedLWLockTrancheArray = (const char *)
+ &MainLWLockArray[NUM_FIXED_LWLOCKS + numNamedLocks];
+
+ /* Register LWLocks requested with RequestNamedLWLockTranch */
if (NamedLWLockTrancheRequests > 0)
{
- char *trancheNames;
-
- NamedLWLockTrancheArray = (NamedLWLockTranche *)
- &MainLWLockArray[NUM_FIXED_LWLOCKS + numNamedLocks];
-
- trancheNames = (char *) NamedLWLockTrancheArray +
- (NamedLWLockTrancheRequests * sizeof(NamedLWLockTranche));
lock = &MainLWLockArray[NUM_FIXED_LWLOCKS];
for (i = 0; i < NamedLWLockTrancheRequests; i++)
{
NamedLWLockTrancheRequest *request;
- NamedLWLockTranche *tranche;
- char *name;
+ int tranche_id;
request = &NamedLWLockTrancheRequestArray[i];
- tranche = &NamedLWLockTrancheArray[i];
- name = trancheNames;
- trancheNames += strlen(request->tranche_name) + 1;
- strcpy(name, request->tranche_name);
- tranche->trancheId = LWLockNewTrancheId();
- tranche->trancheName = name;
+ /* Allocate a new tranche ID */
+ tranche_id = LWLockNewTrancheId(request->tranche_name);
+ /* Initialize the requested amount of LWLocks */
for (j = 0; j < request->num_lwlocks; j++, lock++)
- LWLockInitialize(&lock->lock, tranche->trancheId);
+ LWLockInitialize(&lock->lock, tranche_id);
}
}
}
@@ -571,58 +561,44 @@ GetNamedLWLockTranche(const char *tranche_name)
* Allocate a new tranche ID.
*/
int
-LWLockNewTrancheId(void)
+LWLockNewTrancheId(const char *tranche_name)
{
- int result;
+ int tranche_id;
+ int index;
+ Size tranche_name_length = strlen(tranche_name) + 1;
int *LWLockCounter;
+ const char *slot;
+
+ /* The supplied tranche name is too long */
+ if (tranche_name_length > MAX_NAMED_TRANCHES_NAME_LEN)
+ elog(ERROR, "tranche name too long");
LWLockCounter = (int *) ((char *) MainLWLockArray - sizeof(int));
- /* We use the ShmemLock spinlock to protect LWLockCounter */
- SpinLockAcquire(ShmemLock);
- result = (*LWLockCounter)++;
- SpinLockRelease(ShmemLock);
- return result;
-}
+ LWLockAcquire(NamedLWLockTrancheArrayLock, LW_EXCLUSIVE);
-/*
- * Register a dynamic tranche name in the lookup table of the current process.
- *
- * This routine will save a pointer to the tranche name passed as an argument,
- * so the name should be allocated in a backend-lifetime context
- * (shared memory, TopMemoryContext, static constant, or similar).
- *
- * The tranche name will be user-visible as a wait event name, so try to
- * use a name that fits the style for those.
- */
-void
-LWLockRegisterTranche(int tranche_id, const char *tranche_name)
-{
- /* This should only be called for user-defined tranches. */
- if (tranche_id < LWTRANCHE_FIRST_USER_DEFINED)
- return;
+ /* Get the next tranche ID while holding an Exclusive lock */
+ tranche_id = (*LWLockCounter)++;
- /* Convert to array index. */
- tranche_id -= LWTRANCHE_FIRST_USER_DEFINED;
+ /* Get the NamedLWLockTrancheArray index for the tranche ID */
+ index = tranche_id - LWTRANCHE_FIRST_USER_DEFINED;
- /* If necessary, create or enlarge array. */
- if (tranche_id >= LWLockTrancheNamesAllocated)
+ /* Extensions registered too many tranches */
+ if (index > MAX_NAMED_TRANCHES)
{
- int newalloc;
-
- newalloc = pg_nextpower2_32(Max(8, tranche_id + 1));
+ LWLockRelease(NamedLWLockTrancheArrayLock);
- if (LWLockTrancheNames == NULL)
- LWLockTrancheNames = (const char **)
- MemoryContextAllocZero(TopMemoryContext,
- newalloc * sizeof(char *));
- else
- LWLockTrancheNames =
- repalloc0_array(LWLockTrancheNames, const char *, LWLockTrancheNamesAllocated, newalloc);
- LWLockTrancheNamesAllocated = newalloc;
+ elog(ERROR, "too many LWLock tranches registered");
}
- LWLockTrancheNames[tranche_id] = tranche_name;
+ /* Get the index location from the NamedLWLockTrancheArray array */
+ slot = NamedLWLockTrancheArray + (index * MAX_NAMED_TRANCHES_NAME_LEN);
+
+ strcpy((char *) slot, tranche_name);
+
+ LWLockRelease(NamedLWLockTrancheArrayLock);
+
+ return tranche_id;
}
/*
@@ -641,42 +617,41 @@ void
RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)
{
NamedLWLockTrancheRequest *request;
+ Size tranche_name_length = strlen(tranche_name) + 1;
if (!process_shmem_requests_in_progress)
elog(FATAL, "cannot request additional LWLocks outside shmem_request_hook");
+ if (tranche_name_length > MAX_NAMED_TRANCHES_NAME_LEN)
+ elog(FATAL, "tranche name too long");
+
if (NamedLWLockTrancheRequestArray == NULL)
{
- NamedLWLockTrancheRequestsAllocated = 16;
NamedLWLockTrancheRequestArray = (NamedLWLockTrancheRequest *)
MemoryContextAlloc(TopMemoryContext,
- NamedLWLockTrancheRequestsAllocated
+ MAX_NAMED_TRANCHES
* sizeof(NamedLWLockTrancheRequest));
}
- if (NamedLWLockTrancheRequests >= NamedLWLockTrancheRequestsAllocated)
- {
- int i = pg_nextpower2_32(NamedLWLockTrancheRequests + 1);
-
- NamedLWLockTrancheRequestArray = (NamedLWLockTrancheRequest *)
- repalloc(NamedLWLockTrancheRequestArray,
- i * sizeof(NamedLWLockTrancheRequest));
- NamedLWLockTrancheRequestsAllocated = i;
- }
+ if (NamedLWLockTrancheRequests >= MAX_NAMED_TRANCHES)
+ elog(FATAL, "too many dynamic LWLock tranches registered");
request = &NamedLWLockTrancheRequestArray[NamedLWLockTrancheRequests];
- Assert(strlen(tranche_name) + 1 <= NAMEDATALEN);
- strlcpy(request->tranche_name, tranche_name, NAMEDATALEN);
+ strlcpy(request->tranche_name, tranche_name, tranche_name_length);
request->num_lwlocks = num_lwlocks;
NamedLWLockTrancheRequests++;
}
/*
* LWLockInitialize - initialize a new lwlock; it's initially unlocked
+ * If the tranche was never registered, GetLWTrancheName will return
+ * and error.
*/
void
LWLockInitialize(LWLock *lock, int tranche_id)
{
+ GetLWTrancheName(tranche_id);
+
pg_atomic_init_u32(&lock->state, LW_FLAG_RELEASE_OK);
#ifdef LOCK_DEBUG
pg_atomic_init_u32(&lock->nwaiters, 0);
@@ -713,22 +688,51 @@ LWLockReportWaitEnd(void)
static const char *
GetLWTrancheName(uint16 trancheId)
{
+ int index = 0;
+
/* Built-in tranche or individual LWLock? */
if (trancheId < LWTRANCHE_FIRST_USER_DEFINED)
return BuiltinTrancheNames[trancheId];
/*
- * It's an extension tranche, so look in LWLockTrancheNames[]. However,
- * it's possible that the tranche has never been registered in the current
- * process, in which case give up and return "extension".
+ * This is an extension tranche. Look it up in LWLockTrancheNames[], and
+ * synchronize from NamedLWLockTrancheArray[] if necessary. If the tranche
+ * has never been registered by the extension, raise an error.
+ */
+ index = trancheId - LWTRANCHE_FIRST_USER_DEFINED;
+
+ /*
+ * Can't find the tranche in the local array, so we need to sync it from
+ * the shared array.
*/
- trancheId -= LWTRANCHE_FIRST_USER_DEFINED;
+ if (LWLockTrancheNames == NULL || LWLockTrancheNames[index] == NULL)
+ {
+ int *LWLockCounter;
+
+ LWLockCounter = (int *) ((char *) MainLWLockArray - sizeof(int));
+
+ /* first time, let's initialize the local array */
+ if (LWLockTrancheNames == NULL)
+ LWLockTrancheNames = (const char **)
+ MemoryContextAllocZero(TopMemoryContext,
+ MAX_NAMED_TRANCHES * sizeof(char *));
+
+ /*
+ * Sync the backend local array from the shared array. A shared lock
+ * is held on the shared array while syncing.
+ */
+ LWLockAcquire(NamedLWLockTrancheArrayLock, LW_SHARED);
+ for (int i = 0; i < *LWLockCounter - LWTRANCHE_FIRST_USER_DEFINED; i++)
+ LWLockTrancheNames[i] = NamedLWLockTrancheArray + (i * MAX_NAMED_TRANCHES_NAME_LEN);
+ LWLockRelease(NamedLWLockTrancheArrayLock);
+ }
- if (trancheId >= LWLockTrancheNamesAllocated ||
- LWLockTrancheNames[trancheId] == NULL)
- return "extension";
+ /* Still can't find the tranche, raise an error */
+ if (!LWLockTrancheNames[index])
+ elog(ERROR, "LWLock tranche is not registered");
- return LWLockTrancheNames[trancheId];
+ /* We have a tranche name, return it */
+ return LWLockTrancheNames[index];
}
/*
diff --git a/src/backend/utils/activity/wait_event_names.txt b/src/backend/utils/activity/wait_event_names.txt
index 5427da5bc1b..2eed0a0682d 100644
--- a/src/backend/utils/activity/wait_event_names.txt
+++ b/src/backend/utils/activity/wait_event_names.txt
@@ -352,6 +352,7 @@ DSMRegistry "Waiting to read or update the dynamic shared memory registry."
InjectionPoint "Waiting to read or update information related to injection points."
SerialControl "Waiting to read or update shared <filename>pg_serial</filename> state."
AioWorkerSubmissionQueue "Waiting to access AIO worker submission queue."
+NamedLWLockTrancheArray "Waiting to access the named LWLock tranches array."
#
# END OF PREDEFINED LWLOCKS (DO NOT CHANGE THIS LINE)
diff --git a/src/include/storage/lwlock.h b/src/include/storage/lwlock.h
index 5e717765764..1ba77cb3658 100644
--- a/src/include/storage/lwlock.h
+++ b/src/include/storage/lwlock.h
@@ -80,7 +80,7 @@ typedef struct NamedLWLockTranche
char *trancheName;
} NamedLWLockTranche;
-extern PGDLLIMPORT NamedLWLockTranche *NamedLWLockTrancheArray;
+extern PGDLLIMPORT const char *NamedLWLockTrancheArray;
extern PGDLLIMPORT int NamedLWLockTrancheRequests;
/*
@@ -157,19 +157,11 @@ extern LWLockPadded *GetNamedLWLockTranche(const char *tranche_name);
/*
* There is another, more flexible method of obtaining lwlocks. First, call
- * LWLockNewTrancheId just once to obtain a tranche ID; this allocates from
- * a shared counter. Next, each individual process using the tranche should
- * call LWLockRegisterTranche() to associate that tranche ID with a name.
- * Finally, LWLockInitialize should be called just once per lwlock, passing
- * the tranche ID as an argument.
- *
- * It may seem strange that each process using the tranche must register it
- * separately, but dynamic shared memory segments aren't guaranteed to be
- * mapped at the same address in all coordinating backends, so storing the
- * registration in the main shared memory segment wouldn't work for that case.
+ * LWLockNewTrancheId with an associated tranche name just once to obtain a
+ * tranche ID; this allocates from a shared counter. Finally, LWLockInitialize
+ * should be called just once per lwlock, passing the tranche ID as an argument.
*/
-extern int LWLockNewTrancheId(void);
-extern void LWLockRegisterTranche(int tranche_id, const char *tranche_name);
+extern int LWLockNewTrancheId(const char *tranche_name);
extern void LWLockInitialize(LWLock *lock, int tranche_id);
/*
diff --git a/src/include/storage/lwlocklist.h b/src/include/storage/lwlocklist.h
index 06a1ffd4b08..0b00c5a4b3f 100644
--- a/src/include/storage/lwlocklist.h
+++ b/src/include/storage/lwlocklist.h
@@ -85,6 +85,7 @@ PG_LWLOCK(50, DSMRegistry)
PG_LWLOCK(51, InjectionPoint)
PG_LWLOCK(52, SerialControl)
PG_LWLOCK(53, AioWorkerSubmissionQueue)
+PG_LWLOCK(54, NamedLWLockTrancheArray)
/*
* There also exist several built-in LWLock tranches. As with the predefined
diff --git a/src/test/modules/test_dsa/test_dsa.c b/src/test/modules/test_dsa/test_dsa.c
index cd24d0f4873..01d5c6fa67f 100644
--- a/src/test/modules/test_dsa/test_dsa.c
+++ b/src/test/modules/test_dsa/test_dsa.c
@@ -29,8 +29,7 @@ test_dsa_basic(PG_FUNCTION_ARGS)
dsa_pointer p[100];
/* XXX: this tranche is leaked */
- tranche_id = LWLockNewTrancheId();
- LWLockRegisterTranche(tranche_id, "test_dsa");
+ tranche_id = LWLockNewTrancheId("test_dsa");
a = dsa_create(tranche_id);
for (int i = 0; i < 100; i++)
@@ -70,8 +69,7 @@ test_dsa_resowners(PG_FUNCTION_ARGS)
ResourceOwner childowner;
/* XXX: this tranche is leaked */
- tranche_id = LWLockNewTrancheId();
- LWLockRegisterTranche(tranche_id, "test_dsa");
+ tranche_id = LWLockNewTrancheId("test_dsa");
/* Create DSA in parent resource owner */
a = dsa_create(tranche_id);
diff --git a/src/test/modules/test_dsm_registry/test_dsm_registry.c b/src/test/modules/test_dsm_registry/test_dsm_registry.c
index 141c8ed1b34..4cc2ccdac3f 100644
--- a/src/test/modules/test_dsm_registry/test_dsm_registry.c
+++ b/src/test/modules/test_dsm_registry/test_dsm_registry.c
@@ -48,7 +48,7 @@ init_tdr_dsm(void *ptr)
{
TestDSMRegistryStruct *dsm = (TestDSMRegistryStruct *) ptr;
- LWLockInitialize(&dsm->lck, LWLockNewTrancheId());
+ LWLockInitialize(&dsm->lck, LWLockNewTrancheId("test_dsm_registry"));
dsm->val = 0;
}
@@ -61,7 +61,6 @@ tdr_attach_shmem(void)
sizeof(TestDSMRegistryStruct),
init_tdr_dsm,
&found);
- LWLockRegisterTranche(tdr_dsm->lck.tranche, "test_dsm_registry");
if (tdr_dsa == NULL)
tdr_dsa = GetNamedDSA("test_dsm_registry_dsa", &found);
diff --git a/src/test/modules/test_radixtree/test_radixtree.c b/src/test/modules/test_radixtree/test_radixtree.c
index 80ad0296164..787162c8793 100644
--- a/src/test/modules/test_radixtree/test_radixtree.c
+++ b/src/test/modules/test_radixtree/test_radixtree.c
@@ -124,10 +124,9 @@ test_empty(void)
rt_iter *iter;
uint64 key;
#ifdef TEST_SHARED_RT
- int tranche_id = LWLockNewTrancheId();
+ int tranche_id = LWLockNewTrancheId("test_radix_tree");
dsa_area *dsa;
- LWLockRegisterTranche(tranche_id, "test_radix_tree");
dsa = dsa_create(tranche_id);
radixtree = rt_create(dsa, tranche_id);
#else
@@ -167,10 +166,9 @@ test_basic(rt_node_class_test_elem *test_info, int shift, bool asc)
uint64 *keys;
int children = test_info->nkeys;
#ifdef TEST_SHARED_RT
- int tranche_id = LWLockNewTrancheId();
+ int tranche_id = LWLockNewTrancheId("test_radix_tree");
dsa_area *dsa;
- LWLockRegisterTranche(tranche_id, "test_radix_tree");
dsa = dsa_create(tranche_id);
radixtree = rt_create(dsa, tranche_id);
#else
@@ -304,10 +302,9 @@ test_random(void)
int num_keys = 100000;
uint64 *keys;
#ifdef TEST_SHARED_RT
- int tranche_id = LWLockNewTrancheId();
+ int tranche_id = LWLockNewTrancheId("test_radix_tree");
dsa_area *dsa;
- LWLockRegisterTranche(tranche_id, "test_radix_tree");
dsa = dsa_create(tranche_id);
radixtree = rt_create(dsa, tranche_id);
#else
diff --git a/src/test/modules/test_slru/test_slru.c b/src/test/modules/test_slru/test_slru.c
index 32750930e43..8c0367eeee4 100644
--- a/src/test/modules/test_slru/test_slru.c
+++ b/src/test/modules/test_slru/test_slru.c
@@ -232,11 +232,9 @@ test_slru_shmem_startup(void)
(void) MakePGDirectory(slru_dir_name);
/* initialize the SLRU facility */
- test_tranche_id = LWLockNewTrancheId();
- LWLockRegisterTranche(test_tranche_id, "test_slru_tranche");
+ test_tranche_id = LWLockNewTrancheId("test_slru_tranche");
- test_buffer_tranche_id = LWLockNewTrancheId();
- LWLockRegisterTranche(test_tranche_id, "test_buffer_tranche");
+ test_buffer_tranche_id = LWLockNewTrancheId("test_buffer_tranche");
TestSlruCtl->PagePrecedes = test_slru_page_precedes_logically;
SimpleLruInit(TestSlruCtl, "TestSLRU",
diff --git a/src/test/modules/test_tidstore/test_tidstore.c b/src/test/modules/test_tidstore/test_tidstore.c
index eb16e0fbfa6..0c8f43867e5 100644
--- a/src/test/modules/test_tidstore/test_tidstore.c
+++ b/src/test/modules/test_tidstore/test_tidstore.c
@@ -103,8 +103,7 @@ test_create(PG_FUNCTION_ARGS)
{
int tranche_id;
- tranche_id = LWLockNewTrancheId();
- LWLockRegisterTranche(tranche_id, "test_tidstore");
+ tranche_id = LWLockNewTrancheId("test_tidstore");
tidstore = TidStoreCreateShared(tidstore_max_size, tranche_id);
--
2.39.5 (Apple Git-154)