summaryrefslogtreecommitdiff
path: root/src/backend/storage/lmgr/proc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/storage/lmgr/proc.c')
-rw-r--r--src/backend/storage/lmgr/proc.c129
1 files changed, 78 insertions, 51 deletions
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 749a79d48ef..e4ca861a8e6 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -1514,10 +1514,6 @@ ProcSleep(LOCALLOCK *locallock)
long secs;
int usecs;
long msecs;
- dlist_iter proc_iter;
- PROCLOCK *curproclock;
- bool first_holder = true,
- first_waiter = true;
int lockHoldersNum = 0;
initStringInfo(&buf);
@@ -1533,54 +1529,10 @@ ProcSleep(LOCALLOCK *locallock)
msecs = secs * 1000 + usecs / 1000;
usecs = usecs % 1000;
- /*
- * we loop over the lock's procLocks to gather a list of all
- * holders and waiters. Thus we will be able to provide more
- * detailed information for lock debugging purposes.
- *
- * lock->procLocks contains all processes which hold or wait for
- * this lock.
- */
-
+ /* Gather a list of all lock holders and waiters */
LWLockAcquire(partitionLock, LW_SHARED);
-
- dlist_foreach(proc_iter, &lock->procLocks)
- {
- curproclock =
- dlist_container(PROCLOCK, lockLink, proc_iter.cur);
-
- /*
- * we are a waiter if myProc->waitProcLock == curproclock; we
- * are a holder if it is NULL or something different
- */
- if (curproclock->tag.myProc->waitProcLock == curproclock)
- {
- if (first_waiter)
- {
- appendStringInfo(&lock_waiters_sbuf, "%d",
- curproclock->tag.myProc->pid);
- first_waiter = false;
- }
- else
- appendStringInfo(&lock_waiters_sbuf, ", %d",
- curproclock->tag.myProc->pid);
- }
- else
- {
- if (first_holder)
- {
- appendStringInfo(&lock_holders_sbuf, "%d",
- curproclock->tag.myProc->pid);
- first_holder = false;
- }
- else
- appendStringInfo(&lock_holders_sbuf, ", %d",
- curproclock->tag.myProc->pid);
-
- lockHoldersNum++;
- }
- }
-
+ GetLockHoldersAndWaiters(locallock, &lock_holders_sbuf,
+ &lock_waiters_sbuf, &lockHoldersNum);
LWLockRelease(partitionLock);
if (deadlock_state == DS_SOFT_DEADLOCK)
@@ -1886,6 +1838,81 @@ CheckDeadLockAlert(void)
}
/*
+ * GetLockHoldersAndWaiters - get lock holders and waiters for a lock
+ *
+ * Fill lock_holders_sbuf and lock_waiters_sbuf with the PIDs of processes holding
+ * and waiting for the lock, and set lockHoldersNum to the number of lock holders.
+ *
+ * The lock table's partition lock must be held on entry and remains held on exit.
+ */
+void
+GetLockHoldersAndWaiters(LOCALLOCK *locallock, StringInfo lock_holders_sbuf,
+ StringInfo lock_waiters_sbuf, int *lockHoldersNum)
+{
+ dlist_iter proc_iter;
+ PROCLOCK *curproclock;
+ LOCK *lock = locallock->lock;
+ bool first_holder = true,
+ first_waiter = true;
+
+#ifdef USE_ASSERT_CHECKING
+ {
+ uint32 hashcode = locallock->hashcode;
+ LWLock *partitionLock = LockHashPartitionLock(hashcode);
+
+ Assert(LWLockHeldByMe(partitionLock));
+ }
+#endif
+
+ *lockHoldersNum = 0;
+
+ /*
+ * Loop over the lock's procLocks to gather a list of all holders and
+ * waiters. Thus we will be able to provide more detailed information for
+ * lock debugging purposes.
+ *
+ * lock->procLocks contains all processes which hold or wait for this
+ * lock.
+ */
+ dlist_foreach(proc_iter, &lock->procLocks)
+ {
+ curproclock =
+ dlist_container(PROCLOCK, lockLink, proc_iter.cur);
+
+ /*
+ * We are a waiter if myProc->waitProcLock == curproclock; we are a
+ * holder if it is NULL or something different.
+ */
+ if (curproclock->tag.myProc->waitProcLock == curproclock)
+ {
+ if (first_waiter)
+ {
+ appendStringInfo(lock_waiters_sbuf, "%d",
+ curproclock->tag.myProc->pid);
+ first_waiter = false;
+ }
+ else
+ appendStringInfo(lock_waiters_sbuf, ", %d",
+ curproclock->tag.myProc->pid);
+ }
+ else
+ {
+ if (first_holder)
+ {
+ appendStringInfo(lock_holders_sbuf, "%d",
+ curproclock->tag.myProc->pid);
+ first_holder = false;
+ }
+ else
+ appendStringInfo(lock_holders_sbuf, ", %d",
+ curproclock->tag.myProc->pid);
+
+ (*lockHoldersNum)++;
+ }
+ }
+}
+
+/*
* ProcWaitForSignal - wait for a signal from another backend.
*
* As this uses the generic process latch the caller has to be robust against