Simplify LWLock tranche machinery by removing array_base/array_stride.
authorRobert Haas <rhaas@postgresql.org>
Fri, 16 Dec 2016 16:29:23 +0000 (11:29 -0500)
committerRobert Haas <rhaas@postgresql.org>
Fri, 16 Dec 2016 16:29:23 +0000 (11:29 -0500)
array_base and array_stride were added so that we could identify the
offset of an LWLock within a tranche, but this facility is only very
marginally used apart from the main tranche.  So, give every lock in
the main tranche its own tranche ID and get rid of array_base,
array_stride, and all that's attached.  For debugging facilities
(Trace_lwlocks and LWLOCK_STATS) print the pointer address of the
LWLock using %p instead of the offset.  This is arguably more useful,
and certainly a lot cheaper.  Drop the offset-within-tranche from
the information reported to dtrace and from one can't-happen message
inside lwlock.c.

The main user-visible impact of this change is that pg_stat_activity
will now report all waits for LWLocks as "LWLock" rather than
reporting some as "LWLockTranche" and others as "LWLockNamed".

The main motivation for this change is that the need to specify an
array_base and an array_stride is awkward for parallel query.  There
is only a very limited supply of tranche IDs so we can't just keep
allocating new ones, and if we try to use the same tranche IDs every
time then we run into trouble when multiple parallel contexts are
use simultaneously.  So if we didn't get rid of this mechanism we'd
have to make it even more complicated.  By simplifying it in this
way, we instead reduce the size of the generated code for lwlock.c
by about 5%.

Discussion: http://postgr.es/m/CA+TgmoYsFn6NUW1x0AZtupJGUAs1UDY4dJtCN47_Q6D0sP80PA@mail.gmail.com

14 files changed:
doc/src/sgml/monitoring.sgml
src/backend/access/transam/slru.c
src/backend/access/transam/xlog.c
src/backend/postmaster/pgstat.c
src/backend/replication/logical/origin.c
src/backend/replication/slot.c
src/backend/storage/buffer/buf_init.c
src/backend/storage/ipc/procarray.c
src/backend/storage/lmgr/lwlock.c
src/backend/utils/mmgr/dsa.c
src/backend/utils/probes.d
src/include/access/slru.h
src/include/pgstat.h
src/include/storage/lwlock.h

index 128ee13b5f7f2230b46b028a3df8f31b55c122c7..5b58d2e84dcf064c27d433ee29caa3da272bd437 100644 (file)
@@ -646,18 +646,11 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
        <itemizedlist>
         <listitem>
          <para>
-          <literal>LWLockNamed</>: The backend is waiting for a specific named
-          lightweight lock.  Each such lock protects a particular data
-          structure in shared memory.  <literal>wait_event</> will contain
-          the name of the lightweight lock.
-         </para>
-        </listitem>
-        <listitem>
-         <para>
-          <literal>LWLockTranche</>: The backend is waiting for one of a
-          group of related lightweight locks.  All locks in the group perform
-          a similar function; <literal>wait_event</> will identify the general
-          purpose of locks in that group.
+          <literal>LWLock</>: The backend is waiting for a lightweight lock.
+          Each such lock protects a particular data structure in shared memory.
+          <literal>wait_event</> will contain a name identifying the purpose
+          of the lightweight lock.  (Some locks have specific names; others
+          are part of a group of locks each with a similar purpose.)
          </para>
         </listitem>
         <listitem>
@@ -825,7 +818,7 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
 
       <tbody>
        <row>
-        <entry morerows="41"><literal>LWLockNamed</></entry>
+        <entry morerows="57"><literal>LWLock</></entry>
         <entry><literal>ShmemIndexLock</></entry>
         <entry>Waiting to find or allocate space in shared memory.</entry>
        </row>
@@ -1011,7 +1004,6 @@ postgres   27093  0.0  0.0  30096  2752 ?        Ss   11:34   0:00 postgres: ser
          <entry>Waiting to read or update old snapshot control information.</entry>
         </row>
         <row>
-         <entry morerows="15"><literal>LWLockTranche</></entry>
          <entry><literal>clog</></entry>
          <entry>Waiting for I/O on a clog (transaction status) buffer.</entry>
         </row>
@@ -1279,7 +1271,7 @@ SELECT pid, wait_event_type, wait_event FROM pg_stat_activity WHERE wait_event i
  pid  | wait_event_type |  wait_event
 ------+-----------------+---------------
  2540 | Lock            | relation
- 6644 | LWLockNamed     | ProcArrayLock
+ 6644 | LWLock          | ProcArrayLock
 (2 rows)
 </programlisting>
    </para>
@@ -3347,55 +3339,49 @@ SELECT pg_stat_get_backend_pid(s.backendid) AS pid,
     </row>
     <row>
      <entry><literal>lwlock-acquire</literal></entry>
-     <entry><literal>(char *, int, LWLockMode)</literal></entry>
+     <entry><literal>(char *, LWLockMode)</literal></entry>
      <entry>Probe that fires when an LWLock has been acquired.
       arg0 is the LWLock's tranche.
-      arg1 is the LWLock's offset within its tranche.
-      arg2 is the requested lock mode, either exclusive or shared.</entry>
+      arg1 is the requested lock mode, either exclusive or shared.</entry>
     </row>
     <row>
      <entry><literal>lwlock-release</literal></entry>
-     <entry><literal>(char *, int)</literal></entry>
+     <entry><literal>(char *)</literal></entry>
      <entry>Probe that fires when an LWLock has been released (but note
       that any released waiters have not yet been awakened).
-      arg0 is the LWLock's tranche.
-      arg1 is the LWLock's offset within its tranche.</entry>
+      arg0 is the LWLock's tranche.</entry>
     </row>
     <row>
      <entry><literal>lwlock-wait-start</literal></entry>
-     <entry><literal>(char *, int, LWLockMode)</literal></entry>
+     <entry><literal>(char *, LWLockMode)</literal></entry>
      <entry>Probe that fires when an LWLock was not immediately available and
       a server process has begun to wait for the lock to become available.
       arg0 is the LWLock's tranche.
-      arg1 is the LWLock's offset within its tranche.
-      arg2 is the requested lock mode, either exclusive or shared.</entry>
+      arg1 is the requested lock mode, either exclusive or shared.</entry>
     </row>
     <row>
      <entry><literal>lwlock-wait-done</literal></entry>
-     <entry><literal>(char *, int, LWLockMode)</literal></entry>
+     <entry><literal>(char *, LWLockMode)</literal></entry>
      <entry>Probe that fires when a server process has been released from its
       wait for an LWLock (it does not actually have the lock yet).
       arg0 is the LWLock's tranche.
-      arg1 is the LWLock's offset within its tranche.
-      arg2 is the requested lock mode, either exclusive or shared.</entry>
+      arg1 is the requested lock mode, either exclusive or shared.</entry>
     </row>
     <row>
      <entry><literal>lwlock-condacquire</literal></entry>
-     <entry><literal>(char *, int, LWLockMode)</literal></entry>
+     <entry><literal>(char *, LWLockMode)</literal></entry>
      <entry>Probe that fires when an LWLock was successfully acquired when the
       caller specified no waiting.
       arg0 is the LWLock's tranche.
-      arg1 is the LWLock's offset within its tranche.
-      arg2 is the requested lock mode, either exclusive or shared.</entry>
+      arg1 is the requested lock mode, either exclusive or shared.</entry>
     </row>
     <row>
      <entry><literal>lwlock-condacquire-fail</literal></entry>
-     <entry><literal>(char *, int, LWLockMode)</literal></entry>
+     <entry><literal>(char *, LWLockMode)</literal></entry>
      <entry>Probe that fires when an LWLock was not successfully acquired when
       the caller specified no waiting.
       arg0 is the LWLock's tranche.
-      arg1 is the LWLock's offset within its tranche.
-      arg2 is the requested lock mode, either exclusive or shared.</entry>
+      arg1 is the requested lock mode, either exclusive or shared.</entry>
     </row>
     <row>
      <entry><literal>lock-wait-start</literal></entry>
index bbae5847f2d5dab6d533c921de1aafd1134fc9cb..8b95f35dbaf412c57deb8cf048d9ef9299bb4b6b 100644 (file)
@@ -216,9 +216,6 @@ SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
        Assert(strlen(name) + 1 < SLRU_MAX_NAME_LENGTH);
        strlcpy(shared->lwlock_tranche_name, name, SLRU_MAX_NAME_LENGTH);
        shared->lwlock_tranche_id = tranche_id;
-       shared->lwlock_tranche.name = shared->lwlock_tranche_name;
-       shared->lwlock_tranche.array_base = shared->buffer_locks;
-       shared->lwlock_tranche.array_stride = sizeof(LWLockPadded);
 
        ptr += BUFFERALIGN(offset);
        for (slotno = 0; slotno < nslots; slotno++)
@@ -237,7 +234,8 @@ SimpleLruInit(SlruCtl ctl, const char *name, int nslots, int nlsns,
        Assert(found);
 
    /* Register SLRU tranche in the main tranches array */
-   LWLockRegisterTranche(shared->lwlock_tranche_id, &shared->lwlock_tranche);
+   LWLockRegisterTranche(shared->lwlock_tranche_id,
+                         shared->lwlock_tranche_name);
 
    /*
     * Initialize the unshared control struct, including directory path. We
index 084401d2f238d729243bca4e3fdad4ff5a82f123..aa9ee5a0dd84cad03895ab3a63e99c97a4eadbd1 100644 (file)
@@ -517,7 +517,6 @@ typedef struct XLogCtlInsert
     * WAL insertion locks.
     */
    WALInsertLockPadded *WALInsertLocks;
-   LWLockTranche WALInsertLockTranche;
 } XLogCtlInsert;
 
 /*
@@ -4688,7 +4687,7 @@ XLOGShmemInit(void)
        /* Initialize local copy of WALInsertLocks and register the tranche */
        WALInsertLocks = XLogCtl->Insert.WALInsertLocks;
        LWLockRegisterTranche(LWTRANCHE_WAL_INSERT,
-                             &XLogCtl->Insert.WALInsertLockTranche);
+                             "wal_insert");
        return;
    }
    memset(XLogCtl, 0, sizeof(XLogCtlData));
@@ -4711,11 +4710,7 @@ XLOGShmemInit(void)
        (WALInsertLockPadded *) allocptr;
    allocptr += sizeof(WALInsertLockPadded) * NUM_XLOGINSERT_LOCKS;
 
-   XLogCtl->Insert.WALInsertLockTranche.name = "wal_insert";
-   XLogCtl->Insert.WALInsertLockTranche.array_base = WALInsertLocks;
-   XLogCtl->Insert.WALInsertLockTranche.array_stride = sizeof(WALInsertLockPadded);
-
-   LWLockRegisterTranche(LWTRANCHE_WAL_INSERT, &XLogCtl->Insert.WALInsertLockTranche);
+   LWLockRegisterTranche(LWTRANCHE_WAL_INSERT, "wal_insert");
    for (i = 0; i < NUM_XLOGINSERT_LOCKS; i++)
    {
        LWLockInitialize(&WALInsertLocks[i].l.lock, LWTRANCHE_WAL_INSERT);
index c7584cb1d3492e89684bf986c163e926a86d3bae..61e6a2cd3390e8d56b94572e6103752b0b927d5e 100644 (file)
@@ -3152,11 +3152,8 @@ pgstat_get_wait_event_type(uint32 wait_event_info)
 
    switch (classId)
    {
-       case PG_WAIT_LWLOCK_NAMED:
-           event_type = "LWLockNamed";
-           break;
-       case PG_WAIT_LWLOCK_TRANCHE:
-           event_type = "LWLockTranche";
+       case PG_WAIT_LWLOCK:
+           event_type = "LWLock";
            break;
        case PG_WAIT_LOCK:
            event_type = "Lock";
@@ -3209,8 +3206,7 @@ pgstat_get_wait_event(uint32 wait_event_info)
 
    switch (classId)
    {
-       case PG_WAIT_LWLOCK_NAMED:
-       case PG_WAIT_LWLOCK_TRANCHE:
+       case PG_WAIT_LWLOCK:
            event_name = GetLWLockIdentifier(classId, eventId);
            break;
        case PG_WAIT_LOCK:
index cc2b513236623b39570bb7eb916c4a348a29e249..0deec75dc260a334560d7711c484b751537930cf 100644 (file)
@@ -143,7 +143,6 @@ typedef struct ReplicationStateOnDisk
 typedef struct ReplicationStateCtl
 {
    int         tranche_id;
-   LWLockTranche tranche;
    ReplicationState states[FLEXIBLE_ARRAY_MEMBER];
 } ReplicationStateCtl;
 
@@ -474,11 +473,6 @@ ReplicationOriginShmemInit(void)
        int         i;
 
        replication_states_ctl->tranche_id = LWTRANCHE_REPLICATION_ORIGIN;
-       replication_states_ctl->tranche.name = "replication_origin";
-       replication_states_ctl->tranche.array_base =
-           &replication_states[0].lock;
-       replication_states_ctl->tranche.array_stride =
-           sizeof(ReplicationState);
 
        MemSet(replication_states, 0, ReplicationOriginShmemSize());
 
@@ -488,7 +482,7 @@ ReplicationOriginShmemInit(void)
    }
 
    LWLockRegisterTranche(replication_states_ctl->tranche_id,
-                         &replication_states_ctl->tranche);
+                         "replication_origin");
 }
 
 /* ---------------------------------------------------------------------------
index d8ed005e7ece28243a7db90889a4a21f60db568e..cf814d11a2311f39e437634df9f565c2300e30ba 100644 (file)
@@ -98,8 +98,6 @@ ReplicationSlot *MyReplicationSlot = NULL;
 int            max_replication_slots = 0;  /* the maximum number of replication
                                         * slots */
 
-static LWLockTranche ReplSlotIOLWLockTranche;
-
 static void ReplicationSlotDropAcquired(void);
 static void ReplicationSlotDropPtr(ReplicationSlot *slot);
 
@@ -141,12 +139,8 @@ ReplicationSlotsShmemInit(void)
        ShmemInitStruct("ReplicationSlot Ctl", ReplicationSlotsShmemSize(),
                        &found);
 
-   ReplSlotIOLWLockTranche.name = "replication_slot_io";
-   ReplSlotIOLWLockTranche.array_base =
-       ((char *) ReplicationSlotCtl) + offsetof(ReplicationSlotCtlData, replication_slots) +offsetof(ReplicationSlot, io_in_progress_lock);
-   ReplSlotIOLWLockTranche.array_stride = sizeof(ReplicationSlot);
    LWLockRegisterTranche(LWTRANCHE_REPLICATION_SLOT_IO_IN_PROGRESS,
-                         &ReplSlotIOLWLockTranche);
+                         "replication_slot_io");
 
    if (!found)
    {
index a4163cf717d91a85a328c58a00d29852567fb2bf..c507389a050b986a90c5469497405e94e20ebd82 100644 (file)
@@ -21,8 +21,6 @@
 BufferDescPadded *BufferDescriptors;
 char      *BufferBlocks;
 LWLockMinimallyPadded *BufferIOLWLockArray = NULL;
-LWLockTranche BufferIOLWLockTranche;
-LWLockTranche BufferContentLWLockTranche;
 WritebackContext BackendWritebackContext;
 CkptSortItem *CkptBufferIds;
 
@@ -90,18 +88,8 @@ InitBufferPool(void)
                        NBuffers * (Size) sizeof(LWLockMinimallyPadded),
                        &foundIOLocks);
 
-   BufferIOLWLockTranche.name = "buffer_io";
-   BufferIOLWLockTranche.array_base = BufferIOLWLockArray;
-   BufferIOLWLockTranche.array_stride = sizeof(LWLockMinimallyPadded);
-   LWLockRegisterTranche(LWTRANCHE_BUFFER_IO_IN_PROGRESS,
-                         &BufferIOLWLockTranche);
-
-   BufferContentLWLockTranche.name = "buffer_content";
-   BufferContentLWLockTranche.array_base =
-       ((char *) BufferDescriptors) + offsetof(BufferDesc, content_lock);
-   BufferContentLWLockTranche.array_stride = sizeof(BufferDescPadded);
-   LWLockRegisterTranche(LWTRANCHE_BUFFER_CONTENT,
-                         &BufferContentLWLockTranche);
+   LWLockRegisterTranche(LWTRANCHE_BUFFER_IO_IN_PROGRESS, "buffer_io");
+   LWLockRegisterTranche(LWTRANCHE_BUFFER_CONTENT, "buffer_content");
 
    /*
     * The array used to sort to-be-checkpointed buffer ids is located in
index bf38470f01d92204d93d9a9632f0df402b88461e..0f637556ccbc94c6fde256032145eb96b17bc351 100644 (file)
@@ -106,9 +106,6 @@ static TransactionId *KnownAssignedXids;
 static bool *KnownAssignedXidsValid;
 static TransactionId latestObservedXid = InvalidTransactionId;
 
-/* LWLock tranche for backend locks */
-static LWLockTranche ProcLWLockTranche;
-
 /*
  * If we're in STANDBY_SNAPSHOT_PENDING state, standbySnapshotPendingXmin is
  * the highest xid that might still be running that we don't have in
@@ -266,11 +263,7 @@ CreateSharedProcArray(void)
    }
 
    /* Register and initialize fields of ProcLWLockTranche */
-   ProcLWLockTranche.name = "proc";
-   ProcLWLockTranche.array_base = (char *) (ProcGlobal->allProcs) +
-       offsetof(PGPROC, backendLock);
-   ProcLWLockTranche.array_stride = sizeof(PGPROC);
-   LWLockRegisterTranche(LWTRANCHE_PROC, &ProcLWLockTranche);
+   LWLockRegisterTranche(LWTRANCHE_PROC, "proc");
 }
 
 /*
index 03c4c7825eb37c070bcee8f8ba03f0d564254b69..4b381e4e0cc7a73ab8995d3ca77d3abbd2a0c4d0 100644 (file)
@@ -108,18 +108,14 @@ extern slock_t *ShmemLock;
 #define LW_SHARED_MASK             ((uint32) ((1 << 24)-1))
 
 /*
- * This is indexed by tranche ID and stores metadata for all tranches known
+ * This is indexed by tranche ID and stores the names of all tranches known
  * to the current backend.
  */
-static LWLockTranche **LWLockTrancheArray = NULL;
+static char **LWLockTrancheArray = NULL;
 static int LWLockTranchesAllocated = 0;
 
 #define T_NAME(lock) \
-   (LWLockTrancheArray[(lock)->tranche]->name)
-#define T_ID(lock) \
-   ((int) ((((char *) lock) - \
-       ((char *) LWLockTrancheArray[(lock)->tranche]->array_base)) / \
-       LWLockTrancheArray[(lock)->tranche]->array_stride))
+   (LWLockTrancheArray[(lock)->tranche])
 
 /*
  * This points to the main array of LWLocks in shared memory.  Backends inherit
@@ -127,10 +123,6 @@ static int LWLockTranchesAllocated = 0;
  * where we have special measures to pass it down).
  */
 LWLockPadded *MainLWLockArray = NULL;
-static LWLockTranche MainLWLockTranche;
-static LWLockTranche BufMappingLWLockTranche;
-static LWLockTranche LockManagerLWLockTranche;
-static LWLockTranche PredicateLockManagerLWLockTranche;
 
 /*
  * We use this structure to keep track of locked LWLocks for release
@@ -175,7 +167,7 @@ static inline void LWLockReportWaitEnd(void);
 typedef struct lwlock_stats_key
 {
    int         tranche;
-   int         instance;
+   void       *instance;
 }  lwlock_stats_key;
 
 typedef struct lwlock_stats
@@ -202,32 +194,18 @@ PRINT_LWDEBUG(const char *where, LWLock *lock, LWLockMode mode)
    if (Trace_lwlocks)
    {
        uint32      state = pg_atomic_read_u32(&lock->state);
-       int         id = T_ID(lock);
-
-       if (lock->tranche == 0 && id < NUM_INDIVIDUAL_LWLOCKS)
-           ereport(LOG,
-                   (errhidestmt(true),
-                    errhidecontext(true),
-                    errmsg_internal("%d: %s(%s): excl %u shared %u haswaiters %u waiters %u rOK %d",
-                                    MyProcPid,
-                                    where, MainLWLockNames[id],
-                                    (state & LW_VAL_EXCLUSIVE) != 0,
-                                    state & LW_SHARED_MASK,
-                                    (state & LW_FLAG_HAS_WAITERS) != 0,
-                                    pg_atomic_read_u32(&lock->nwaiters),
-                                    (state & LW_FLAG_RELEASE_OK) != 0)));
-       else
-           ereport(LOG,
-                   (errhidestmt(true),
-                    errhidecontext(true),
-                    errmsg_internal("%d: %s(%s %d): excl %u shared %u haswaiters %u waiters %u rOK %d",
-                                    MyProcPid,
-                                    where, T_NAME(lock), id,
-                                    (state & LW_VAL_EXCLUSIVE) != 0,
-                                    state & LW_SHARED_MASK,
-                                    (state & LW_FLAG_HAS_WAITERS) != 0,
-                                    pg_atomic_read_u32(&lock->nwaiters),
-                                    (state & LW_FLAG_RELEASE_OK) != 0)));
+
+       ereport(LOG,
+               (errhidestmt(true),
+                errhidecontext(true),
+                errmsg_internal("%d: %s(%s %p): excl %u shared %u haswaiters %u waiters %u rOK %d",
+                                MyProcPid,
+                                where, T_NAME(lock), lock,
+                                (state & LW_VAL_EXCLUSIVE) != 0,
+                                state & LW_SHARED_MASK,
+                                (state & LW_FLAG_HAS_WAITERS) != 0,
+                                pg_atomic_read_u32(&lock->nwaiters),
+                                (state & LW_FLAG_RELEASE_OK) != 0)));
    }
 }
 
@@ -237,20 +215,11 @@ LOG_LWDEBUG(const char *where, LWLock *lock, const char *msg)
    /* hide statement & context here, otherwise the log is just too verbose */
    if (Trace_lwlocks)
    {
-       int         id = T_ID(lock);
-
-       if (lock->tranche == 0 && id < NUM_INDIVIDUAL_LWLOCKS)
-           ereport(LOG,
-                   (errhidestmt(true),
-                    errhidecontext(true),
-                    errmsg_internal("%s(%s): %s", where,
-                                    MainLWLockNames[id], msg)));
-       else
-           ereport(LOG,
-                   (errhidestmt(true),
-                    errhidecontext(true),
-                    errmsg_internal("%s(%s %d): %s", where,
-                                    T_NAME(lock), id, msg)));
+       ereport(LOG,
+               (errhidestmt(true),
+                errhidecontext(true),
+                errmsg_internal("%s(%s %p): %s", where,
+                                T_NAME(lock), lock, msg)));
    }
 }
 
@@ -315,8 +284,8 @@ print_lwlock_stats(int code, Datum arg)
    while ((lwstats = (lwlock_stats *) hash_seq_search(&scan)) != NULL)
    {
        fprintf(stderr,
-               "PID %d lwlock %s %d: shacq %u exacq %u blk %u spindelay %u dequeue self %u\n",
-               MyProcPid, LWLockTrancheArray[lwstats->key.tranche]->name,
+               "PID %d lwlock %s %p: shacq %u exacq %u blk %u spindelay %u dequeue self %u\n",
+               MyProcPid, LWLockTrancheArray[lwstats->key.tranche],
                lwstats->key.instance, lwstats->sh_acquire_count,
                lwstats->ex_acquire_count, lwstats->block_count,
                lwstats->spin_delay_count, lwstats->dequeue_self_count);
@@ -342,7 +311,7 @@ get_lwlock_stats_entry(LWLock *lock)
 
    /* Fetch or create the entry. */
    key.tranche = lock->tranche;
-   key.instance = T_ID(lock);
+   key.instance = lock;
    lwstats = hash_search(lwlock_stats_htab, &key, HASH_ENTER, &found);
    if (!found)
    {
@@ -464,7 +433,7 @@ InitializeLWLocks(void)
 
    /* Initialize all individual LWLocks in main array */
    for (id = 0, lock = MainLWLockArray; id < NUM_INDIVIDUAL_LWLOCKS; id++, lock++)
-       LWLockInitialize(&lock->lock, LWTRANCHE_MAIN);
+       LWLockInitialize(&lock->lock, id);
 
    /* Initialize buffer mapping LWLocks in main array */
    lock = MainLWLockArray + NUM_INDIVIDUAL_LWLOCKS;
@@ -506,10 +475,8 @@ InitializeLWLocks(void)
            name = trancheNames;
            trancheNames += strlen(request->tranche_name) + 1;
            strcpy(name, request->tranche_name);
-           tranche->lwLockTranche.name = name;
            tranche->trancheId = LWLockNewTrancheId();
-           tranche->lwLockTranche.array_base = lock;
-           tranche->lwLockTranche.array_stride = sizeof(LWLockPadded);
+           tranche->trancheName = name;
 
            for (j = 0; j < request->num_lwlocks; j++, lock++)
                LWLockInitialize(&lock->lock, tranche->trancheId);
@@ -527,39 +494,25 @@ RegisterLWLockTranches(void)
 
    if (LWLockTrancheArray == NULL)
    {
-       LWLockTranchesAllocated = 32;
-       LWLockTrancheArray = (LWLockTranche **)
+       LWLockTranchesAllocated = 64;
+       LWLockTrancheArray = (char **)
            MemoryContextAllocZero(TopMemoryContext,
-                         LWLockTranchesAllocated * sizeof(LWLockTranche *));
+                         LWLockTranchesAllocated * sizeof(char *));
        Assert(LWLockTranchesAllocated >= LWTRANCHE_FIRST_USER_DEFINED);
    }
 
-   MainLWLockTranche.name = "main";
-   MainLWLockTranche.array_base = MainLWLockArray;
-   MainLWLockTranche.array_stride = sizeof(LWLockPadded);
-   LWLockRegisterTranche(LWTRANCHE_MAIN, &MainLWLockTranche);
+   for (i = 0; i < NUM_INDIVIDUAL_LWLOCKS; ++i)
+       LWLockRegisterTranche(i, MainLWLockNames[i]);
 
-   BufMappingLWLockTranche.name = "buffer_mapping";
-   BufMappingLWLockTranche.array_base = MainLWLockArray + NUM_INDIVIDUAL_LWLOCKS;
-   BufMappingLWLockTranche.array_stride = sizeof(LWLockPadded);
-   LWLockRegisterTranche(LWTRANCHE_BUFFER_MAPPING, &BufMappingLWLockTranche);
-
-   LockManagerLWLockTranche.name = "lock_manager";
-   LockManagerLWLockTranche.array_base = MainLWLockArray + NUM_INDIVIDUAL_LWLOCKS +
-       NUM_BUFFER_PARTITIONS;
-   LockManagerLWLockTranche.array_stride = sizeof(LWLockPadded);
-   LWLockRegisterTranche(LWTRANCHE_LOCK_MANAGER, &LockManagerLWLockTranche);
-
-   PredicateLockManagerLWLockTranche.name = "predicate_lock_manager";
-   PredicateLockManagerLWLockTranche.array_base = MainLWLockArray + NUM_INDIVIDUAL_LWLOCKS +
-       NUM_BUFFER_PARTITIONS + NUM_LOCK_PARTITIONS;
-   PredicateLockManagerLWLockTranche.array_stride = sizeof(LWLockPadded);
-   LWLockRegisterTranche(LWTRANCHE_PREDICATE_LOCK_MANAGER, &PredicateLockManagerLWLockTranche);
+   LWLockRegisterTranche(LWTRANCHE_BUFFER_MAPPING, "buffer_mapping");
+   LWLockRegisterTranche(LWTRANCHE_LOCK_MANAGER, "lock_manager");
+   LWLockRegisterTranche(LWTRANCHE_PREDICATE_LOCK_MANAGER,
+                         "predicate_lock_manager");
 
    /* Register named tranches. */
    for (i = 0; i < NamedLWLockTrancheRequests; i++)
        LWLockRegisterTranche(NamedLWLockTrancheArray[i].trancheId,
-                             &NamedLWLockTrancheArray[i].lwLockTranche);
+                             NamedLWLockTrancheArray[i].trancheName);
 }
 
 /*
@@ -633,7 +586,7 @@ LWLockNewTrancheId(void)
  * (TopMemoryContext, static variable, or similar).
  */
 void
-LWLockRegisterTranche(int tranche_id, LWLockTranche *tranche)
+LWLockRegisterTranche(int tranche_id, char *tranche_name)
 {
    Assert(LWLockTrancheArray != NULL);
 
@@ -645,15 +598,14 @@ LWLockRegisterTranche(int tranche_id, LWLockTranche *tranche)
        while (i <= tranche_id)
            i *= 2;
 
-       LWLockTrancheArray = (LWLockTranche **)
-           repalloc(LWLockTrancheArray,
-                    i * sizeof(LWLockTranche *));
+       LWLockTrancheArray = (char **)
+           repalloc(LWLockTrancheArray, i * sizeof(char *));
        LWLockTranchesAllocated = i;
        while (j < LWLockTranchesAllocated)
            LWLockTrancheArray[j++] = NULL;
    }
 
-   LWLockTrancheArray[tranche_id] = tranche;
+   LWLockTrancheArray[tranche_id] = tranche_name;
 }
 
 /*
@@ -729,12 +681,7 @@ LWLockInitialize(LWLock *lock, int tranche_id)
 static inline void
 LWLockReportWaitStart(LWLock *lock)
 {
-   int         lockId = T_ID(lock);
-
-   if (lock->tranche == 0)
-       pgstat_report_wait_start(PG_WAIT_LWLOCK_NAMED | (uint16) lockId);
-   else
-       pgstat_report_wait_start(PG_WAIT_LWLOCK_TRANCHE | lock->tranche);
+   pgstat_report_wait_start(PG_WAIT_LWLOCK | lock->tranche);
 }
 
 /*
@@ -752,10 +699,7 @@ LWLockReportWaitEnd(void)
 const char *
 GetLWLockIdentifier(uint32 classId, uint16 eventId)
 {
-   if (classId == PG_WAIT_LWLOCK_NAMED)
-       return MainLWLockNames[eventId];
-
-   Assert(classId == PG_WAIT_LWLOCK_TRANCHE);
+   Assert(classId == PG_WAIT_LWLOCK);
 
    /*
     * It is quite possible that user has registered tranche in one of the
@@ -763,10 +707,10 @@ GetLWLockIdentifier(uint32 classId, uint16 eventId)
     * all of them, so we can't assume the tranche is registered here.
     */
    if (eventId >= LWLockTranchesAllocated ||
-       LWLockTrancheArray[eventId]->name == NULL)
+       LWLockTrancheArray[eventId] == NULL)
        return "extension";
 
-   return LWLockTrancheArray[eventId]->name;
+   return LWLockTrancheArray[eventId];
 }
 
 /*
@@ -1279,7 +1223,7 @@ LWLockAcquire(LWLock *lock, LWLockMode mode)
 #endif
 
        LWLockReportWaitStart(lock);
-       TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), T_ID(lock), mode);
+       TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), mode);
 
        for (;;)
        {
@@ -1301,7 +1245,7 @@ LWLockAcquire(LWLock *lock, LWLockMode mode)
        }
 #endif
 
-       TRACE_POSTGRESQL_LWLOCK_WAIT_DONE(T_NAME(lock), T_ID(lock), mode);
+       TRACE_POSTGRESQL_LWLOCK_WAIT_DONE(T_NAME(lock), mode);
        LWLockReportWaitEnd();
 
        LOG_LWDEBUG("LWLockAcquire", lock, "awakened");
@@ -1310,7 +1254,7 @@ LWLockAcquire(LWLock *lock, LWLockMode mode)
        result = false;
    }
 
-   TRACE_POSTGRESQL_LWLOCK_ACQUIRE(T_NAME(lock), T_ID(lock), mode);
+   TRACE_POSTGRESQL_LWLOCK_ACQUIRE(T_NAME(lock), mode);
 
    /* Add lock to list of locks held by this backend */
    held_lwlocks[num_held_lwlocks].lock = lock;
@@ -1361,14 +1305,14 @@ LWLockConditionalAcquire(LWLock *lock, LWLockMode mode)
        RESUME_INTERRUPTS();
 
        LOG_LWDEBUG("LWLockConditionalAcquire", lock, "failed");
-       TRACE_POSTGRESQL_LWLOCK_CONDACQUIRE_FAIL(T_NAME(lock), T_ID(lock), mode);
+       TRACE_POSTGRESQL_LWLOCK_CONDACQUIRE_FAIL(T_NAME(lock), mode);
    }
    else
    {
        /* Add lock to list of locks held by this backend */
        held_lwlocks[num_held_lwlocks].lock = lock;
        held_lwlocks[num_held_lwlocks++].mode = mode;
-       TRACE_POSTGRESQL_LWLOCK_CONDACQUIRE(T_NAME(lock), T_ID(lock), mode);
+       TRACE_POSTGRESQL_LWLOCK_CONDACQUIRE(T_NAME(lock), mode);
    }
    return !mustwait;
 }
@@ -1440,7 +1384,7 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode)
 #endif
 
            LWLockReportWaitStart(lock);
-           TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), T_ID(lock), mode);
+           TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), mode);
 
            for (;;)
            {
@@ -1458,7 +1402,7 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode)
                Assert(nwaiters < MAX_BACKENDS);
            }
 #endif
-           TRACE_POSTGRESQL_LWLOCK_WAIT_DONE(T_NAME(lock), T_ID(lock), mode);
+           TRACE_POSTGRESQL_LWLOCK_WAIT_DONE(T_NAME(lock), mode);
            LWLockReportWaitEnd();
 
            LOG_LWDEBUG("LWLockAcquireOrWait", lock, "awakened");
@@ -1488,8 +1432,7 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode)
        /* Failed to get lock, so release interrupt holdoff */
        RESUME_INTERRUPTS();
        LOG_LWDEBUG("LWLockAcquireOrWait", lock, "failed");
-       TRACE_POSTGRESQL_LWLOCK_ACQUIRE_OR_WAIT_FAIL(T_NAME(lock), T_ID(lock),
-                                                    mode);
+       TRACE_POSTGRESQL_LWLOCK_ACQUIRE_OR_WAIT_FAIL(T_NAME(lock), mode);
    }
    else
    {
@@ -1497,7 +1440,7 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode)
        /* Add lock to list of locks held by this backend */
        held_lwlocks[num_held_lwlocks].lock = lock;
        held_lwlocks[num_held_lwlocks++].mode = mode;
-       TRACE_POSTGRESQL_LWLOCK_ACQUIRE_OR_WAIT(T_NAME(lock), T_ID(lock), mode);
+       TRACE_POSTGRESQL_LWLOCK_ACQUIRE_OR_WAIT(T_NAME(lock), mode);
    }
 
    return !mustwait;
@@ -1657,8 +1600,7 @@ LWLockWaitForVar(LWLock *lock, uint64 *valptr, uint64 oldval, uint64 *newval)
 #endif
 
        LWLockReportWaitStart(lock);
-       TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), T_ID(lock),
-                                          LW_EXCLUSIVE);
+       TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), LW_EXCLUSIVE);
 
        for (;;)
        {
@@ -1677,8 +1619,7 @@ LWLockWaitForVar(LWLock *lock, uint64 *valptr, uint64 oldval, uint64 *newval)
        }
 #endif
 
-       TRACE_POSTGRESQL_LWLOCK_WAIT_DONE(T_NAME(lock), T_ID(lock),
-                                         LW_EXCLUSIVE);
+       TRACE_POSTGRESQL_LWLOCK_WAIT_DONE(T_NAME(lock), LW_EXCLUSIVE);
        LWLockReportWaitEnd();
 
        LOG_LWDEBUG("LWLockWaitForVar", lock, "awakened");
@@ -1686,7 +1627,7 @@ LWLockWaitForVar(LWLock *lock, uint64 *valptr, uint64 oldval, uint64 *newval)
        /* Now loop back and check the status of the lock again. */
    }
 
-   TRACE_POSTGRESQL_LWLOCK_ACQUIRE(T_NAME(lock), T_ID(lock), LW_EXCLUSIVE);
+   TRACE_POSTGRESQL_LWLOCK_ACQUIRE(T_NAME(lock), LW_EXCLUSIVE);
 
    /*
     * Fix the process wait semaphore's count for any absorbed wakeups.
@@ -1784,7 +1725,7 @@ LWLockRelease(LWLock *lock)
            break;
 
    if (i < 0)
-       elog(ERROR, "lock %s %d is not held", T_NAME(lock), T_ID(lock));
+       elog(ERROR, "lock %s is not held", T_NAME(lock));
 
    mode = held_lwlocks[i].mode;
 
@@ -1829,7 +1770,7 @@ LWLockRelease(LWLock *lock)
        LWLockWakeup(lock);
    }
 
-   TRACE_POSTGRESQL_LWLOCK_RELEASE(T_NAME(lock), T_ID(lock));
+   TRACE_POSTGRESQL_LWLOCK_RELEASE(T_NAME(lock));
 
    /*
     * Now okay to allow cancel/die interrupts.
index abe3f1a63d19729c3b15bd0dadc41e365080e1b1..988a2970b2d77121269c8ec7ddb3f5e91062ee76 100644 (file)
@@ -362,9 +362,6 @@ struct dsa_area
    /* Pointer to the control object in shared memory. */
    dsa_area_control *control;
 
-   /* The lock tranche for this process. */
-   LWLockTranche lwlock_tranche;
-
    /* Has the mapping been pinned? */
    bool        mapping_pinned;
 
@@ -1207,10 +1204,8 @@ create_internal(void *place, size_t size,
    area->mapping_pinned = false;
    memset(area->segment_maps, 0, sizeof(dsa_segment_map) * DSA_MAX_SEGMENTS);
    area->high_segment_index = 0;
-   area->lwlock_tranche.array_base = &area->control->pools[0];
-   area->lwlock_tranche.array_stride = sizeof(dsa_area_pool);
-   area->lwlock_tranche.name = control->lwlock_tranche_name;
-   LWLockRegisterTranche(control->lwlock_tranche_id, &area->lwlock_tranche);
+   LWLockRegisterTranche(control->lwlock_tranche_id,
+                         control->lwlock_tranche_name);
    LWLockInitialize(&control->lock, control->lwlock_tranche_id);
    for (i = 0; i < DSA_NUM_SIZE_CLASSES; ++i)
        LWLockInitialize(DSA_SCLASS_LOCK(area, i),
@@ -1267,10 +1262,8 @@ attach_internal(void *place, dsm_segment *segment, dsa_handle handle)
    memset(&area->segment_maps[0], 0,
           sizeof(dsa_segment_map) * DSA_MAX_SEGMENTS);
    area->high_segment_index = 0;
-   area->lwlock_tranche.array_base = &area->control->pools[0];
-   area->lwlock_tranche.array_stride = sizeof(dsa_area_pool);
-   area->lwlock_tranche.name = control->lwlock_tranche_name;
-   LWLockRegisterTranche(control->lwlock_tranche_id, &area->lwlock_tranche);
+   LWLockRegisterTranche(control->lwlock_tranche_id,
+                         control->lwlock_tranche_name);
 
    /* Set up the segment map for this process's mapping. */
    segment_map = &area->segment_maps[0];
index 2f92dfa9adb00e921bee1d4b32022b52bb36f8d5..adcebe2e055b24e4a5f4374c66496fae6861c560 100644 (file)
@@ -28,14 +28,14 @@ provider postgresql {
    probe transaction__commit(LocalTransactionId);
    probe transaction__abort(LocalTransactionId);
 
-   probe lwlock__acquire(const char *, int, LWLockMode);
-   probe lwlock__release(const char *, int);
-   probe lwlock__wait__start(const char *, int, LWLockMode);
-   probe lwlock__wait__done(const char *, int, LWLockMode);
-   probe lwlock__condacquire(const char *, int, LWLockMode);
-   probe lwlock__condacquire__fail(const char *, int, LWLockMode);
-   probe lwlock__acquire__or__wait(const char *, int, LWLockMode);
-   probe lwlock__acquire__or__wait__fail(const char *, int, LWLockMode);
+   probe lwlock__acquire(const char *, LWLockMode);
+   probe lwlock__release(const char *);
+   probe lwlock__wait__start(const char *, LWLockMode);
+   probe lwlock__wait__done(const char *, LWLockMode);
+   probe lwlock__condacquire(const char *, LWLockMode);
+   probe lwlock__condacquire__fail(const char *, LWLockMode);
+   probe lwlock__acquire__or__wait(const char *, LWLockMode);
+   probe lwlock__acquire__or__wait__fail(const char *, LWLockMode);
 
    probe lock__wait__start(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, LOCKMODE);
    probe lock__wait__done(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, LOCKMODE);
index 5fcebc52fba4a38e694798608cc3f4ccc4964235..ca8ab7ba5248d5aebaf32688f1ea1d144de2adcc 100644 (file)
@@ -104,7 +104,6 @@ typedef struct SlruSharedData
 
    /* LWLocks */
    int         lwlock_tranche_id;
-   LWLockTranche lwlock_tranche;
    char        lwlock_tranche_name[SLRU_MAX_NAME_LENGTH];
    LWLockPadded *buffer_locks;
 } SlruSharedData;
index 152ff0620852133323edda179e17539893fbe539..282f8aeccd2ebaea771d813fbc0401903c891a78 100644 (file)
@@ -715,8 +715,7 @@ typedef enum BackendState
  * Wait Classes
  * ----------
  */
-#define PG_WAIT_LWLOCK_NAMED       0x01000000U
-#define PG_WAIT_LWLOCK_TRANCHE     0x02000000U
+#define PG_WAIT_LWLOCK             0x01000000U
 #define PG_WAIT_LOCK               0x03000000U
 #define PG_WAIT_BUFFER_PIN         0x04000000U
 #define PG_WAIT_ACTIVITY           0x05000000U
index 9a2d86975cad72971c07764bd786fc893a11b07a..db1c687e21e8398bb201666b833c5eb6991d82e5 100644 (file)
 
 struct PGPROC;
 
-/*
- * Prior to PostgreSQL 9.4, every lightweight lock in the system was stored
- * in a single array.  For convenience and for compatibility with past
- * releases, we still have a main array, but it's now also permissible to
- * store LWLocks elsewhere in the main shared memory segment or in a dynamic
- * shared memory segment.  Each array of lwlocks forms a separate "tranche".
- *
- * It's occasionally necessary to identify a particular LWLock "by name"; e.g.
- * because we wish to report the lock to dtrace.  We could store a name or
- * other identifying information in the lock itself, but since it's common
- * to have many nearly-identical locks (e.g. one per buffer) this would end
- * up wasting significant amounts of memory.  Instead, each lwlock stores a
- * tranche ID which tells us which array it's part of.  Based on that, we can
- * figure out where the lwlock lies within the array using the data structure
- * shown below; the lock is then identified based on the tranche name and
- * computed array index.  We need the array stride because the array might not
- * be an array of lwlocks, but rather some larger data structure that includes
- * one or more lwlocks per element.
- */
-typedef struct LWLockTranche
-{
-   const char *name;
-   void       *array_base;
-   Size        array_stride;
-} LWLockTranche;
-
 /*
  * Code outside of lwlock.c should not manipulate the contents of this
  * structure directly, but we have to declare it here to allow LWLocks to be
@@ -118,8 +92,8 @@ extern char *MainLWLockNames[];
 /* struct for storing named tranche information */
 typedef struct NamedLWLockTranche
 {
-   LWLockTranche lwLockTranche;
    int         trancheId;
+   char       *trancheName;
 } NamedLWLockTranche;
 
 extern PGDLLIMPORT NamedLWLockTranche *NamedLWLockTrancheArray;
@@ -199,9 +173,9 @@ 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 appropriate
- * metadata.  Finally, LWLockInitialize should be called just once per lwlock,
- * passing the tranche ID as an argument.
+ * 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
@@ -209,17 +183,18 @@ extern LWLockPadded *GetNamedLWLockTranche(const char *tranche_name);
  * registration in the main shared memory segment wouldn't work for that case.
  */
 extern int LWLockNewTrancheId(void);
-extern void LWLockRegisterTranche(int tranche_id, LWLockTranche *tranche);
+extern void LWLockRegisterTranche(int tranche_id, char *tranche_name);
 extern void LWLockInitialize(LWLock *lock, int tranche_id);
 
 /*
- * We reserve a few predefined tranche IDs.  A call to LWLockNewTrancheId
- * will never return a value less than LWTRANCHE_FIRST_USER_DEFINED.
+ * Every tranche ID less than NUM_INDIVIDUAL_LWLOCKS is reserved; also,
+ * we reserve additional tranche IDs for builtin tranches not included in
+ * the set of individual LWLocks.  A call to LWLockNewTrancheId will never
+ * return a value less than LWTRANCHE_FIRST_USER_DEFINED.
  */
 typedef enum BuiltinTrancheIds
 {
-   LWTRANCHE_MAIN,
-   LWTRANCHE_CLOG_BUFFERS,
+   LWTRANCHE_CLOG_BUFFERS = NUM_INDIVIDUAL_LWLOCKS,
    LWTRANCHE_COMMITTS_BUFFERS,
    LWTRANCHE_SUBTRANS_BUFFERS,
    LWTRANCHE_MXACTOFFSET_BUFFERS,