Move dynamically-allocated LWLock tranche names to shared memory.
authorNathan Bossart <nathan@postgresql.org>
Wed, 3 Sep 2025 18:57:48 +0000 (13:57 -0500)
committerNathan Bossart <nathan@postgresql.org>
Wed, 3 Sep 2025 18:57:48 +0000 (13:57 -0500)
There are two ways for shared libraries to allocate their own
LWLock tranches.  One way is to call RequestNamedLWLockTranche() in
a shmem_request_hook, which requires the library to be loaded via
shared_preload_libraries.  The other way is to call
LWLockNewTrancheId(), which is not subject to the same
restrictions.  However, LWLockNewTrancheId() does require each
backend to store the tranche's name in backend-local memory via
LWLockRegisterTranche().  This API is a little cumbersome and leads
to things like unhelpful pg_stat_activity.wait_event values in
backends that haven't loaded the library.

This commit moves these LWLock tranche names to shared memory, thus
eliminating the need for each backend to call
LWLockRegisterTranche().  Instead, the tranche name must be
provided to LWLockNewTrancheId(), which immediately makes the name
available to all backends.  Since the tranche name array is
append-only, lookups can ordinarily avoid locking as long as their
local copy of the LWLock counter is greater than the requested
tranche ID.

One downside of this approach is that we now have a hard limit on
both the length of tranche names (NAMEDATALEN-1 bytes) and the
number of dynamically-allocated tranches (256).  Besides a limit of
NAMEDATALEN-1 bytes for tranche names registered via
RequestNamedLWLockTranche(), no such limits previously existed.  We
could avoid these new limits by using dynamic shared memory, but
the complexity involved didn't seem worth it.  We briefly
considered making the tranche limit user-configurable but
ultimately decided against that, too.  Since there is still a lot
of time left in the v19 development cycle, it's possible we will
revisit this choice.

Author: Sami Imseih <samimseih@gmail.com>
Reviewed-by: Bertrand Drouvot <bertranddrouvot.pg@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Reviewed-by: Rahila Syed <rahilasyed90@gmail.com>
Reviewed-by: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/CAA5RZ0vvED3naph8My8Szv6DL4AxOVK3eTPS0qXsaKi%3DbVdW2A%40mail.gmail.com

contrib/pg_prewarm/autoprewarm.c
doc/src/sgml/xfunc.sgml
src/backend/postmaster/launch_backend.c
src/backend/storage/ipc/dsm_registry.c
src/backend/storage/lmgr/lwlock.c
src/include/storage/lwlock.h
src/test/modules/test_dsa/test_dsa.c
src/test/modules/test_dsm_registry/test_dsm_registry.c
src/test/modules/test_radixtree/test_radixtree.c
src/test/modules/test_slru/test_slru.c
src/test/modules/test_tidstore/test_tidstore.c

index c01b9c7e6a4d669b682ac04286c9168387152431..880e897796a1ebd48815a30a7aa80a262962cf60 100644 (file)
@@ -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;
 }
index f116d0648e5590feaeb3a0d91ae7b7a8d919ffbe..da21ef56891841e9138087712e1de0bd85b17255 100644 (file)
@@ -3759,7 +3759,7 @@ LWLockPadded *GetNamedLWLockTranche(const char *tranche_name)
       <literal>shmem_request_hook</literal>.  To do so, first allocate a
       <literal>tranche_id</literal> by calling:
 <programlisting>
-int LWLockNewTrancheId(void)
+int LWLockNewTrancheId(const char *name)
 </programlisting>
       Next, initialize each LWLock, passing the new
       <literal>tranche_id</literal> as an argument:
@@ -3777,17 +3777,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>
index cd9547b03a32b73fde8633eafae74ba03fa7fe0b..a38979c50e4bbf3da3929117e1f8483eca40fb83 100644 (file)
@@ -101,7 +101,7 @@ typedef struct
    struct InjectionPointsCtl *ActiveInjectionPoints;
 #endif
    int         NamedLWLockTrancheRequests;
-   NamedLWLockTranche *NamedLWLockTrancheArray;
+   char      **LWLockTrancheNames;
    int        *LWLockCounter;
    LWLockPadded *MainLWLockArray;
    slock_t    *ProcStructLock;
@@ -761,7 +761,7 @@ save_backend_variables(BackendParameters *param,
 #endif
 
    param->NamedLWLockTrancheRequests = NamedLWLockTrancheRequests;
-   param->NamedLWLockTrancheArray = NamedLWLockTrancheArray;
+   param->LWLockTrancheNames = LWLockTrancheNames;
    param->LWLockCounter = LWLockCounter;
    param->MainLWLockArray = MainLWLockArray;
    param->ProcStructLock = ProcStructLock;
@@ -1022,7 +1022,7 @@ restore_backend_variables(BackendParameters *param)
 #endif
 
    NamedLWLockTrancheRequests = param->NamedLWLockTrancheRequests;
-   NamedLWLockTrancheArray = param->NamedLWLockTrancheArray;
+   LWLockTrancheNames = param->LWLockTrancheNames;
    LWLockCounter = param->LWLockCounter;
    MainLWLockArray = param->MainLWLockArray;
    ProcStructLock = param->ProcStructLock;
index ca12815f4a854c72ccda4e68d61b14a9e4baf819..971309251062d6a86888f9b6f7a09e1363df3c02 100644 (file)
@@ -299,8 +299,7 @@ GetNamedDSA(const char *name, bool *found)
        entry->type = DSMR_ENTRY_TYPE_DSA;
 
        /* Initialize the LWLock tranche for the DSA. */
-       state->tranche = LWLockNewTrancheId();
-       LWLockRegisterTranche(state->tranche, name);
+       state->tranche = LWLockNewTrancheId(name);
 
        /* Initialize the DSA. */
        ret = dsa_create(state->tranche);
@@ -321,9 +320,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, name);
-
        /* Attach to existing DSA. */
        ret = dsa_attach(state->handle);
        dsa_pin_mapping(ret);
@@ -378,8 +374,7 @@ GetNamedDSHash(const char *name, const dshash_parameters *params, bool *found)
        entry->type = DSMR_ENTRY_TYPE_DSH;
 
        /* Initialize the LWLock tranche for the hash table. */
-       dsh_state->tranche = LWLockNewTrancheId();
-       LWLockRegisterTranche(dsh_state->tranche, name);
+       dsh_state->tranche = LWLockNewTrancheId(name);
 
        /* Initialize the DSA for the hash table. */
        dsa = dsa_create(dsh_state->tranche);
@@ -409,9 +404,6 @@ GetNamedDSHash(const char *name, const dshash_parameters *params, bool *found)
            ereport(ERROR,
                    (errmsg("requested DSHash already attached to current process")));
 
-       /* Initialize existing LWLock tranche for the hash table. */
-       LWLockRegisterTranche(dsh_state->tranche, name);
-
        /* Attach to existing DSA for the hash table. */
        dsa = dsa_attach(dsh_state->dsa_handle);
        dsa_pin_mapping(dsa);
index a4aecd1fbc34f635dd34a1b76c1596d76a50f290..258cdebd0f5c992b3fb89c16dbdb9a8f7b30f5ce 100644 (file)
@@ -126,8 +126,8 @@ StaticAssertDecl((LW_VAL_EXCLUSIVE & LW_FLAG_MASK) == 0,
  * 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[].
+ * or LWLockNewTrancheId.  These names are stored in shared memory and can be
+ * accessed via LWLockTrancheNames.
  *
  * 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 +146,12 @@ 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.
+ * points to the shared memory locations of the names of all
+ * dynamically-created tranches.  Backends inherit the pointer by fork from the
+ * postmaster (except in the EXEC_BACKEND case, where we have special measures
+ * to pass it down).
  */
-static const char **LWLockTrancheNames = NULL;
-static int LWLockTrancheNamesAllocated = 0;
+char     **LWLockTrancheNames = NULL;
 
 /*
  * This points to the main array of LWLocks in shared memory.  Backends inherit
@@ -184,20 +185,22 @@ typedef struct NamedLWLockTrancheRequest
 } NamedLWLockTrancheRequest;
 
 static NamedLWLockTrancheRequest *NamedLWLockTrancheRequestArray = NULL;
-static int NamedLWLockTrancheRequestsAllocated = 0;
 
 /*
- * NamedLWLockTrancheRequests is both the valid length of the request array,
- * and the length of the shared-memory NamedLWLockTrancheArray later on.
- * This variable and NamedLWLockTrancheArray are non-static so that
- * postmaster.c can copy them to child processes in EXEC_BACKEND builds.
+ * NamedLWLockTrancheRequests is the valid length of the request array.  This
+ * variable is non-static so that postmaster.c can copy them to child processes
+ * in EXEC_BACKEND builds.
  */
 int            NamedLWLockTrancheRequests = 0;
 
-/* points to data in shared memory: */
-NamedLWLockTranche *NamedLWLockTrancheArray = NULL;
+/* shared memory counter of registered tranches */
 int           *LWLockCounter = NULL;
 
+/* backend-local counter of registered tranches */
+static int LocalLWLockCounter;
+
+#define MAX_NAMED_TRANCHES 256
+
 static void InitializeLWLocks(void);
 static inline void LWLockReportWaitStart(LWLock *lock);
 static inline void LWLockReportWaitEnd(void);
@@ -392,31 +395,28 @@ Size
 LWLockShmemSize(void)
 {
    Size        size;
-   int         i;
    int         numLocks = NUM_FIXED_LWLOCKS;
 
    /* Calculate total number of locks needed in the main array. */
    numLocks += NumLWLocksForNamedTranches();
 
-   /* Space for dynamic allocation counter, plus room for alignment. */
-   size = sizeof(int) + LWLOCK_PADDED_SIZE;
+   /* Space for dynamic allocation counter. */
+   size = MAXALIGN(sizeof(int));
 
-   /* Space for the LWLock array. */
-   size = add_size(size, mul_size(numLocks, sizeof(LWLockPadded)));
+   /* Space for named tranches. */
+   size = add_size(size, mul_size(MAX_NAMED_TRANCHES, sizeof(char *)));
+   size = add_size(size, mul_size(MAX_NAMED_TRANCHES, NAMEDATALEN));
 
-   /* 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 the LWLock array, plus room for cache line alignment. */
+   size = add_size(size, LWLOCK_PADDED_SIZE);
+   size = add_size(size, mul_size(numLocks, sizeof(LWLockPadded)));
 
    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)
@@ -432,7 +432,16 @@ CreateLWLocks(void)
        /* Initialize the dynamic-allocation counter for tranches */
        LWLockCounter = (int *) ptr;
        *LWLockCounter = LWTRANCHE_FIRST_USER_DEFINED;
-       ptr += sizeof(int);
+       ptr += MAXALIGN(sizeof(int));
+
+       /* Initialize tranche names */
+       LWLockTrancheNames = (char **) ptr;
+       ptr += MAX_NAMED_TRANCHES * sizeof(char *);
+       for (int i = 0; i < MAX_NAMED_TRANCHES; i++)
+       {
+           LWLockTrancheNames[i] = ptr;
+           ptr += NAMEDATALEN;
+       }
 
        /* Ensure desired alignment of LWLock array */
        ptr += LWLOCK_PADDED_SIZE - ((uintptr_t) ptr) % LWLOCK_PADDED_SIZE;
@@ -441,11 +450,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);
 }
 
 /*
@@ -454,7 +458,6 @@ CreateLWLocks(void)
 static void
 InitializeLWLocks(void)
 {
-   int         numNamedLocks = NumLWLocksForNamedTranches();
    int         id;
    int         i;
    int         j;
@@ -485,32 +488,18 @@ InitializeLWLocks(void)
     */
    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;
 
            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;
+           tranche = LWLockNewTrancheId(request->tranche_name);
 
            for (j = 0; j < request->num_lwlocks; j++, lock++)
-               LWLockInitialize(&lock->lock, tranche->trancheId);
+               LWLockInitialize(&lock->lock, tranche);
        }
    }
 }
@@ -562,59 +551,47 @@ GetNamedLWLockTranche(const char *tranche_name)
 }
 
 /*
- * Allocate a new tranche ID.
+ * Allocate a new tranche ID with the provided name.
  */
 int
-LWLockNewTrancheId(void)
+LWLockNewTrancheId(const char *name)
 {
    int         result;
 
-   /* We use the ShmemLock spinlock to protect LWLockCounter */
-   SpinLockAcquire(ShmemLock);
-   result = (*LWLockCounter)++;
-   SpinLockRelease(ShmemLock);
+   if (!name)
+       ereport(ERROR,
+               (errcode(ERRCODE_INVALID_NAME),
+                errmsg("tranche name cannot be NULL")));
 
-   return result;
-}
+   if (strlen(name) >= NAMEDATALEN)
+       ereport(ERROR,
+               (errcode(ERRCODE_NAME_TOO_LONG),
+                errmsg("tranche name too long"),
+                errdetail("LWLock tranche names must be no longer than %d bytes.",
+                          NAMEDATALEN - 1)));
 
-/*
- * 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;
-
-   /* Convert to array index. */
-   tranche_id -= LWTRANCHE_FIRST_USER_DEFINED;
+   /*
+    * We use the ShmemLock spinlock to protect LWLockCounter and
+    * LWLockTrancheNames.
+    */
+   SpinLockAcquire(ShmemLock);
 
-   /* If necessary, create or enlarge array. */
-   if (tranche_id >= LWLockTrancheNamesAllocated)
+   if (*LWLockCounter - LWTRANCHE_FIRST_USER_DEFINED >= MAX_NAMED_TRANCHES)
    {
-       int         newalloc;
+       SpinLockRelease(ShmemLock);
+       ereport(ERROR,
+               (errmsg("maximum number of tranches already registered"),
+                errdetail("No more than %d tranches may be registered.",
+                          MAX_NAMED_TRANCHES)));
+   }
 
-       newalloc = pg_nextpower2_32(Max(8, tranche_id + 1));
+   result = (*LWLockCounter)++;
+   LocalLWLockCounter = *LWLockCounter;
+   strlcpy(LWLockTrancheNames[result - LWTRANCHE_FIRST_USER_DEFINED], name, NAMEDATALEN);
 
-       if (LWLockTrancheNames == NULL)
-           LWLockTrancheNames = (const char **)
-               MemoryContextAllocZero(TopMemoryContext,
-                                      newalloc * sizeof(char *));
-       else
-           LWLockTrancheNames =
-               repalloc0_array(LWLockTrancheNames, const char *, LWLockTrancheNamesAllocated, newalloc);
-       LWLockTrancheNamesAllocated = newalloc;
-   }
+   SpinLockRelease(ShmemLock);
 
-   LWLockTrancheNames[tranche_id] = tranche_name;
+   return result;
 }
 
 /*
@@ -637,27 +614,33 @@ RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)
    if (!process_shmem_requests_in_progress)
        elog(FATAL, "cannot request additional LWLocks outside shmem_request_hook");
 
+   if (!tranche_name)
+       ereport(ERROR,
+               (errcode(ERRCODE_INVALID_NAME),
+                errmsg("tranche name cannot be NULL")));
+
+   if (strlen(tranche_name) >= NAMEDATALEN)
+       ereport(ERROR,
+               (errcode(ERRCODE_NAME_TOO_LONG),
+                errmsg("tranche name too long"),
+                errdetail("LWLock tranche names must be no longer than %d bytes.",
+                          NAMEDATALEN - 1)));
+
    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)
+       ereport(ERROR,
+               (errmsg("maximum number of tranches already registered"),
+                errdetail("No more than %d tranches may be registered.",
+                          MAX_NAMED_TRANCHES)));
 
    request = &NamedLWLockTrancheRequestArray[NamedLWLockTrancheRequests];
-   Assert(strlen(tranche_name) + 1 <= NAMEDATALEN);
    strlcpy(request->tranche_name, tranche_name, NAMEDATALEN);
    request->num_lwlocks = num_lwlocks;
    NamedLWLockTrancheRequests++;
@@ -669,6 +652,9 @@ RequestNamedLWLockTranche(const char *tranche_name, int num_lwlocks)
 void
 LWLockInitialize(LWLock *lock, int tranche_id)
 {
+   /* verify the tranche_id is valid */
+   (void) GetLWTrancheName(tranche_id);
+
    pg_atomic_init_u32(&lock->state, LW_FLAG_RELEASE_OK);
 #ifdef LOCK_DEBUG
    pg_atomic_init_u32(&lock->nwaiters, 0);
@@ -710,15 +696,27 @@ GetLWTrancheName(uint16 trancheId)
        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".
+    * We only ever add new entries to LWLockTrancheNames, so most lookups can
+    * avoid taking the spinlock as long as the backend-local counter
+    * (LocalLWLockCounter) is greater than the requested tranche ID.  Else,
+    * we need to first update the backend-local counter with ShmemLock held
+    * before attempting the lookup again.  In practice, the latter case is
+    * probably rare.
     */
-   trancheId -= LWTRANCHE_FIRST_USER_DEFINED;
+   if (trancheId >= LocalLWLockCounter)
+   {
+       SpinLockAcquire(ShmemLock);
+       LocalLWLockCounter = *LWLockCounter;
+       SpinLockRelease(ShmemLock);
+
+       if (trancheId >= LocalLWLockCounter)
+           elog(ERROR, "tranche %d is not registered", trancheId);
+   }
 
-   if (trancheId >= LWLockTrancheNamesAllocated ||
-       LWLockTrancheNames[trancheId] == NULL)
-       return "extension";
+   /*
+    * It's an extension tranche, so look in LWLockTrancheNames.
+    */
+   trancheId -= LWTRANCHE_FIRST_USER_DEFINED;
 
    return LWLockTrancheNames[trancheId];
 }
index f9cf57f8d266d10c7438a3bd048c7951db588e35..0e9cf81a4c7668dcda82d621d2e372b06d082150 100644 (file)
@@ -73,14 +73,7 @@ typedef union LWLockPadded
 
 extern PGDLLIMPORT LWLockPadded *MainLWLockArray;
 
-/* struct for storing named tranche information */
-typedef struct NamedLWLockTranche
-{
-   int         trancheId;
-   char       *trancheName;
-} NamedLWLockTranche;
-
-extern PGDLLIMPORT NamedLWLockTranche *NamedLWLockTrancheArray;
+extern PGDLLIMPORT char **LWLockTrancheNames;
 extern PGDLLIMPORT int NamedLWLockTrancheRequests;
 extern PGDLLIMPORT int *LWLockCounter;
 
@@ -158,19 +151,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 to obtain a tranche ID; this allocates from a shared
+ * counter.  Second, 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 *name);
 extern void LWLockInitialize(LWLock *lock, int tranche_id);
 
 /*
index cd24d0f48736d6f4286ab97d6fc3a3ae6b91040d..01d5c6fa67f0efd09360961a5116a42f9d2eb162 100644 (file)
@@ -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);
index 141c8ed1b34e3b87ee526d043ddc500b47ec8d0f..4cc2ccdac3f1123ee57afad5008b7be88047d91c 100644 (file)
@@ -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);
index 80ad029616473561719289c111124bfdadd052d5..787162c879330f9074cb65ad8842f866e185e391 100644 (file)
@@ -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
index 32750930e433de41ae7d11d6d4f43ff1acbc590f..8c0367eeee424b21c92a4c01301506d0b53fc0b9 100644 (file)
@@ -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",
index eb16e0fbfa6470e841dc4e1b765611a959f1c645..0c8f43867e55e1bd6cbcaff7bdd99391df24d85f 100644 (file)
@@ -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);