Branch data 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 : 40118 : pgstat_lock_flush_cb(bool nowait)
52 : : {
53 : : LWLock *lckstat_lock;
54 : : PgStatShared_Lock *shstats;
55 : :
56 [ + + ]: 40118 : if (!have_lockstats)
57 : 39887 : return false;
58 : :
59 : 231 : shstats = &pgStatLocal.shmem->lock;
60 : 231 : lckstat_lock = &shstats->lock;
61 : :
62 [ + + ]: 231 : if (!nowait)
63 : 217 : LWLockAcquire(lckstat_lock, LW_EXCLUSIVE);
64 [ - + ]: 14 : else if (!LWLockConditionalAcquire(lckstat_lock, LW_EXCLUSIVE))
65 : 0 : return true;
66 : :
67 [ + + ]: 3003 : 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 : 2772 : LOCKSTAT_ACC(waits);
72 : 2772 : LOCKSTAT_ACC(wait_time);
73 : 2772 : LOCKSTAT_ACC(fastpath_exceeded);
74 : : #undef LOCKSTAT_ACC
75 : : }
76 : :
77 : 231 : LWLockRelease(lckstat_lock);
78 : :
79 : 231 : memset(&PendingLockStats, 0, sizeof(PendingLockStats));
80 : 231 : have_lockstats = false;
81 : :
82 : 231 : return false;
83 : : }
84 : :
85 : : void
86 : 1246 : pgstat_lock_init_shmem_cb(void *stats)
87 : : {
88 : 1246 : PgStatShared_Lock *stat_shmem = (PgStatShared_Lock *) stats;
89 : :
90 : 1246 : LWLockInitialize(&stat_shmem->lock, LWTRANCHE_PGSTATS_DATA);
91 : 1246 : }
92 : :
93 : : void
94 : 261 : pgstat_lock_reset_all_cb(TimestampTz ts)
95 : : {
96 : 261 : LWLock *lckstat_lock = &pgStatLocal.shmem->lock.lock;
97 : :
98 : 261 : LWLockAcquire(lckstat_lock, LW_EXCLUSIVE);
99 : :
100 : 261 : pgStatLocal.shmem->lock.stats.stat_reset_timestamp = ts;
101 : :
102 : 261 : memset(pgStatLocal.shmem->lock.stats.stats, 0,
103 : : sizeof(pgStatLocal.shmem->lock.stats.stats));
104 : :
105 : 261 : LWLockRelease(lckstat_lock);
106 : 261 : }
107 : :
108 : : void
109 : 809 : pgstat_lock_snapshot_cb(void)
110 : : {
111 : 809 : LWLock *lckstat_lock = &pgStatLocal.shmem->lock.lock;
112 : :
113 : 809 : LWLockAcquire(lckstat_lock, LW_SHARED);
114 : :
115 : 809 : pgStatLocal.snapshot.lock = pgStatLocal.shmem->lock.stats;
116 : :
117 : 809 : LWLockRelease(lckstat_lock);
118 : 809 : }
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 : 89507 : pgstat_count_lock_fastpath_exceeded(uint8 locktag_type)
129 : : {
130 : : Assert(locktag_type <= LOCKTAG_LAST_TYPE);
131 : 89507 : PendingLockStats.stats[locktag_type].fastpath_exceeded++;
132 : 89507 : have_lockstats = true;
133 : 89507 : pgstat_report_fixed = true;
134 : :
135 : 89507 : pgstat_count_backend_lock_fastpath_exceeded(locktag_type);
136 : 89507 : }
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 : 27 : pgstat_count_lock_waits(uint8 locktag_type, PgStat_Counter usecs)
146 : : {
147 : : Assert(locktag_type <= LOCKTAG_LAST_TYPE);
148 : 27 : PendingLockStats.stats[locktag_type].waits++;
149 : 27 : PendingLockStats.stats[locktag_type].wait_time += usecs;
150 : 27 : have_lockstats = true;
151 : 27 : pgstat_report_fixed = true;
152 : :
153 : 27 : pgstat_count_backend_lock_waits(locktag_type, usecs);
154 : 27 : }
|