Age Owner Branch data TLA 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 *
42 michael@paquier.xyz 26 :GNC 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
42 michael@paquier.xyz 37 :UNC 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
42 michael@paquier.xyz 51 :GNC 39143 : pgstat_lock_flush_cb(bool nowait)
52 : : {
53 : : LWLock *lckstat_lock;
54 : : PgStatShared_Lock *shstats;
55 : :
56 [ + + ]: 39143 : if (!have_lockstats)
57 : 38834 : return false;
58 : :
29 59 : 309 : shstats = &pgStatLocal.shmem->lock;
60 : 309 : lckstat_lock = &shstats->lock;
61 : :
62 [ + + ]: 309 : if (!nowait)
63 : 286 : LWLockAcquire(lckstat_lock, LW_EXCLUSIVE);
64 [ - + ]: 23 : else if (!LWLockConditionalAcquire(lckstat_lock, LW_EXCLUSIVE))
29 michael@paquier.xyz 65 :UNC 0 : return true;
66 : :
42 michael@paquier.xyz 67 [ + + ]:GNC 4017 : 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 : 3708 : LOCKSTAT_ACC(waits);
72 : 3708 : LOCKSTAT_ACC(wait_time);
73 : 3708 : LOCKSTAT_ACC(fastpath_exceeded);
74 : : #undef LOCKSTAT_ACC
75 : : }
76 : :
29 77 : 309 : LWLockRelease(lckstat_lock);
78 : :
79 : 309 : memset(&PendingLockStats, 0, sizeof(PendingLockStats));
42 80 : 309 : have_lockstats = false;
81 : :
29 82 : 309 : return false;
83 : : }
84 : :
85 : : void
42 86 : 1241 : pgstat_lock_init_shmem_cb(void *stats)
87 : : {
88 : 1241 : PgStatShared_Lock *stat_shmem = (PgStatShared_Lock *) stats;
89 : :
29 90 : 1241 : LWLockInitialize(&stat_shmem->lock, LWTRANCHE_PGSTATS_DATA);
42 91 : 1241 : }
92 : :
93 : : void
94 : 258 : pgstat_lock_reset_all_cb(TimestampTz ts)
95 : : {
29 96 : 258 : LWLock *lckstat_lock = &pgStatLocal.shmem->lock.lock;
97 : :
98 : 258 : LWLockAcquire(lckstat_lock, LW_EXCLUSIVE);
99 : :
100 : 258 : pgStatLocal.shmem->lock.stats.stat_reset_timestamp = ts;
101 : :
102 : 258 : memset(pgStatLocal.shmem->lock.stats.stats, 0,
103 : : sizeof(pgStatLocal.shmem->lock.stats.stats));
104 : :
105 : 258 : LWLockRelease(lckstat_lock);
42 106 : 258 : }
107 : :
108 : : void
109 : 808 : pgstat_lock_snapshot_cb(void)
110 : : {
29 111 : 808 : LWLock *lckstat_lock = &pgStatLocal.shmem->lock.lock;
112 : :
113 : 808 : LWLockAcquire(lckstat_lock, LW_SHARED);
114 : :
115 : 808 : pgStatLocal.snapshot.lock = pgStatLocal.shmem->lock.stats;
116 : :
117 : 808 : LWLockRelease(lckstat_lock);
42 118 : 808 : }
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 : 108926 : pgstat_count_lock_fastpath_exceeded(uint8 locktag_type)
129 : : {
130 [ - + ]: 108926 : Assert(locktag_type <= LOCKTAG_LAST_TYPE);
131 : 108926 : PendingLockStats.stats[locktag_type].fastpath_exceeded++;
132 : 108926 : have_lockstats = true;
133 : 108926 : pgstat_report_fixed = true;
134 : 108926 : }
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 : 38 : pgstat_count_lock_waits(uint8 locktag_type, long msecs)
144 : : {
145 [ - + ]: 38 : Assert(locktag_type <= LOCKTAG_LAST_TYPE);
146 : 38 : PendingLockStats.stats[locktag_type].waits++;
147 : 38 : PendingLockStats.stats[locktag_type].wait_time += (PgStat_Counter) msecs;
148 : 38 : have_lockstats = true;
149 : 38 : pgstat_report_fixed = true;
150 : 38 : }
|