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 : }
|