From b25f6db5693d0ca7d37b394145796b3bf96a35c1 Mon Sep 17 00:00:00 2001 From: Alexandre Felipe Date: Tue, 18 Aug 2026 01:06:17 +0100 Subject: [PATCH 3/5] lwlock: Save only pointer Instead of saving the mode of the lock infer it from the lock itself op | avg | min | q1 | med | q3 | max | std -------------+-------+------+-------+-------+-------+--------+------ spin-lock | 14.41 | 7.81 | 12.04 | 15.95 | 16.28 | 82.69 | 4.15 LWLock-ex | 6.97 | 6.18 | 6.84 | 6.84 | 6.84 | 47.53 | 1.71 LWLock-sh | 7.15 | 6.51 | 6.84 | 6.84 | 6.84 | 248.70 | 7.68 lw-ex-mode | 7.93 | 6.84 | 7.48 | 7.48 | 7.81 | 308.59 | 9.67 lw-ex-last | 6.75 | 6.18 | 6.51 | 6.52 | 6.84 | 26.04 | 0.82 lw-sh-mode | 7.57 | 6.84 | 7.48 | 7.48 | 7.81 | 16.28 | 0.61 lw-sh-last | 6.79 | 6.18 | 6.51 | 6.52 | 6.84 | 113.61 | 3.42 LWLock-cond | 6.16 | 5.21 | 5.86 | 5.86 | 6.19 | 63.80 | 1.95 nop | 0.72 | 0.32 | 0.65 | 0.66 | 0.98 | 2.93 | 0.27 --- src/backend/storage/lmgr/lwlock.c | 52 ++++++++++++++----------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index f572b4a4f84..444b5ed37ec 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -156,15 +156,9 @@ LWLockPadded *MainLWLockArray = NULL; */ #define MAX_SIMUL_LWLOCKS 200 -/* struct representing the LWLocks we're holding */ -typedef struct LWLockHandle -{ - LWLock *lock; - LWLockMode mode; -} LWLockHandle; static int num_held_lwlocks = 0; -static LWLockHandle held_lwlocks[MAX_SIMUL_LWLOCKS]; +static LWLock *held_lwlocks[MAX_SIMUL_LWLOCKS]; /* Maximum number of LWLock tranches that can be assigned by extensions */ #define MAX_USER_DEFINED_TRANCHES 256 @@ -229,6 +223,12 @@ static const char *GetLWTrancheName(uint16 trancheId); #define T_NAME(lock) \ GetLWTrancheName((lock)->tranche) +static LWLockMode +LWLockInferLockMode(LWLock *lock) +{ + return (pg_atomic_read_u32(&lock->state) & LW_VAL_EXCLUSIVE) ? + LW_EXCLUSIVE : LW_SHARED; +} #ifdef LWLOCK_STATS typedef struct lwlock_stats_key { @@ -1298,8 +1298,7 @@ LWLockAcquireCommon(LWLock *lock, LWLockMode mode) TRACE_POSTGRESQL_LWLOCK_ACQUIRE(T_NAME(lock), mode); /* Add lock to list of locks held by this backend */ - held_lwlocks[num_held_lwlocks].lock = lock; - held_lwlocks[num_held_lwlocks++].mode = mode; + held_lwlocks[num_held_lwlocks++] = lock; /* * Fix the process wait semaphore's count for any absorbed wakeups. @@ -1376,8 +1375,7 @@ LWLockConditionalAcquire(LWLock *lock, LWLockMode mode) else { /* Add lock to list of locks held by this backend */ - held_lwlocks[num_held_lwlocks].lock = lock; - held_lwlocks[num_held_lwlocks++].mode = mode; + held_lwlocks[num_held_lwlocks++] = lock; if (TRACE_POSTGRESQL_LWLOCK_CONDACQUIRE_ENABLED()) TRACE_POSTGRESQL_LWLOCK_CONDACQUIRE(T_NAME(lock), mode); } @@ -1507,8 +1505,7 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode) { LOG_LWDEBUG("LWLockAcquireOrWait", lock, "succeeded"); /* Add lock to list of locks held by this backend */ - held_lwlocks[num_held_lwlocks].lock = lock; - held_lwlocks[num_held_lwlocks++].mode = mode; + held_lwlocks[num_held_lwlocks++] = lock; if (TRACE_POSTGRESQL_LWLOCK_ACQUIRE_OR_WAIT_ENABLED()) TRACE_POSTGRESQL_LWLOCK_ACQUIRE_OR_WAIT(T_NAME(lock), mode); } @@ -1850,13 +1847,12 @@ extern void LWLockRelease(LWLock *lock) { int i = num_held_lwlocks - 1; - LWLockMode mode; + LWLockMode mode = LWLockInferLockMode(lock); /* * Fast path: check if this is the most recently acquired lock. */ - if (likely(i >= 0 && held_lwlocks[i].lock == lock)) + if (likely(i >= 0 && held_lwlocks[i] == lock)) { - mode = held_lwlocks[i].mode; num_held_lwlocks = i; LWLockReleaseInternal(lock, mode); return; @@ -1867,14 +1863,12 @@ LWLockRelease(LWLock *lock) */ for (i = num_held_lwlocks; --i >= 0;) - if (lock == held_lwlocks[i].lock) + if (lock == held_lwlocks[i]) break; if (i < 0) elog(ERROR, "lock %s is not held", T_NAME(lock)); - mode = held_lwlocks[i].mode; - num_held_lwlocks--; for (; i < num_held_lwlocks; i++) held_lwlocks[i] = held_lwlocks[i + 1]; @@ -1896,9 +1890,9 @@ LWLockReleaseCommon(LWLock *lock, LWLockMode mode) { int i = num_held_lwlocks - 1; - if (likely(i >= 0 && held_lwlocks[i].lock == lock)) + if (likely(i >= 0 && held_lwlocks[i] == lock)) { - Assert(held_lwlocks[i].mode == mode); + Assert(LWLockInferLockMode(lock) == mode); num_held_lwlocks = i; LWLockReleaseInternal(lock, mode); return; @@ -1906,13 +1900,13 @@ LWLockReleaseCommon(LWLock *lock, LWLockMode mode) for (;i >= 0; --i) - if (lock == held_lwlocks[i].lock) + if (lock == held_lwlocks[i]) break; if (i < 0) elog(ERROR, "lock %s is not held", T_NAME(lock)); - Assert(held_lwlocks[i].mode == mode); + Assert(LWLockInferLockMode(lock) == mode); num_held_lwlocks--; for (; i < num_held_lwlocks; i++) @@ -1955,8 +1949,8 @@ static pg_always_inline void LWLockReleaseLastCommon(LWLock *lock, LWLockMode mode) { Assert(num_held_lwlocks > 0); - Assert(held_lwlocks[num_held_lwlocks - 1].lock == lock); - Assert(held_lwlocks[num_held_lwlocks - 1].mode == mode); + Assert(held_lwlocks[num_held_lwlocks - 1] == lock); + Assert(LWLockInferLockMode(lock) == mode); num_held_lwlocks--; LWLockReleaseInternal(lock, mode); @@ -2022,7 +2016,7 @@ LWLockReleaseAll(void) { HOLD_INTERRUPTS(); /* match the upcoming RESUME_INTERRUPTS */ - LWLockRelease(held_lwlocks[num_held_lwlocks - 1].lock); + LWLockRelease(held_lwlocks[num_held_lwlocks - 1]); } Assert(num_held_lwlocks == 0); @@ -2041,7 +2035,7 @@ LWLockHeldByMe(LWLock *lock) for (i = 0; i < num_held_lwlocks; i++) { - if (held_lwlocks[i].lock == lock) + if (held_lwlocks[i] == lock) return true; } return false; @@ -2064,7 +2058,7 @@ LWLockAnyHeldByMe(LWLock *lock, int nlocks, size_t stride) end = begin + nlocks * stride; for (i = 0; i < num_held_lwlocks; i++) { - held_lock_addr = (char *) held_lwlocks[i].lock; + held_lock_addr = (char *) held_lwlocks[i]; if (held_lock_addr >= begin && held_lock_addr < end && (held_lock_addr - begin) % stride == 0) @@ -2085,7 +2079,7 @@ LWLockHeldByMeInMode(LWLock *lock, LWLockMode mode) for (i = 0; i < num_held_lwlocks; i++) { - if (held_lwlocks[i].lock == lock && held_lwlocks[i].mode == mode) + if (held_lwlocks[i] == lock && LWLockInferLockMode(lock) == mode) return true; } return false; -- 2.53.0