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 % 51 47
Test Date: 2026-04-07 14:16:30 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           12 : pgstat_fetch_stat_lock(void)
      27              : {
      28           12 :     pgstat_snapshot_fixed(PGSTAT_KIND_LOCK);
      29              : 
      30           12 :     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        39328 : pgstat_lock_flush_cb(bool nowait)
      52              : {
      53              :     LWLock     *lckstat_lock;
      54              :     PgStatShared_Lock *shstats;
      55              : 
      56        39328 :     if (!have_lockstats)
      57        39026 :         return false;
      58              : 
      59          302 :     shstats = &pgStatLocal.shmem->lock;
      60          302 :     lckstat_lock = &shstats->lock;
      61              : 
      62          302 :     if (!nowait)
      63          287 :         LWLockAcquire(lckstat_lock, LW_EXCLUSIVE);
      64           15 :     else if (!LWLockConditionalAcquire(lckstat_lock, LW_EXCLUSIVE))
      65            0 :         return true;
      66              : 
      67         3926 :     for (int i = 0; i <= LOCKTAG_LAST_TYPE; i++)
      68              :     {
      69              : #define LOCKSTAT_ACC(fld) \
      70              :     (shstats->stats.stats[i].fld += PendingLockStats.stats[i].fld)
      71         3624 :         LOCKSTAT_ACC(waits);
      72         3624 :         LOCKSTAT_ACC(wait_time);
      73         3624 :         LOCKSTAT_ACC(fastpath_exceeded);
      74              : #undef LOCKSTAT_ACC
      75              :     }
      76              : 
      77          302 :     LWLockRelease(lckstat_lock);
      78              : 
      79          302 :     memset(&PendingLockStats, 0, sizeof(PendingLockStats));
      80          302 :     have_lockstats = false;
      81              : 
      82          302 :     return false;
      83              : }
      84              : 
      85              : void
      86         1231 : pgstat_lock_init_shmem_cb(void *stats)
      87              : {
      88         1231 :     PgStatShared_Lock *stat_shmem = (PgStatShared_Lock *) stats;
      89              : 
      90         1231 :     LWLockInitialize(&stat_shmem->lock, LWTRANCHE_PGSTATS_DATA);
      91         1231 : }
      92              : 
      93              : void
      94          254 : pgstat_lock_reset_all_cb(TimestampTz ts)
      95              : {
      96          254 :     LWLock     *lckstat_lock = &pgStatLocal.shmem->lock.lock;
      97              : 
      98          254 :     LWLockAcquire(lckstat_lock, LW_EXCLUSIVE);
      99              : 
     100          254 :     pgStatLocal.shmem->lock.stats.stat_reset_timestamp = ts;
     101              : 
     102          254 :     memset(pgStatLocal.shmem->lock.stats.stats, 0,
     103              :            sizeof(pgStatLocal.shmem->lock.stats.stats));
     104              : 
     105          254 :     LWLockRelease(lckstat_lock);
     106          254 : }
     107              : 
     108              : void
     109          799 : pgstat_lock_snapshot_cb(void)
     110              : {
     111          799 :     LWLock     *lckstat_lock = &pgStatLocal.shmem->lock.lock;
     112              : 
     113          799 :     LWLockAcquire(lckstat_lock, LW_SHARED);
     114              : 
     115          799 :     pgStatLocal.snapshot.lock = pgStatLocal.shmem->lock.stats;
     116              : 
     117          799 :     LWLockRelease(lckstat_lock);
     118          799 : }
     119              : 
     120              : /*
     121              :  * Increment counter for lock not acquired with the fast-path, per lock
     122              :  * type, due to the fast-path slot limit reached.
     123              :  *
     124              :  * Note: This function should not be called in performance-sensitive paths,
     125              :  * like lock acquisitions.
     126              :  */
     127              : void
     128       105121 : pgstat_count_lock_fastpath_exceeded(uint8 locktag_type)
     129              : {
     130              :     Assert(locktag_type <= LOCKTAG_LAST_TYPE);
     131       105121 :     PendingLockStats.stats[locktag_type].fastpath_exceeded++;
     132       105121 :     have_lockstats = true;
     133       105121 :     pgstat_report_fixed = true;
     134       105121 : }
     135              : 
     136              : /*
     137              :  * Increment the number of waits and wait time, per lock type.
     138              :  *
     139              :  * Note: This function should not be called in performance-sensitive paths,
     140              :  * like lock acquisitions.
     141              :  */
     142              : void
     143           30 : pgstat_count_lock_waits(uint8 locktag_type, long msecs)
     144              : {
     145              :     Assert(locktag_type <= LOCKTAG_LAST_TYPE);
     146           30 :     PendingLockStats.stats[locktag_type].waits++;
     147           30 :     PendingLockStats.stats[locktag_type].wait_time += (PgStat_Counter) msecs;
     148           30 :     have_lockstats = true;
     149           30 :     pgstat_report_fixed = true;
     150           30 : }
        

Generated by: LCOV version 2.0-1