From c8a0d97545a6d58d5ca1646146c63a687cb33079 Mon Sep 17 00:00:00 2001 From: Craig Ringer Date: Thu, 19 Nov 2020 17:38:45 +0800 Subject: [PATCH v1 2/5] Pass the target LWLock* and tranche ID to LWLock tracepoints Previously the TRACE_POSTGRESQL_LWLOCK_ tracepoints only received a pointer to the LWLock tranche name. This made it impossible to identify individual locks. Passing the lock pointer itself isn't perfect. If the lock is allocated inside a DSM segment then it might be mapped at a different address in different backends. It's safe to compare lock pointers between backends (assuming !EXEC_BACKEND) if they're in the individual lock tranches or an extension-requested named tranche, but not necessarily for tranches in BuiltinTrancheIds or tranches >= LWTRANCHE_FIRST_USER_DEFINED that were directly assigned with LWLockNewTrancheId(). Still, it's better than nothing; the pointer is stable within a backend, and usually between backends. --- src/backend/storage/lmgr/lwlock.c | 35 +++++++++++++++++++------------ src/backend/utils/probes.d | 18 +++++++++------- 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/backend/storage/lmgr/lwlock.c b/src/backend/storage/lmgr/lwlock.c index 0a147bddaf..92de34a399 100644 --- a/src/backend/storage/lmgr/lwlock.c +++ b/src/backend/storage/lmgr/lwlock.c @@ -1323,7 +1323,8 @@ LWLockAcquire(LWLock *lock, LWLockMode mode) #endif LWLockReportWaitStart(lock); - TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), mode); + TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), mode, lock, + lock->tranche); for (;;) { @@ -1345,7 +1346,8 @@ LWLockAcquire(LWLock *lock, LWLockMode mode) } #endif - TRACE_POSTGRESQL_LWLOCK_WAIT_DONE(T_NAME(lock), mode); + TRACE_POSTGRESQL_LWLOCK_WAIT_DONE(T_NAME(lock), mode, lock, + lock->tranche); LWLockReportWaitEnd(); LOG_LWDEBUG("LWLockAcquire", lock, "awakened"); @@ -1354,7 +1356,7 @@ LWLockAcquire(LWLock *lock, LWLockMode mode) result = false; } - TRACE_POSTGRESQL_LWLOCK_ACQUIRE(T_NAME(lock), mode); + TRACE_POSTGRESQL_LWLOCK_ACQUIRE(T_NAME(lock), mode, lock, lock->tranche); /* Add lock to list of locks held by this backend */ held_lwlocks[num_held_lwlocks].lock = lock; @@ -1405,14 +1407,16 @@ LWLockConditionalAcquire(LWLock *lock, LWLockMode mode) RESUME_INTERRUPTS(); LOG_LWDEBUG("LWLockConditionalAcquire", lock, "failed"); - TRACE_POSTGRESQL_LWLOCK_CONDACQUIRE_FAIL(T_NAME(lock), mode); + TRACE_POSTGRESQL_LWLOCK_CONDACQUIRE_FAIL(T_NAME(lock), mode, lock, + lock->tranche); } 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; - TRACE_POSTGRESQL_LWLOCK_CONDACQUIRE(T_NAME(lock), mode); + TRACE_POSTGRESQL_LWLOCK_CONDACQUIRE(T_NAME(lock), mode, lock, + lock->tranche); } return !mustwait; } @@ -1484,7 +1488,8 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode) #endif LWLockReportWaitStart(lock); - TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), mode); + TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), mode, lock, + lock->tranche); for (;;) { @@ -1502,7 +1507,8 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode) Assert(nwaiters < MAX_BACKENDS); } #endif - TRACE_POSTGRESQL_LWLOCK_WAIT_DONE(T_NAME(lock), mode); + TRACE_POSTGRESQL_LWLOCK_WAIT_DONE(T_NAME(lock), mode, lock, + lock->tranche); LWLockReportWaitEnd(); LOG_LWDEBUG("LWLockAcquireOrWait", lock, "awakened"); @@ -1532,7 +1538,8 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode mode) /* Failed to get lock, so release interrupt holdoff */ RESUME_INTERRUPTS(); LOG_LWDEBUG("LWLockAcquireOrWait", lock, "failed"); - TRACE_POSTGRESQL_LWLOCK_ACQUIRE_OR_WAIT_FAIL(T_NAME(lock), mode); + TRACE_POSTGRESQL_LWLOCK_ACQUIRE_OR_WAIT_FAIL(T_NAME(lock), mode, lock, + lock->tranche); } else { @@ -1540,7 +1547,8 @@ LWLockAcquireOrWait(LWLock *lock, LWLockMode 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; - TRACE_POSTGRESQL_LWLOCK_ACQUIRE_OR_WAIT(T_NAME(lock), mode); + TRACE_POSTGRESQL_LWLOCK_ACQUIRE_OR_WAIT(T_NAME(lock), mode, lock, + lock->tranche); } return !mustwait; @@ -1700,7 +1708,8 @@ LWLockWaitForVar(LWLock *lock, uint64 *valptr, uint64 oldval, uint64 *newval) #endif LWLockReportWaitStart(lock); - TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), LW_EXCLUSIVE); + TRACE_POSTGRESQL_LWLOCK_WAIT_START(T_NAME(lock), LW_EXCLUSIVE, lock, + lock->tranche); for (;;) { @@ -1719,7 +1728,7 @@ LWLockWaitForVar(LWLock *lock, uint64 *valptr, uint64 oldval, uint64 *newval) } #endif - TRACE_POSTGRESQL_LWLOCK_WAIT_DONE(T_NAME(lock), LW_EXCLUSIVE); + TRACE_POSTGRESQL_LWLOCK_WAIT_DONE(T_NAME(lock), LW_EXCLUSIVE, lock, lock->tranche); LWLockReportWaitEnd(); LOG_LWDEBUG("LWLockWaitForVar", lock, "awakened"); @@ -1845,6 +1854,8 @@ LWLockRelease(LWLock *lock) /* nobody else can have that kind of lock */ Assert(!(oldstate & LW_VAL_EXCLUSIVE)); + /* Released, though not woken yet. All releases must fire this. */ + TRACE_POSTGRESQL_LWLOCK_RELEASE(T_NAME(lock), mode, lock, lock->tranche); /* * We're still waiting for backends to get scheduled, don't wake them up @@ -1868,8 +1879,6 @@ LWLockRelease(LWLock *lock) LWLockWakeup(lock); } - TRACE_POSTGRESQL_LWLOCK_RELEASE(T_NAME(lock)); - /* * Now okay to allow cancel/die interrupts. */ diff --git a/src/backend/utils/probes.d b/src/backend/utils/probes.d index a0b0458108..89805c3a89 100644 --- a/src/backend/utils/probes.d +++ b/src/backend/utils/probes.d @@ -17,6 +17,7 @@ #define LocalTransactionId unsigned int #define LWLockMode int #define LOCKMODE int +#define LWLock void #define BlockNumber unsigned int #define Oid unsigned int #define ForkNumber int @@ -28,14 +29,15 @@ provider postgresql { probe transaction__commit(LocalTransactionId); probe transaction__abort(LocalTransactionId); - probe lwlock__acquire(const char *, LWLockMode); - probe lwlock__release(const char *); - probe lwlock__wait__start(const char *, LWLockMode); - probe lwlock__wait__done(const char *, LWLockMode); - probe lwlock__condacquire(const char *, LWLockMode); - probe lwlock__condacquire__fail(const char *, LWLockMode); - probe lwlock__acquire__or__wait(const char *, LWLockMode); - probe lwlock__acquire__or__wait__fail(const char *, LWLockMode); + probe lwlock__acquire(const char *, LWLockMode, LWLock*, int); + probe lwlock__release(const char *, LWLockMode, LWLock*, int); + probe lwlock__wait__start(const char *, LWLockMode, LWLock*, int); + probe lwlock__wait__done(const char *, LWLockMode, LWLock*, int); + probe lwlock__condacquire(const char *, LWLockMode, LWLock*, int); + probe lwlock__condacquire__fail(const char *, LWLockMode, LWLock*, int); + probe lwlock__acquire__or__wait(const char *, LWLockMode, LWLock*, int); + probe lwlock__acquire__or__wait__fail(const char *, LWLockMode, LWLock*, int); + probe lock__wait__start(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, LOCKMODE); probe lock__wait__done(unsigned int, unsigned int, unsigned int, unsigned int, unsigned int, LOCKMODE); -- 2.26.2