Coverage Report

Created: 2026-08-14 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/backend/utils/activity/pgstat_lock.c
Line
Count
Source
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
pgstat_fetch_stat_lock(void)
27
0
{
28
0
  pgstat_snapshot_fixed(PGSTAT_KIND_LOCK);
29
30
0
  return &pgStatLocal.snapshot.lock;
31
0
}
32
33
/*
34
 * Simpler wrapper of pgstat_lock_flush_cb()
35
 */
36
void
37
pgstat_lock_flush(bool nowait)
38
0
{
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
pgstat_lock_flush_cb(bool nowait)
52
0
{
53
0
  LWLock     *lckstat_lock;
54
0
  PgStatShared_Lock *shstats;
55
56
0
  if (!have_lockstats)
57
0
    return false;
58
59
0
  shstats = &pgStatLocal.shmem->lock;
60
0
  lckstat_lock = &shstats->lock;
61
62
0
  if (!nowait)
63
0
    LWLockAcquire(lckstat_lock, LW_EXCLUSIVE);
64
0
  else if (!LWLockConditionalAcquire(lckstat_lock, LW_EXCLUSIVE))
65
0
    return true;
66
67
0
  for (int i = 0; i <= LOCKTAG_LAST_TYPE; i++)
68
0
  {
69
0
#define LOCKSTAT_ACC(fld) \
70
0
  (shstats->stats.stats[i].fld += PendingLockStats.stats[i].fld)
71
0
    LOCKSTAT_ACC(waits);
72
0
    LOCKSTAT_ACC(wait_time);
73
0
    LOCKSTAT_ACC(fastpath_exceeded);
74
0
#undef LOCKSTAT_ACC
75
0
  }
76
77
0
  LWLockRelease(lckstat_lock);
78
79
0
  memset(&PendingLockStats, 0, sizeof(PendingLockStats));
80
0
  have_lockstats = false;
81
82
0
  return false;
83
0
}
84
85
void
86
pgstat_lock_init_shmem_cb(void *stats)
87
0
{
88
0
  PgStatShared_Lock *stat_shmem = (PgStatShared_Lock *) stats;
89
90
0
  LWLockInitialize(&stat_shmem->lock, LWTRANCHE_PGSTATS_DATA);
91
0
}
92
93
void
94
pgstat_lock_reset_all_cb(TimestampTz ts)
95
0
{
96
0
  LWLock     *lckstat_lock = &pgStatLocal.shmem->lock.lock;
97
98
0
  LWLockAcquire(lckstat_lock, LW_EXCLUSIVE);
99
100
0
  pgStatLocal.shmem->lock.stats.stat_reset_timestamp = ts;
101
102
0
  memset(pgStatLocal.shmem->lock.stats.stats, 0,
103
0
       sizeof(pgStatLocal.shmem->lock.stats.stats));
104
105
0
  LWLockRelease(lckstat_lock);
106
0
}
107
108
void
109
pgstat_lock_snapshot_cb(void)
110
0
{
111
0
  LWLock     *lckstat_lock = &pgStatLocal.shmem->lock.lock;
112
113
0
  LWLockAcquire(lckstat_lock, LW_SHARED);
114
115
0
  pgStatLocal.snapshot.lock = pgStatLocal.shmem->lock.stats;
116
117
0
  LWLockRelease(lckstat_lock);
118
0
}
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
pgstat_count_lock_fastpath_exceeded(uint8 locktag_type)
129
0
{
130
0
  Assert(locktag_type <= LOCKTAG_LAST_TYPE);
131
0
  PendingLockStats.stats[locktag_type].fastpath_exceeded++;
132
0
  have_lockstats = true;
133
0
  pgstat_report_fixed = true;
134
135
0
  pgstat_count_backend_lock_fastpath_exceeded(locktag_type);
136
0
}
137
138
/*
139
 * Increment the number of waits and wait time, per lock type.
140
 *
141
 * Note: This function should not be called in performance-sensitive paths,
142
 * like lock acquisitions.
143
 */
144
void
145
pgstat_count_lock_waits(uint8 locktag_type, PgStat_Counter usecs)
146
0
{
147
0
  Assert(locktag_type <= LOCKTAG_LAST_TYPE);
148
0
  PendingLockStats.stats[locktag_type].waits++;
149
0
  PendingLockStats.stats[locktag_type].wait_time += usecs;
150
0
  have_lockstats = true;
151
0
  pgstat_report_fixed = true;
152
153
0
  pgstat_count_backend_lock_waits(locktag_type, usecs);
154
0
}