LCOV - code coverage report
Current view: top level - src/backend/utils/activity - pgstat_lock.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 92.2 % 64 59
Test Date: 2026-03-25 05:16:10 Functions: 87.5 % 8 7
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* -------------------------------------------------------------------------
       2              :  *
       3              :  * pgstat_lock.c
       4              :  *    Implementation of lock statistics.
       5              :  *
       6              :  * This file contains the implementation of lock statistics.  It is kept
       7              :  * separate from pgstat.c to enforce the line between the statistics
       8              :  * access / storage implementation and the details about individual types
       9              :  * of statistics.
      10              :  *
      11              :  * Copyright (c) 2021-2026, PostgreSQL Global Development Group
      12              :  *
      13              :  * IDENTIFICATION
      14              :  *    src/backend/utils/activity/pgstat_lock.c
      15              :  * -------------------------------------------------------------------------
      16              :  */
      17              : 
      18              : #include "postgres.h"
      19              : 
      20              : #include "utils/pgstat_internal.h"
      21              : 
      22              : static PgStat_PendingLock PendingLockStats;
      23              : static bool have_lockstats = false;
      24              : 
      25              : PgStat_Lock *
      26            8 : pgstat_fetch_stat_lock(void)
      27              : {
      28            8 :     pgstat_snapshot_fixed(PGSTAT_KIND_LOCK);
      29              : 
      30            8 :     return &pgStatLocal.snapshot.lock;
      31              : }
      32              : 
      33              : /*
      34              :  * Simpler wrapper of pgstat_lock_flush_cb()
      35              :  */
      36              : void
      37            0 : pgstat_lock_flush(bool nowait)
      38              : {
      39            0 :     (void) pgstat_lock_flush_cb(nowait);
      40            0 : }
      41              : 
      42              : /*
      43              :  * Flush out locally pending lock statistics
      44              :  *
      45              :  * If no stats have been recorded, this function returns false.
      46              :  *
      47              :  * If nowait is true, this function returns true if the lock could not be
      48              :  * acquired. Otherwise, return false.
      49              :  */
      50              : bool
      51        39215 : pgstat_lock_flush_cb(bool nowait)
      52              : {
      53              :     LWLock     *lcktype_lock;
      54              :     PgStat_LockEntry *lck_shstats;
      55        39215 :     bool        lock_not_acquired = false;
      56              : 
      57        39215 :     if (!have_lockstats)
      58        38905 :         return false;
      59              : 
      60         4030 :     for (int i = 0; i <= LOCKTAG_LAST_TYPE; i++)
      61              :     {
      62         3720 :         lcktype_lock = &pgStatLocal.shmem->lock.locks[i];
      63         3720 :         lck_shstats =
      64         3720 :             &pgStatLocal.shmem->lock.stats.stats[i];
      65              : 
      66         3720 :         if (!nowait)
      67         3396 :             LWLockAcquire(lcktype_lock, LW_EXCLUSIVE);
      68          324 :         else if (!LWLockConditionalAcquire(lcktype_lock, LW_EXCLUSIVE))
      69              :         {
      70            0 :             lock_not_acquired = true;
      71            0 :             continue;
      72              :         }
      73              : 
      74              : #define LOCKSTAT_ACC(fld) \
      75              :     (lck_shstats->fld += PendingLockStats.stats[i].fld)
      76         3720 :         LOCKSTAT_ACC(waits);
      77         3720 :         LOCKSTAT_ACC(wait_time);
      78         3720 :         LOCKSTAT_ACC(fastpath_exceeded);
      79              : #undef LOCKSTAT_ACC
      80              : 
      81         3720 :         LWLockRelease(lcktype_lock);
      82              :     }
      83              : 
      84          310 :     memset(&PendingLockStats, 0, sizeof(PendingLockStats));
      85              : 
      86          310 :     have_lockstats = false;
      87              : 
      88          310 :     return lock_not_acquired;
      89              : }
      90              : 
      91              : 
      92              : void
      93         1180 : pgstat_lock_init_shmem_cb(void *stats)
      94              : {
      95         1180 :     PgStatShared_Lock *stat_shmem = (PgStatShared_Lock *) stats;
      96              : 
      97        15340 :     for (int i = 0; i <= LOCKTAG_LAST_TYPE; i++)
      98        14160 :         LWLockInitialize(&stat_shmem->locks[i], LWTRANCHE_PGSTATS_DATA);
      99         1180 : }
     100              : 
     101              : void
     102          242 : pgstat_lock_reset_all_cb(TimestampTz ts)
     103              : {
     104         3146 :     for (int i = 0; i <= LOCKTAG_LAST_TYPE; i++)
     105              :     {
     106         2904 :         LWLock     *lcktype_lock = &pgStatLocal.shmem->lock.locks[i];
     107         2904 :         PgStat_LockEntry *lck_shstats = &pgStatLocal.shmem->lock.stats.stats[i];
     108              : 
     109         2904 :         LWLockAcquire(lcktype_lock, LW_EXCLUSIVE);
     110              : 
     111              :         /*
     112              :          * Use the lock in the first lock type PgStat_LockEntry to protect the
     113              :          * reset timestamp as well.
     114              :          */
     115         2904 :         if (i == 0)
     116          242 :             pgStatLocal.shmem->lock.stats.stat_reset_timestamp = ts;
     117              : 
     118         2904 :         memset(lck_shstats, 0, sizeof(*lck_shstats));
     119         2904 :         LWLockRelease(lcktype_lock);
     120              :     }
     121          242 : }
     122              : 
     123              : void
     124          757 : pgstat_lock_snapshot_cb(void)
     125              : {
     126         9841 :     for (int i = 0; i <= LOCKTAG_LAST_TYPE; i++)
     127              :     {
     128         9084 :         LWLock     *lcktype_lock = &pgStatLocal.shmem->lock.locks[i];
     129         9084 :         PgStat_LockEntry *lck_shstats = &pgStatLocal.shmem->lock.stats.stats[i];
     130         9084 :         PgStat_LockEntry *lck_snap = &pgStatLocal.snapshot.lock.stats[i];
     131              : 
     132         9084 :         LWLockAcquire(lcktype_lock, LW_SHARED);
     133              : 
     134              :         /*
     135              :          * Use the lock in the first lock type PgStat_LockEntry to protect the
     136              :          * reset timestamp as well.
     137              :          */
     138         9084 :         if (i == 0)
     139          757 :             pgStatLocal.snapshot.lock.stat_reset_timestamp =
     140          757 :                 pgStatLocal.shmem->lock.stats.stat_reset_timestamp;
     141              : 
     142              :         /* using struct assignment due to better type safety */
     143         9084 :         *lck_snap = *lck_shstats;
     144         9084 :         LWLockRelease(lcktype_lock);
     145              :     }
     146          757 : }
     147              : 
     148              : /*
     149              :  * Increment counter for lock not acquired with the fast-path, per lock
     150              :  * type, due to the fast-path slot limit reached.
     151              :  *
     152              :  * Note: This function should not be called in performance-sensitive paths,
     153              :  * like lock acquisitions.
     154              :  */
     155              : void
     156       254391 : pgstat_count_lock_fastpath_exceeded(uint8 locktag_type)
     157              : {
     158              :     Assert(locktag_type <= LOCKTAG_LAST_TYPE);
     159       254391 :     PendingLockStats.stats[locktag_type].fastpath_exceeded++;
     160       254391 :     have_lockstats = true;
     161       254391 :     pgstat_report_fixed = true;
     162       254391 : }
     163              : 
     164              : /*
     165              :  * Increment the number of waits and wait time, per lock type.
     166              :  *
     167              :  * Note: This function should not be called in performance-sensitive paths,
     168              :  * like lock acquisitions.
     169              :  */
     170              : void
     171           25 : pgstat_count_lock_waits(uint8 locktag_type, long msecs)
     172              : {
     173              :     Assert(locktag_type <= LOCKTAG_LAST_TYPE);
     174           25 :     PendingLockStats.stats[locktag_type].waits++;
     175           25 :     PendingLockStats.stats[locktag_type].wait_time += (PgStat_Counter) msecs;
     176           25 :     have_lockstats = true;
     177           25 :     pgstat_report_fixed = true;
     178           25 : }
        

Generated by: LCOV version 2.0-1