LCOV - differential code coverage report
Current view: top level - src/backend/storage/lmgr - deadlock.c (source / functions) Coverage Total Hit LBC UIC UBC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 86.4 % 316 273 11 28 4 12 164 23 74 27 175 13
Current Date: 2023-04-08 17:13:01 Functions: 91.7 % 12 11 1 9 1 1 1 9
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (60,120] days: 100.0 % 23 23 23
Legend: Lines: hit not hit (240..) days: 85.3 % 293 250 11 28 4 12 164 74 27 175
Function coverage date bins:
(240..) days: 50.0 % 22 11 1 9 1 1 1 9

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * deadlock.c
                                  4                 :  *    POSTGRES deadlock detection code
                                  5                 :  *
                                  6                 :  * See src/backend/storage/lmgr/README for a description of the deadlock
                                  7                 :  * detection and resolution algorithms.
                                  8                 :  *
                                  9                 :  *
                                 10                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                 11                 :  * Portions Copyright (c) 1994, Regents of the University of California
                                 12                 :  *
                                 13                 :  *
                                 14                 :  * IDENTIFICATION
                                 15                 :  *    src/backend/storage/lmgr/deadlock.c
                                 16                 :  *
                                 17                 :  *  Interface:
                                 18                 :  *
                                 19                 :  *  DeadLockCheck()
                                 20                 :  *  DeadLockReport()
                                 21                 :  *  RememberSimpleDeadLock()
                                 22                 :  *  InitDeadLockChecking()
                                 23                 :  *
                                 24                 :  *-------------------------------------------------------------------------
                                 25                 :  */
                                 26                 : #include "postgres.h"
                                 27                 : 
                                 28                 : #include "miscadmin.h"
                                 29                 : #include "pg_trace.h"
                                 30                 : #include "pgstat.h"
                                 31                 : #include "storage/lmgr.h"
                                 32                 : #include "storage/proc.h"
                                 33                 : #include "utils/memutils.h"
                                 34                 : 
                                 35                 : 
                                 36                 : /*
                                 37                 :  * One edge in the waits-for graph.
                                 38                 :  *
                                 39                 :  * waiter and blocker may or may not be members of a lock group, but if either
                                 40                 :  * is, it will be the leader rather than any other member of the lock group.
                                 41                 :  * The group leaders act as representatives of the whole group even though
                                 42                 :  * those particular processes need not be waiting at all.  There will be at
                                 43                 :  * least one member of the waiter's lock group on the wait queue for the given
                                 44                 :  * lock, maybe more.
                                 45                 :  */
                                 46                 : typedef struct
                                 47                 : {
                                 48                 :     PGPROC     *waiter;         /* the leader of the waiting lock group */
                                 49                 :     PGPROC     *blocker;        /* the leader of the group it is waiting for */
                                 50                 :     LOCK       *lock;           /* the lock being waited for */
                                 51                 :     int         pred;           /* workspace for TopoSort */
                                 52                 :     int         link;           /* workspace for TopoSort */
                                 53                 : } EDGE;
                                 54                 : 
                                 55                 : /* One potential reordering of a lock's wait queue */
                                 56                 : typedef struct
                                 57                 : {
                                 58                 :     LOCK       *lock;           /* the lock whose wait queue is described */
                                 59                 :     PGPROC    **procs;          /* array of PGPROC *'s in new wait order */
                                 60                 :     int         nProcs;
                                 61                 : } WAIT_ORDER;
                                 62                 : 
                                 63                 : /*
                                 64                 :  * Information saved about each edge in a detected deadlock cycle.  This
                                 65                 :  * is used to print a diagnostic message upon failure.
                                 66                 :  *
                                 67                 :  * Note: because we want to examine this info after releasing the lock
                                 68                 :  * manager's partition locks, we can't just store LOCK and PGPROC pointers;
                                 69                 :  * we must extract out all the info we want to be able to print.
                                 70                 :  */
                                 71                 : typedef struct
                                 72                 : {
                                 73                 :     LOCKTAG     locktag;        /* ID of awaited lock object */
                                 74                 :     LOCKMODE    lockmode;       /* type of lock we're waiting for */
                                 75                 :     int         pid;            /* PID of blocked backend */
                                 76                 : } DEADLOCK_INFO;
                                 77                 : 
                                 78                 : 
                                 79                 : static bool DeadLockCheckRecurse(PGPROC *proc);
                                 80                 : static int  TestConfiguration(PGPROC *startProc);
                                 81                 : static bool FindLockCycle(PGPROC *checkProc,
                                 82                 :                           EDGE *softEdges, int *nSoftEdges);
                                 83                 : static bool FindLockCycleRecurse(PGPROC *checkProc, int depth,
                                 84                 :                                  EDGE *softEdges, int *nSoftEdges);
                                 85                 : static bool FindLockCycleRecurseMember(PGPROC *checkProc,
                                 86                 :                                        PGPROC *checkProcLeader,
                                 87                 :                                        int depth, EDGE *softEdges, int *nSoftEdges);
                                 88                 : static bool ExpandConstraints(EDGE *constraints, int nConstraints);
                                 89                 : static bool TopoSort(LOCK *lock, EDGE *constraints, int nConstraints,
                                 90                 :                      PGPROC **ordering);
                                 91                 : 
                                 92                 : #ifdef DEBUG_DEADLOCK
                                 93                 : static void PrintLockQueue(LOCK *lock, const char *info);
                                 94                 : #endif
                                 95                 : 
                                 96                 : 
                                 97                 : /*
                                 98                 :  * Working space for the deadlock detector
                                 99                 :  */
                                100                 : 
                                101                 : /* Workspace for FindLockCycle */
                                102                 : static PGPROC **visitedProcs;   /* Array of visited procs */
                                103                 : static int  nVisitedProcs;
                                104                 : 
                                105                 : /* Workspace for TopoSort */
                                106                 : static PGPROC **topoProcs;      /* Array of not-yet-output procs */
                                107                 : static int *beforeConstraints;  /* Counts of remaining before-constraints */
                                108                 : static int *afterConstraints;   /* List head for after-constraints */
                                109                 : 
                                110                 : /* Output area for ExpandConstraints */
                                111                 : static WAIT_ORDER *waitOrders;  /* Array of proposed queue rearrangements */
                                112                 : static int  nWaitOrders;
                                113                 : static PGPROC **waitOrderProcs; /* Space for waitOrders queue contents */
                                114                 : 
                                115                 : /* Current list of constraints being considered */
                                116                 : static EDGE *curConstraints;
                                117                 : static int  nCurConstraints;
                                118                 : static int  maxCurConstraints;
                                119                 : 
                                120                 : /* Storage space for results from FindLockCycle */
                                121                 : static EDGE *possibleConstraints;
                                122                 : static int  nPossibleConstraints;
                                123                 : static int  maxPossibleConstraints;
                                124                 : static DEADLOCK_INFO *deadlockDetails;
                                125                 : static int  nDeadlockDetails;
                                126                 : 
                                127                 : /* PGPROC pointer of any blocking autovacuum worker found */
                                128                 : static PGPROC *blocking_autovacuum_proc = NULL;
                                129                 : 
                                130                 : 
                                131                 : /*
                                132                 :  * InitDeadLockChecking -- initialize deadlock checker during backend startup
                                133                 :  *
                                134                 :  * This does per-backend initialization of the deadlock checker; primarily,
                                135                 :  * allocation of working memory for DeadLockCheck.  We do this per-backend
                                136                 :  * since there's no percentage in making the kernel do copy-on-write
                                137                 :  * inheritance of workspace from the postmaster.  We want to allocate the
                                138                 :  * space at startup because (a) the deadlock checker might be invoked when
                                139                 :  * there's no free memory left, and (b) the checker is normally run inside a
                                140                 :  * signal handler, which is a very dangerous place to invoke palloc from.
                                141                 :  */
                                142                 : void
 8109 tgl                       143 CBC       11510 : InitDeadLockChecking(void)
                                144                 : {
                                145                 :     MemoryContext oldcxt;
                                146                 : 
                                147                 :     /* Make sure allocations are permanent */
                                148           11510 :     oldcxt = MemoryContextSwitchTo(TopMemoryContext);
                                149                 : 
                                150                 :     /*
                                151                 :      * FindLockCycle needs at most MaxBackends entries in visitedProcs[] and
                                152                 :      * deadlockDetails[].
                                153                 :      */
  362 rhaas                     154           11510 :     visitedProcs = (PGPROC **) palloc(MaxBackends * sizeof(PGPROC *));
                                155           11510 :     deadlockDetails = (DEADLOCK_INFO *) palloc(MaxBackends * sizeof(DEADLOCK_INFO));
                                156                 : 
                                157                 :     /*
                                158                 :      * TopoSort needs to consider at most MaxBackends wait-queue entries, and
                                159                 :      * it needn't run concurrently with FindLockCycle.
                                160                 :      */
 8109 tgl                       161           11510 :     topoProcs = visitedProcs;   /* re-use this space */
  362 rhaas                     162           11510 :     beforeConstraints = (int *) palloc(MaxBackends * sizeof(int));
                                163           11510 :     afterConstraints = (int *) palloc(MaxBackends * sizeof(int));
                                164                 : 
                                165                 :     /*
                                166                 :      * We need to consider rearranging at most MaxBackends/2 wait queues
                                167                 :      * (since it takes at least two waiters in a queue to create a soft edge),
                                168                 :      * and the expanded form of the wait queues can't involve more than
                                169                 :      * MaxBackends total waiters.
                                170                 :      */
 7493 tgl                       171           11510 :     waitOrders = (WAIT_ORDER *)
  362 rhaas                     172           11510 :         palloc((MaxBackends / 2) * sizeof(WAIT_ORDER));
                                173           11510 :     waitOrderProcs = (PGPROC **) palloc(MaxBackends * sizeof(PGPROC *));
                                174                 : 
                                175                 :     /*
                                176                 :      * Allow at most MaxBackends distinct constraints in a configuration. (Is
                                177                 :      * this enough?  In practice it seems it should be, but I don't quite see
                                178                 :      * how to prove it.  If we run out, we might fail to find a workable wait
                                179                 :      * queue rearrangement even though one exists.)  NOTE that this number
                                180                 :      * limits the maximum recursion depth of DeadLockCheckRecurse. Making it
                                181                 :      * really big might potentially allow a stack-overflow problem.
                                182                 :      */
                                183           11510 :     maxCurConstraints = MaxBackends;
 8109 tgl                       184           11510 :     curConstraints = (EDGE *) palloc(maxCurConstraints * sizeof(EDGE));
                                185                 : 
                                186                 :     /*
                                187                 :      * Allow up to 3*MaxBackends constraints to be saved without having to
                                188                 :      * re-run TestConfiguration.  (This is probably more than enough, but we
                                189                 :      * can survive if we run low on space by doing excess runs of
                                190                 :      * TestConfiguration to re-compute constraint lists each time needed.) The
                                191                 :      * last MaxBackends entries in possibleConstraints[] are reserved as
                                192                 :      * output workspace for FindLockCycle.
                                193                 :      */
  362 rhaas                     194           11510 :     maxPossibleConstraints = MaxBackends * 4;
 8109 tgl                       195           11510 :     possibleConstraints =
                                196           11510 :         (EDGE *) palloc(maxPossibleConstraints * sizeof(EDGE));
                                197                 : 
                                198           11510 :     MemoryContextSwitchTo(oldcxt);
                                199           11510 : }
                                200                 : 
                                201                 : /*
                                202                 :  * DeadLockCheck -- Checks for deadlocks for a given process
                                203                 :  *
                                204                 :  * This code looks for deadlocks involving the given process.  If any
                                205                 :  * are found, it tries to rearrange lock wait queues to resolve the
                                206                 :  * deadlock.  If resolution is impossible, return DS_HARD_DEADLOCK ---
                                207                 :  * the caller is then expected to abort the given proc's transaction.
                                208                 :  *
                                209                 :  * Caller must already have locked all partitions of the lock tables.
                                210                 :  *
                                211                 :  * On failure, deadlock details are recorded in deadlockDetails[] for
                                212                 :  * subsequent printing by DeadLockReport().  That activity is separate
                                213                 :  * because (a) we don't want to do it while holding all those LWLocks,
                                214                 :  * and (b) we are typically invoked inside a signal handler.
                                215                 :  */
                                216                 : DeadLockState
 7607 JanWieck                  217              26 : DeadLockCheck(PGPROC *proc)
                                218                 : {
 8109 tgl                       219 ECB             :     /* Initialize to "no constraints" */
 8109 tgl                       220 GIC          26 :     nCurConstraints = 0;
                                221              26 :     nPossibleConstraints = 0;
 8109 tgl                       222 CBC          26 :     nWaitOrders = 0;
                                223                 : 
                                224                 :     /* Initialize to not blocked by an autovacuum worker */
 5644 alvherre                  225              26 :     blocking_autovacuum_proc = NULL;
                                226                 : 
                                227                 :     /* Search for deadlocks and possible fixes */
 8109 tgl                       228 GIC          26 :     if (DeadLockCheckRecurse(proc))
                                229                 :     {
                                230                 :         /*
                                231                 :          * Call FindLockCycle one more time, to record the correct
                                232                 :          * deadlockDetails[] for the basic state with no rearrangements.
                                233                 :          */
                                234                 :         int         nSoftEdges;
 7388 tgl                       235 ECB             : 
 5364 alvherre                  236                 :         TRACE_POSTGRESQL_DEADLOCK_FOUND();
 5364 alvherre                  237 EUB             : 
 7388 tgl                       238 GIC           4 :         nWaitOrders = 0;
 7388 tgl                       239 CBC           4 :         if (!FindLockCycle(proc, possibleConstraints, &nSoftEdges))
 7199 tgl                       240 UIC           0 :             elog(FATAL, "deadlock seems to have disappeared");
                                241                 : 
 5881 bruce                     242 GIC           4 :         return DS_HARD_DEADLOCK;    /* cannot find a non-deadlocked state */
 7388 tgl                       243 ECB             :     }
                                244                 : 
 8109                           245                 :     /* Apply any needed rearrangements of wait queues */
   81 andres                    246 GNC          25 :     for (int i = 0; i < nWaitOrders; i++)
 8109 tgl                       247 ECB             :     {
 8053 bruce                     248 CBC           3 :         LOCK       *lock = waitOrders[i].lock;
 7607 JanWieck                  249 GIC           3 :         PGPROC    **procs = waitOrders[i].procs;
 8053 bruce                     250 CBC           3 :         int         nProcs = waitOrders[i].nProcs;
   81 andres                    251 GNC           3 :         dclist_head *waitQueue = &lock->waitProcs;
                                252                 : 
                                253               3 :         Assert(nProcs == dclist_count(waitQueue));
                                254                 : 
                                255                 : #ifdef DEBUG_DEADLOCK
                                256                 :         PrintLockQueue(lock, "DeadLockCheck:");
 8109 tgl                       257 ECB             : #endif
                                258                 : 
                                259                 :         /* Reset the queue and re-add procs in the desired order */
   81 andres                    260 GNC           3 :         dclist_init(waitQueue);
                                261              12 :         for (int j = 0; j < nProcs; j++)
                                262               9 :             dclist_push_tail(waitQueue, &procs[j]->links);
 8109 tgl                       263 ECB             : 
                                264                 : #ifdef DEBUG_DEADLOCK
                                265                 :         PrintLockQueue(lock, "rearranged to:");
                                266                 : #endif
                                267                 : 
                                268                 :         /* See if any waiters for the lock can be woken up now */
 8109 tgl                       269 CBC           3 :         ProcLockWakeup(GetLocksMethodTable(lock), lock);
 8109 tgl                       270 EUB             :     }
                                271                 : 
 5773 tgl                       272 ECB             :     /* Return code tells caller if we had to escape a deadlock or not */
 5881 bruce                     273 GIC          22 :     if (nWaitOrders > 0)
                                274               3 :         return DS_SOFT_DEADLOCK;
 5644 alvherre                  275              19 :     else if (blocking_autovacuum_proc != NULL)
 5644 alvherre                  276 UIC           0 :         return DS_BLOCKED_BY_AUTOVACUUM;
                                277                 :     else
 5773 tgl                       278 GIC          19 :         return DS_NO_DEADLOCK;
                                279                 : }
                                280                 : 
 5644 alvherre                  281 EUB             : /*
                                282                 :  * Return the PGPROC of the autovacuum that's blocking a process.
                                283                 :  *
                                284                 :  * We reset the saved pointer as soon as we pass it back.
                                285                 :  */
                                286                 : PGPROC *
 5644 alvherre                  287 UIC           0 : GetBlockingAutoVacuumPgproc(void)
 5644 alvherre                  288 EUB             : {
                                289                 :     PGPROC     *ptr;
                                290                 : 
 5644 alvherre                  291 UIC           0 :     ptr = blocking_autovacuum_proc;
                                292               0 :     blocking_autovacuum_proc = NULL;
                                293                 : 
                                294               0 :     return ptr;
                                295                 : }
                                296                 : 
                                297                 : /*
                                298                 :  * DeadLockCheckRecurse -- recursively search for valid orderings
                                299                 :  *
                                300                 :  * curConstraints[] holds the current set of constraints being considered
                                301                 :  * by an outer level of recursion.  Add to this each possible solution
                                302                 :  * constraint for any cycle detected at this level.
 8109 tgl                       303 ECB             :  *
                                304                 :  * Returns true if no solution exists.  Returns false if a deadlock-free
                                305                 :  * state is attainable, in which case waitOrders[] shows the required
                                306                 :  * rearrangements of lock wait queues (if any).
                                307                 :  */
                                308                 : static bool
 7607 JanWieck                  309 GIC          29 : DeadLockCheckRecurse(PGPROC *proc)
 8109 tgl                       310 ECB             : {
                                311                 :     int         nEdges;
                                312                 :     int         oldPossibleConstraints;
                                313                 :     bool        savedList;
                                314                 :     int         i;
                                315                 : 
 8109 tgl                       316 GBC          29 :     nEdges = TestConfiguration(proc);
 8109 tgl                       317 CBC          29 :     if (nEdges < 0)
                                318               4 :         return true;            /* hard deadlock --- no solution */
 8109 tgl                       319 GIC          25 :     if (nEdges == 0)
                                320              22 :         return false;           /* good configuration found */
 8109 tgl                       321 CBC           3 :     if (nCurConstraints >= maxCurConstraints)
 8109 tgl                       322 LBC           0 :         return true;            /* out of room for active constraints? */
 8109 tgl                       323 GIC           3 :     oldPossibleConstraints = nPossibleConstraints;
  362 rhaas                     324               3 :     if (nPossibleConstraints + nEdges + MaxBackends <= maxPossibleConstraints)
                                325                 :     {
                                326                 :         /* We can save the edge list in possibleConstraints[] */
 8109 tgl                       327 GBC           3 :         nPossibleConstraints += nEdges;
 8109 tgl                       328 GIC           3 :         savedList = true;
                                329                 :     }
                                330                 :     else
                                331                 :     {
                                332                 :         /* Not room; will need to regenerate the edges on-the-fly */
 8109 tgl                       333 LBC           0 :         savedList = false;
                                334                 :     }
 8053 bruce                     335 ECB             : 
                                336                 :     /*
                                337                 :      * Try each available soft edge as an addition to the configuration.
 8109 tgl                       338 EUB             :      */
 8109 tgl                       339 GBC           3 :     for (i = 0; i < nEdges; i++)
                                340                 :     {
 8109 tgl                       341 CBC           3 :         if (!savedList && i > 0)
 8109 tgl                       342 ECB             :         {
                                343                 :             /* Regenerate the list of possible added constraints */
 8109 tgl                       344 LBC           0 :             if (nEdges != TestConfiguration(proc))
 7199                           345               0 :                 elog(FATAL, "inconsistent results during deadlock check");
                                346                 :         }
 8109 tgl                       347 GBC           3 :         curConstraints[nCurConstraints] =
 8053 bruce                     348 GIC           3 :             possibleConstraints[oldPossibleConstraints + i];
 8109 tgl                       349 GBC           3 :         nCurConstraints++;
                                350               3 :         if (!DeadLockCheckRecurse(proc))
 8109 tgl                       351 GIC           3 :             return false;       /* found a valid solution! */
                                352                 :         /* give up on that added constraint, try again */
 8109 tgl                       353 UIC           0 :         nCurConstraints--;
                                354                 :     }
                                355               0 :     nPossibleConstraints = oldPossibleConstraints;
                                356               0 :     return true;                /* no solution found */
                                357                 : }
                                358                 : 
                                359                 : 
                                360                 : /*--------------------
                                361                 :  * Test a configuration (current set of constraints) for validity.
                                362                 :  *
                                363                 :  * Returns:
                                364                 :  *      0: the configuration is good (no deadlocks)
                                365                 :  *     -1: the configuration has a hard deadlock or is not self-consistent
                                366                 :  *      >0: the configuration has one or more soft deadlocks
                                367                 :  *
                                368                 :  * In the soft-deadlock case, one of the soft cycles is chosen arbitrarily
 8109 tgl                       369 ECB             :  * and a list of its soft edges is returned beginning at
                                370                 :  * possibleConstraints+nPossibleConstraints.  The return value is the
                                371                 :  * number of soft edges.
                                372                 :  *--------------------
                                373                 :  */
                                374                 : static int
 7607 JanWieck                  375 GIC          29 : TestConfiguration(PGPROC *startProc)
                                376                 : {
 8053 bruce                     377              29 :     int         softFound = 0;
                                378              29 :     EDGE       *softEdges = possibleConstraints + nPossibleConstraints;
 8053 bruce                     379 ECB             :     int         nSoftEdges;
 8053 bruce                     380 EUB             :     int         i;
                                381                 : 
                                382                 :     /*
                                383                 :      * Make sure we have room for FindLockCycle's output.
                                384                 :      */
  362 rhaas                     385 GIC          29 :     if (nPossibleConstraints + MaxBackends > maxPossibleConstraints)
 8109 tgl                       386 LBC           0 :         return -1;
 8053 bruce                     387 EUB             : 
                                388                 :     /*
                                389                 :      * Expand current constraint set into wait orderings.  Fail if the
                                390                 :      * constraint set is not self-consistent.
                                391                 :      */
 8109 tgl                       392 GIC          29 :     if (!ExpandConstraints(curConstraints, nCurConstraints))
 8109 tgl                       393 UIC           0 :         return -1;
 8053 bruce                     394 ECB             : 
                                395                 :     /*
 6385                           396                 :      * Check for cycles involving startProc or any of the procs mentioned in
                                397                 :      * constraints.  We check startProc last because if it has a soft cycle
 6385 bruce                     398 EUB             :      * still to be dealt with, we want to deal with that first.
 8109 tgl                       399                 :      */
 8109 tgl                       400 GBC          32 :     for (i = 0; i < nCurConstraints; i++)
                                401                 :     {
 8109 tgl                       402 CBC           3 :         if (FindLockCycle(curConstraints[i].waiter, softEdges, &nSoftEdges))
                                403                 :         {
 8109 tgl                       404 UBC           0 :             if (nSoftEdges == 0)
                                405               0 :                 return -1;      /* hard deadlock detected */
                                406               0 :             softFound = nSoftEdges;
                                407                 :         }
 8109 tgl                       408 GIC           3 :         if (FindLockCycle(curConstraints[i].blocker, softEdges, &nSoftEdges))
 8109 tgl                       409 ECB             :         {
 8109 tgl                       410 UIC           0 :             if (nSoftEdges == 0)
 8109 tgl                       411 LBC           0 :                 return -1;      /* hard deadlock detected */
                                412               0 :             softFound = nSoftEdges;
 8109 tgl                       413 ECB             :         }
                                414                 :     }
 8109 tgl                       415 CBC          29 :     if (FindLockCycle(startProc, softEdges, &nSoftEdges))
                                416                 :     {
 8109 tgl                       417 GIC           7 :         if (nSoftEdges == 0)
                                418               4 :             return -1;          /* hard deadlock detected */
                                419               3 :         softFound = nSoftEdges;
                                420                 :     }
                                421              25 :     return softFound;
                                422                 : }
                                423                 : 
                                424                 : 
                                425                 : /*
                                426                 :  * FindLockCycle -- basic check for deadlock cycles
                                427                 :  *
                                428                 :  * Scan outward from the given proc to see if there is a cycle in the
                                429                 :  * waits-for graph that includes this proc.  Return true if a cycle
                                430                 :  * is found, else false.  If a cycle is found, we return a list of
                                431                 :  * the "soft edges", if any, included in the cycle.  These edges could
                                432                 :  * potentially be eliminated by rearranging wait queues.  We also fill
                                433                 :  * deadlockDetails[] with information about the detected cycle; this info
                                434                 :  * is not used by the deadlock algorithm itself, only to print a useful
                                435                 :  * message after failing.
                                436                 :  *
 8109 tgl                       437 ECB             :  * Since we need to be able to check hypothetical configurations that would
                                438                 :  * exist after wait queue rearrangement, the routine pays attention to the
                                439                 :  * table of hypothetical queue orders in waitOrders[].  These orders will
                                440                 :  * be believed in preference to the actual ordering seen in the locktable.
                                441                 :  */
                                442                 : static bool
 7607 JanWieck                  443 CBC          39 : FindLockCycle(PGPROC *checkProc,
 8109 tgl                       444 ECB             :               EDGE *softEdges,  /* output argument */
                                445                 :               int *nSoftEdges)  /* output argument */
                                446                 : {
 8109 tgl                       447 GIC          39 :     nVisitedProcs = 0;
 7388 tgl                       448 CBC          39 :     nDeadlockDetails = 0;
 8109 tgl                       449 GIC          39 :     *nSoftEdges = 0;
 7388                           450              39 :     return FindLockCycleRecurse(checkProc, 0, softEdges, nSoftEdges);
                                451                 : }
                                452                 : 
                                453                 : static bool
 7607 JanWieck                  454             119 : FindLockCycleRecurse(PGPROC *checkProc,
                                455                 :                      int depth,
                                456                 :                      EDGE *softEdges,   /* output argument */
                                457                 :                      int *nSoftEdges)   /* output argument */
                                458                 : {
                                459                 :     int         i;
 2618 rhaas                     460 ECB             :     dlist_iter  iter;
                                461                 : 
                                462                 :     /*
                                463                 :      * If this process is a lock group member, check the leader instead. (Note
                                464                 :      * that we might be the leader, in which case this is a no-op.)
                                465                 :      */
 2618 rhaas                     466 CBC         119 :     if (checkProc->lockGroupLeader != NULL)
 2618 rhaas                     467 GIC          25 :         checkProc = checkProc->lockGroupLeader;
 8109 tgl                       468 ECB             : 
                                469                 :     /*
                                470                 :      * Have we already seen this proc?
                                471                 :      */
 8109 tgl                       472 GIC         259 :     for (i = 0; i < nVisitedProcs; i++)
                                473                 :     {
                                474             157 :         if (visitedProcs[i] == checkProc)
                                475                 :         {
                                476                 :             /* If we return to starting point, we have a deadlock cycle */
 8109 tgl                       477 CBC          17 :             if (i == 0)
 7388 tgl                       478 ECB             :             {
                                479                 :                 /*
 6385 bruce                     480                 :                  * record total length of cycle --- outer levels will now fill
                                481                 :                  * deadlockDetails[]
                                482                 :                  */
  362 rhaas                     483 GIC          11 :                 Assert(depth <= MaxBackends);
 7388 tgl                       484              11 :                 nDeadlockDetails = depth;
                                485                 : 
 8109                           486              11 :                 return true;
 7388 tgl                       487 ECB             :             }
                                488                 : 
                                489                 :             /*
                                490                 :              * Otherwise, we have a cycle but it does not include the start
 6385 bruce                     491                 :              * point, so say "no deadlock".
 8109 tgl                       492                 :              */
 8109 tgl                       493 GIC           6 :             return false;
                                494                 :         }
                                495                 :     }
                                496                 :     /* Mark proc as seen */
  362 rhaas                     497             102 :     Assert(nVisitedProcs < MaxBackends);
 8109 tgl                       498 CBC         102 :     visitedProcs[nVisitedProcs++] = checkProc;
 8053 bruce                     499 ECB             : 
                                500                 :     /*
 2618 rhaas                     501                 :      * If the process is waiting, there is an outgoing waits-for edge to each
                                502                 :      * process that blocks it.
                                503                 :      */
 2618 rhaas                     504 GIC         171 :     if (checkProc->links.next != NULL && checkProc->waitLock != NULL &&
                                505              69 :         FindLockCycleRecurseMember(checkProc, checkProc, depth, softEdges,
                                506                 :                                    nSoftEdges))
                                507              37 :         return true;
                                508                 : 
                                509                 :     /*
 2618 rhaas                     510 ECB             :      * If the process is not waiting, there could still be outgoing waits-for
                                511                 :      * edges if it is part of a lock group, because other members of the lock
                                512                 :      * group might be waiting even though this process is not.  (Given lock
                                513                 :      * groups {A1, A2} and {B1, B2}, if A1 waits for B1 and B2 waits for A2,
                                514                 :      * that is a deadlock even neither of B1 and A2 are waiting for anything.)
                                515                 :      */
 2618 rhaas                     516 CBC         109 :     dlist_foreach(iter, &checkProc->lockGroupMembers)
 2618 rhaas                     517 ECB             :     {
                                518                 :         PGPROC     *memberProc;
                                519                 : 
 2618 rhaas                     520 CBC          48 :         memberProc = dlist_container(PGPROC, lockGroupLink, iter.cur);
                                521                 : 
 2618 rhaas                     522 GIC          48 :         if (memberProc->links.next != NULL && memberProc->waitLock != NULL &&
 2618 rhaas                     523 CBC          21 :             memberProc != checkProc &&
 2118 tgl                       524 GIC          21 :             FindLockCycleRecurseMember(memberProc, checkProc, depth, softEdges,
                                525                 :                                        nSoftEdges))
 2618 rhaas                     526               4 :             return true;
 2618 rhaas                     527 ECB             :     }
                                528                 : 
 2618 rhaas                     529 GIC          61 :     return false;
                                530                 : }
                                531                 : 
                                532                 : static bool
                                533              90 : FindLockCycleRecurseMember(PGPROC *checkProc,
 2618 rhaas                     534 ECB             :                            PGPROC *checkProcLeader,
                                535                 :                            int depth,
                                536                 :                            EDGE *softEdges, /* output argument */
                                537                 :                            int *nSoftEdges) /* output argument */
                                538                 : {
                                539                 :     PGPROC     *proc;
 2618 rhaas                     540 GIC          90 :     LOCK       *lock = checkProc->waitLock;
                                541                 :     dlist_iter  proclock_iter;
                                542                 :     LockMethod  lockMethodTable;
                                543                 :     int         conflictMask;
 2618 rhaas                     544 ECB             :     int         i;
                                545                 :     int         numLockModes,
 2618 rhaas                     546 EUB             :                 lm;
                                547                 : 
 1115 akapila                   548 ECB             :     /*
 1114                           549                 :      * The relation extension or page lock can never participate in actual
                                550                 :      * deadlock cycle.  See Asserts in LockAcquireExtended.  So, there is no
                                551                 :      * advantage in checking wait edges from them.
                                552                 :      */
 1114 akapila                   553 GIC          90 :     if (LOCK_LOCKTAG(*lock) == LOCKTAG_RELATION_EXTEND ||
                                554              90 :         (LOCK_LOCKTAG(*lock) == LOCKTAG_PAGE))
 1115 akapila                   555 UIC           0 :         return false;
 1115 akapila                   556 ECB             : 
 8109 tgl                       557 GIC          90 :     lockMethodTable = GetLocksMethodTable(lock);
 7570 bruce                     558 CBC          90 :     numLockModes = lockMethodTable->numLockModes;
 7570 bruce                     559 GIC          90 :     conflictMask = lockMethodTable->conflictTab[checkProc->waitLockMode];
                                560                 : 
 8109 tgl                       561 ECB             :     /*
 3260 bruce                     562                 :      * Scan for procs that already hold conflicting locks.  These are "hard"
                                563                 :      * edges in the waits-for graph.
                                564                 :      */
   81 andres                    565 GNC         267 :     dlist_foreach(proclock_iter, &lock->procLocks)
                                566                 :     {
                                567             213 :         PROCLOCK   *proclock = dlist_container(PROCLOCK, lockLink, proclock_iter.cur);
                                568                 :         PGPROC     *leader;
 2618 rhaas                     569 ECB             : 
 6104 tgl                       570 GIC         213 :         proc = proclock->tag.myProc;
 2618 rhaas                     571             213 :         leader = proc->lockGroupLeader == NULL ? proc : proc->lockGroupLeader;
                                572                 : 
 2618 rhaas                     573 ECB             :         /* A proc never blocks itself or any other lock group member */
 2618 rhaas                     574 GIC         213 :         if (leader != checkProcLeader)
 8109 tgl                       575 ECB             :         {
 8109 tgl                       576 CBC        1075 :             for (lm = 1; lm <= numLockModes; lm++)
 8109 tgl                       577 ECB             :             {
 6799 tgl                       578 GIC        1002 :                 if ((proclock->holdMask & LOCKBIT_ON(lm)) &&
 6799 tgl                       579 ECB             :                     (conflictMask & LOCKBIT_ON(lm)))
                                580                 :                 {
                                581                 :                     /* This proc hard-blocks checkProc */
 7188 bruce                     582 GIC          64 :                     if (FindLockCycleRecurse(proc, depth + 1,
                                583                 :                                              softEdges, nSoftEdges))
                                584                 :                     {
                                585                 :                         /* fill deadlockDetails[] */
                                586              36 :                         DEADLOCK_INFO *info = &deadlockDetails[depth];
                                587                 : 
 7388 tgl                       588              36 :                         info->locktag = lock->tag;
                                589              36 :                         info->lockmode = checkProc->waitLockMode;
                                590              36 :                         info->pid = checkProc->pid;
                                591                 : 
 8109                           592              36 :                         return true;
                                593                 :                     }
                                594                 : 
                                595                 :                     /*
                                596                 :                      * No deadlock here, but see if this proc is an autovacuum
                                597                 :                      * that is directly hard-blocking our own proc.  If so,
                                598                 :                      * report it so that the caller can send a cancel signal
                                599                 :                      * to it, if appropriate.  If there's more than one such
                                600                 :                      * proc, it's indeterminate which one will be reported.
                                601                 :                      *
                                602                 :                      * We don't touch autovacuums that are indirectly blocking
                                603                 :                      * us; it's up to the direct blockee to take action.  This
 3909 tgl                       604 ECB             :                      * rule simplifies understanding the behavior and ensures
                                605                 :                      * that an autovacuum won't be canceled with less than
 3909 tgl                       606 EUB             :                      * deadlock_timeout grace period.
                                607                 :                      *
                                608                 :                      * Note we read statusFlags without any locking.  This is
 3909 tgl                       609 ECB             :                      * OK only for checking the PROC_IS_AUTOVACUUM flag,
                                610                 :                      * because that flag is set at process start and never
                                611                 :                      * reset.  There is logic elsewhere to avoid canceling an
                                612                 :                      * autovacuum that is working to prevent XID wraparound
                                613                 :                      * problems (which needs to read a different statusFlags
                                614                 :                      * bit), but we don't do that here to avoid grabbing
                                615                 :                      * ProcArrayLock.
                                616                 :                      */
 3909 tgl                       617 GIC          28 :                     if (checkProc == MyProc &&
  874 alvherre                  618              18 :                         proc->statusFlags & PROC_IS_AUTOVACUUM)
 3909 tgl                       619 UIC           0 :                         blocking_autovacuum_proc = proc;
                                620                 : 
                                621                 :                     /* We're done looking at this proclock */
 8109 tgl                       622 GIC          28 :                     break;
                                623                 :                 }
 8109 tgl                       624 ECB             :             }
                                625                 :         }
                                626                 :     }
                                627                 : 
                                628                 :     /*
                                629                 :      * Scan for procs that are ahead of this one in the lock's wait queue.
 6385 bruce                     630                 :      * Those that have conflicting requests soft-block this one.  This must be
                                631                 :      * done after the hard-block search, since if another proc both hard- and
                                632                 :      * soft-blocks this one, we want to call it a hard edge.
 8109 tgl                       633                 :      *
                                634                 :      * If there is a proposed re-ordering of the lock's wait order, use that
                                635                 :      * rather than the current wait order.
                                636                 :      */
 8109 tgl                       637 CBC          63 :     for (i = 0; i < nWaitOrders; i++)
 8109 tgl                       638 ECB             :     {
 8109 tgl                       639 GIC          27 :         if (waitOrders[i].lock == lock)
                                640              18 :             break;
                                641                 :     }
                                642                 : 
                                643              54 :     if (i < nWaitOrders)
                                644                 :     {
                                645                 :         /* Use the given hypothetical wait queue order */
 7607 JanWieck                  646              18 :         PGPROC    **procs = waitOrders[i].procs;
   81 andres                    647 GNC          18 :         int         queue_size = waitOrders[i].nProcs;
 8109 tgl                       648 ECB             : 
 8109 tgl                       649 GIC          23 :         for (i = 0; i < queue_size; i++)
                                650                 :         {
 2618 rhaas                     651 ECB             :             PGPROC     *leader;
                                652                 : 
 8109 tgl                       653 GIC          23 :             proc = procs[i];
 2618 rhaas                     654 CBC          23 :             leader = proc->lockGroupLeader == NULL ? proc :
                                655                 :                 proc->lockGroupLeader;
                                656                 : 
                                657                 :             /*
 2618 rhaas                     658 EUB             :              * TopoSort will always return an ordering with group members
                                659                 :              * adjacent to each other in the wait queue (see comments
                                660                 :              * therein). So, as soon as we reach a process in the same lock
                                661                 :              * group as checkProc, we know we've found all the conflicts that
                                662                 :              * precede any member of the lock group lead by checkProcLeader.
                                663                 :              */
 2618 rhaas                     664 GIC          23 :             if (leader == checkProcLeader)
 8109 tgl                       665              18 :                 break;
                                666                 : 
 8109 tgl                       667 EUB             :             /* Is there a conflict with this guy's request? */
 2750 rhaas                     668 GBC           5 :             if ((LOCKBIT_ON(proc->waitLockMode) & conflictMask) != 0)
 8109 tgl                       669 EUB             :             {
                                670                 :                 /* This proc soft-blocks checkProc */
 7188 bruce                     671 GBC           5 :                 if (FindLockCycleRecurse(proc, depth + 1,
 7388 tgl                       672 EUB             :                                          softEdges, nSoftEdges))
                                673                 :                 {
                                674                 :                     /* fill deadlockDetails[] */
 7188 bruce                     675 UIC           0 :                     DEADLOCK_INFO *info = &deadlockDetails[depth];
                                676                 : 
 7388 tgl                       677               0 :                     info->locktag = lock->tag;
                                678               0 :                     info->lockmode = checkProc->waitLockMode;
 7388 tgl                       679 LBC           0 :                     info->pid = checkProc->pid;
                                680                 : 
                                681                 :                     /*
                                682                 :                      * Add this edge to the list of soft edges in the cycle
                                683                 :                      */
  362 rhaas                     684               0 :                     Assert(*nSoftEdges < MaxBackends);
 2618 rhaas                     685 UIC           0 :                     softEdges[*nSoftEdges].waiter = checkProcLeader;
                                686               0 :                     softEdges[*nSoftEdges].blocker = leader;
                                687               0 :                     softEdges[*nSoftEdges].lock = lock;
 8109 tgl                       688               0 :                     (*nSoftEdges)++;
                                689               0 :                     return true;
                                690                 :                 }
                                691                 :             }
                                692                 :         }
 8109 tgl                       693 ECB             :     }
                                694                 :     else
                                695                 :     {
 2618 rhaas                     696 GIC          36 :         PGPROC     *lastGroupMember = NULL;
                                697                 :         dlist_iter  proc_iter;
                                698                 :         dclist_head *waitQueue;
 2618 rhaas                     699 ECB             : 
                                700                 :         /* Use the true lock wait queue order */
   81 andres                    701 GNC          36 :         waitQueue = &lock->waitProcs;
                                702                 : 
 2618 rhaas                     703 ECB             :         /*
                                704                 :          * Find the last member of the lock group that is present in the wait
                                705                 :          * queue.  Anything after this is not a soft lock conflict. If group
                                706                 :          * locking is not in use, then we know immediately which process we're
                                707                 :          * looking for, but otherwise we've got to search the wait queue to
                                708                 :          * find the last process actually present.
                                709                 :          */
 2618 rhaas                     710 GIC          36 :         if (checkProc->lockGroupLeader == NULL)
                                711              27 :             lastGroupMember = checkProc;
 2618 rhaas                     712 ECB             :         else
                                713                 :         {
   81 andres                    714 GNC          32 :             dclist_foreach(proc_iter, waitQueue)
                                715                 :             {
                                716              23 :                 proc = dlist_container(PGPROC, links, proc_iter.cur);
                                717                 : 
 2618 rhaas                     718 CBC          23 :                 if (proc->lockGroupLeader == checkProcLeader)
 2618 rhaas                     719 GIC          13 :                     lastGroupMember = proc;
                                720                 :             }
 2618 rhaas                     721 CBC           9 :             Assert(lastGroupMember != NULL);
 2618 rhaas                     722 ECB             :         }
                                723                 : 
                                724                 :         /*
                                725                 :          * OK, now rescan (or scan) the queue to identify the soft conflicts.
                                726                 :          */
   81 andres                    727 GNC          47 :         dclist_foreach(proc_iter, waitQueue)
                                728                 :         {
                                729                 :             PGPROC     *leader;
                                730                 : 
                                731              47 :             proc = dlist_container(PGPROC, links, proc_iter.cur);
                                732                 : 
 2618 rhaas                     733 CBC          47 :             leader = proc->lockGroupLeader == NULL ? proc :
                                734                 :                 proc->lockGroupLeader;
 2618 rhaas                     735 ECB             : 
 8109 tgl                       736                 :             /* Done when we reach the target proc */
 2618 rhaas                     737 CBC          47 :             if (proc == lastGroupMember)
 8109 tgl                       738 GIC          31 :                 break;
                                739                 : 
                                740                 :             /* Is there a conflict with this guy's request? */
 2618 rhaas                     741              16 :             if ((LOCKBIT_ON(proc->waitLockMode) & conflictMask) != 0 &&
 2618 rhaas                     742 ECB             :                 leader != checkProcLeader)
 8109 tgl                       743                 :             {
                                744                 :                 /* This proc soft-blocks checkProc */
 7188 bruce                     745 CBC          11 :                 if (FindLockCycleRecurse(proc, depth + 1,
 7388 tgl                       746 ECB             :                                          softEdges, nSoftEdges))
 8109                           747                 :                 {
                                748                 :                     /* fill deadlockDetails[] */
 7188 bruce                     749 GIC           5 :                     DEADLOCK_INFO *info = &deadlockDetails[depth];
                                750                 : 
 7388 tgl                       751               5 :                     info->locktag = lock->tag;
                                752               5 :                     info->lockmode = checkProc->waitLockMode;
                                753               5 :                     info->pid = checkProc->pid;
                                754                 : 
                                755                 :                     /*
 6385 bruce                     756 ECB             :                      * Add this edge to the list of soft edges in the cycle
                                757                 :                      */
  362 rhaas                     758 GIC           5 :                     Assert(*nSoftEdges < MaxBackends);
 2618                           759               5 :                     softEdges[*nSoftEdges].waiter = checkProcLeader;
                                760               5 :                     softEdges[*nSoftEdges].blocker = leader;
                                761               5 :                     softEdges[*nSoftEdges].lock = lock;
 8109 tgl                       762               5 :                     (*nSoftEdges)++;
                                763               5 :                     return true;
                                764                 :                 }
                                765                 :             }
                                766                 :         }
                                767                 :     }
                                768                 : 
                                769                 :     /*
 8109 tgl                       770 ECB             :      * No conflict detected here.
                                771                 :      */
 8109 tgl                       772 GIC          49 :     return false;
 8109 tgl                       773 ECB             : }
                                774                 : 
                                775                 : 
                                776                 : /*
                                777                 :  * ExpandConstraints -- expand a list of constraints into a set of
                                778                 :  *      specific new orderings for affected wait queues
                                779                 :  *
                                780                 :  * Input is a list of soft edges to be reversed.  The output is a list
                                781                 :  * of nWaitOrders WAIT_ORDER structs in waitOrders[], with PGPROC array
                                782                 :  * workspace in waitOrderProcs[].
                                783                 :  *
 2062 peter_e                   784                 :  * Returns true if able to build an ordering that satisfies all the
                                785                 :  * constraints, false if not (there are contradictory constraints).
 8109 tgl                       786                 :  */
                                787                 : static bool
 8109 tgl                       788 GIC          29 : ExpandConstraints(EDGE *constraints,
 8109 tgl                       789 ECB             :                   int nConstraints)
                                790                 : {
 8109 tgl                       791 GBC          29 :     int         nWaitOrderProcs = 0;
 8109 tgl                       792 EUB             :     int         i,
                                793                 :                 j;
 8109 tgl                       794 ECB             : 
 8109 tgl                       795 GBC          29 :     nWaitOrders = 0;
                                796                 : 
 8109 tgl                       797 ECB             :     /*
 3260 bruce                     798                 :      * Scan constraint list backwards.  This is because the last-added
 6385                           799                 :      * constraint is the only one that could fail, and so we want to test it
                                800                 :      * for inconsistency first.
 8109 tgl                       801                 :      */
 8053 bruce                     802 GIC          32 :     for (i = nConstraints; --i >= 0;)
                                803                 :     {
 2618 rhaas                     804               3 :         LOCK       *lock = constraints[i].lock;
                                805                 : 
                                806                 :         /* Did we already make a list for this lock? */
 8053 bruce                     807 CBC           3 :         for (j = nWaitOrders; --j >= 0;)
 8109 tgl                       808 ECB             :         {
 8109 tgl                       809 UBC           0 :             if (waitOrders[j].lock == lock)
 8109 tgl                       810 LBC           0 :                 break;
                                811                 :         }
 8109 tgl                       812 CBC           3 :         if (j >= 0)
 8109 tgl                       813 UIC           0 :             continue;
                                814                 :         /* No, so allocate a new list */
 8109 tgl                       815 GIC           3 :         waitOrders[nWaitOrders].lock = lock;
                                816               3 :         waitOrders[nWaitOrders].procs = waitOrderProcs + nWaitOrderProcs;
   81 andres                    817 GNC           3 :         waitOrders[nWaitOrders].nProcs = dclist_count(&lock->waitProcs);
                                818               3 :         nWaitOrderProcs += dclist_count(&lock->waitProcs);
  362 rhaas                     819 GIC           3 :         Assert(nWaitOrderProcs <= MaxBackends);
                                820                 : 
                                821                 :         /*
                                822                 :          * Do the topo sort.  TopoSort need not examine constraints after this
                                823                 :          * one, since they must be for different locks.
                                824                 :          */
 8053 bruce                     825               3 :         if (!TopoSort(lock, constraints, i + 1,
 8109 tgl                       826               3 :                       waitOrders[nWaitOrders].procs))
 8109 tgl                       827 UIC           0 :             return false;
 8109 tgl                       828 GIC           3 :         nWaitOrders++;
                                829                 :     }
                                830              29 :     return true;
                                831                 : }
                                832                 : 
                                833                 : 
                                834                 : /*
                                835                 :  * TopoSort -- topological sort of a wait queue
                                836                 :  *
                                837                 :  * Generate a re-ordering of a lock's wait queue that satisfies given
                                838                 :  * constraints about certain procs preceding others.  (Each such constraint
                                839                 :  * is a fact of a partial ordering.)  Minimize rearrangement of the queue
                                840                 :  * not needed to achieve the partial ordering.
                                841                 :  *
 8109 tgl                       842 ECB             :  * This is a lot simpler and slower than, for example, the topological sort
                                843                 :  * algorithm shown in Knuth's Volume 1.  However, Knuth's method doesn't
                                844                 :  * try to minimize the damage to the existing order.  In practice we are
                                845                 :  * not likely to be working with more than a few constraints, so the apparent
                                846                 :  * slowness of the algorithm won't really matter.
                                847                 :  *
                                848                 :  * The initial queue ordering is taken directly from the lock's wait queue.
                                849                 :  * The output is an array of PGPROC pointers, of length equal to the lock's
                                850                 :  * wait queue length (the caller is responsible for providing this space).
                                851                 :  * The partial order is specified by an array of EDGE structs.  Each EDGE
                                852                 :  * is one that we need to reverse, therefore the "waiter" must appear before
                                853                 :  * the "blocker" in the output array.  The EDGE array may well contain
                                854                 :  * edges associated with other locks; these should be ignored.
                                855                 :  *
                                856                 :  * Returns true if able to build an ordering that satisfies all the
                                857                 :  * constraints, false if not (there are contradictory constraints).
                                858                 :  */
                                859                 : static bool
 8109 tgl                       860 CBC           3 : TopoSort(LOCK *lock,
                                861                 :          EDGE *constraints,
 8109 tgl                       862 ECB             :          int nConstraints,
 7607 JanWieck                  863                 :          PGPROC **ordering)     /* output argument */
                                864                 : {
   81 andres                    865 GNC           3 :     dclist_head *waitQueue = &lock->waitProcs;
                                866               3 :     int         queue_size = dclist_count(waitQueue);
                                867                 :     PGPROC     *proc;
                                868                 :     int         i,
                                869                 :                 j,
                                870                 :                 jj,
                                871                 :                 k,
                                872                 :                 kk,
                                873                 :                 last;
                                874                 :     dlist_iter  proc_iter;
                                875                 : 
                                876                 :     /* First, fill topoProcs[] array with the procs in their current order */
                                877               3 :     i = 0;
                                878              12 :     dclist_foreach(proc_iter, waitQueue)
                                879                 :     {
                                880               9 :         proc = dlist_container(PGPROC, links, proc_iter.cur);
                                881               9 :         topoProcs[i++] = proc;
                                882                 :     }
                                883               3 :     Assert(i == queue_size);
                                884                 : 
                                885                 :     /*
                                886                 :      * Scan the constraints, and for each proc in the array, generate a count
                                887                 :      * of the number of constraints that say it must be before something else,
                                888                 :      * plus a list of the constraints that say it must be after something
 6385 bruce                     889 ECB             :      * else. The count for the j'th proc is stored in beforeConstraints[j],
                                890                 :      * and the head of its list in afterConstraints[j].  Each constraint
                                891                 :      * stores its list link in constraints[i].link (note any constraint will
                                892                 :      * be in just one list). The array index for the before-proc of the i'th
                                893                 :      * constraint is remembered in constraints[i].pred.
                                894                 :      *
                                895                 :      * Note that it's not necessarily the case that every constraint affects
                                896                 :      * this particular wait queue.  Prior to group locking, a process could be
                                897                 :      * waiting for at most one lock.  But a lock group can be waiting for
                                898                 :      * zero, one, or multiple locks.  Since topoProcs[] is an array of the
                                899                 :      * processes actually waiting, while constraints[] is an array of group
                                900                 :      * leaders, we've got to scan through topoProcs[] for each constraint,
                                901                 :      * checking whether both a waiter and a blocker for that group are
                                902                 :      * present.  If so, the constraint is relevant to this wait queue; if not,
                                903                 :      * it isn't.
                                904                 :      */
 8109 tgl                       905 GIC           6 :     MemSet(beforeConstraints, 0, queue_size * sizeof(int));
                                906               6 :     MemSet(afterConstraints, 0, queue_size * sizeof(int));
 8109 tgl                       907 CBC           6 :     for (i = 0; i < nConstraints; i++)
 8109 tgl                       908 ECB             :     {
 2618 rhaas                     909                 :         /*
                                910                 :          * Find a representative process that is on the lock queue and part of
                                911                 :          * the waiting lock group.  This may or may not be the leader, which
                                912                 :          * may or may not be waiting at all.  If there are any other processes
                                913                 :          * in the same lock group on the queue, set their number of
                                914                 :          * beforeConstraints to -1 to indicate that they should be emitted
                                915                 :          * with their groupmates rather than considered separately.
 1350 tgl                       916                 :          *
                                917                 :          * In this loop and the similar one just below, it's critical that we
                                918                 :          * consistently select the same representative member of any one lock
                                919                 :          * group, so that all the constraints are associated with the same
                                920                 :          * proc, and the -1's are only associated with not-representative
                                921                 :          * members.  We select the last one in the topoProcs array.
 2618 rhaas                     922                 :          */
 8109 tgl                       923 GIC           3 :         proc = constraints[i].waiter;
 2618 rhaas                     924               3 :         Assert(proc != NULL);
                                925               3 :         jj = -1;
 8053 bruce                     926              12 :         for (j = queue_size; --j >= 0;)
                                927                 :         {
 2618 rhaas                     928 CBC           9 :             PGPROC     *waiter = topoProcs[j];
 2618 rhaas                     929 EUB             : 
 2618 rhaas                     930 GIC           9 :             if (waiter == proc || waiter->lockGroupLeader == proc)
                                931                 :             {
                                932               5 :                 Assert(waiter->waitLock == lock);
                                933               5 :                 if (jj == -1)
                                934               3 :                     jj = j;
                                935                 :                 else
 2618 rhaas                     936 ECB             :                 {
 2618 rhaas                     937 CBC           2 :                     Assert(beforeConstraints[j] <= 0);
                                938               2 :                     beforeConstraints[j] = -1;
 2618 rhaas                     939 ECB             :                 }
                                940                 :             }
 8109 tgl                       941                 :         }
                                942                 : 
 2618 rhaas                     943                 :         /* If no matching waiter, constraint is not relevant to this lock. */
 2618 rhaas                     944 GIC           3 :         if (jj < 0)
 2618 rhaas                     945 LBC           0 :             continue;
 2618 rhaas                     946 ECB             : 
                                947                 :         /*
                                948                 :          * Similarly, find a representative process that is on the lock queue
                                949                 :          * and waiting for the blocking lock group.  Again, this could be the
 2618 rhaas                     950 EUB             :          * leader but does not need to be.
                                951                 :          */
 8109 tgl                       952 GIC           3 :         proc = constraints[i].blocker;
 2618 rhaas                     953               3 :         Assert(proc != NULL);
                                954               3 :         kk = -1;
 8053 bruce                     955              12 :         for (k = queue_size; --k >= 0;)
                                956                 :         {
 2618 rhaas                     957 CBC           9 :             PGPROC     *blocker = topoProcs[k];
 2618 rhaas                     958 EUB             : 
 2618 rhaas                     959 GIC           9 :             if (blocker == proc || blocker->lockGroupLeader == proc)
 2618 rhaas                     960 ECB             :             {
 2618 rhaas                     961 CBC           3 :                 Assert(blocker->waitLock == lock);
 2618 rhaas                     962 GIC           3 :                 if (kk == -1)
 2618 rhaas                     963 CBC           3 :                     kk = k;
 2618 rhaas                     964 ECB             :                 else
                                965                 :                 {
 2618 rhaas                     966 UIC           0 :                     Assert(beforeConstraints[k] <= 0);
                                967               0 :                     beforeConstraints[k] = -1;
                                968                 :                 }
                                969                 :             }
                                970                 :         }
                                971                 : 
                                972                 :         /* If no matching blocker, constraint is not relevant to this lock. */
 2618 rhaas                     973 GIC           3 :         if (kk < 0)
 2618 rhaas                     974 UIC           0 :             continue;
                                975                 : 
 1350 tgl                       976 GIC           3 :         Assert(beforeConstraints[jj] >= 0);
 2618 rhaas                     977               3 :         beforeConstraints[jj]++;    /* waiter must come before */
                                978                 :         /* add this constraint to list of after-constraints for blocker */
 2618 rhaas                     979 CBC           3 :         constraints[i].pred = jj;
                                980               3 :         constraints[i].link = afterConstraints[kk];
 2618 rhaas                     981 GIC           3 :         afterConstraints[kk] = i + 1;
                                982                 :     }
 2618 rhaas                     983 ECB             : 
                                984                 :     /*--------------------
                                985                 :      * Now scan the topoProcs array backwards.  At each step, output the
                                986                 :      * last proc that has no remaining before-constraints plus any other
 2618 rhaas                     987 EUB             :      * members of the same lock group; then decrease the beforeConstraints
 2618 rhaas                     988 ECB             :      * count of each of the procs it was constrained against.
                                989                 :      * i = index of ordering[] entry we want to output this time
 8109 tgl                       990                 :      * j = search index for topoProcs[]
                                991                 :      * k = temp for scanning constraint list for proc j
                                992                 :      * last = last non-null index in topoProcs (avoid redundant searches)
                                993                 :      *--------------------
                                994                 :      */
 8053 bruce                     995 CBC           3 :     last = queue_size - 1;
 2618 rhaas                     996 GBC          10 :     for (i = queue_size - 1; i >= 0;)
                                997                 :     {
                                998                 :         int         c;
 2618 rhaas                     999 GIC           7 :         int         nmatches = 0;
                               1000                 : 
                               1001                 :         /* Find next candidate to output */
 8109 tgl                      1002               7 :         while (topoProcs[last] == NULL)
 8109 tgl                      1003 UIC           0 :             last--;
 8109 tgl                      1004 GIC          14 :         for (j = last; j >= 0; j--)
                               1005                 :         {
                               1006              14 :             if (topoProcs[j] != NULL && beforeConstraints[j] == 0)
 8109 tgl                      1007 CBC           7 :                 break;
 8109 tgl                      1008 ECB             :         }
 2618 rhaas                    1009                 : 
 8109 tgl                      1010                 :         /* If no available candidate, topological sort fails */
 8109 tgl                      1011 CBC           7 :         if (j < 0)
 8109 tgl                      1012 UIC           0 :             return false;
 2618 rhaas                    1013 ECB             : 
                               1014                 :         /*
                               1015                 :          * Output everything in the lock group.  There's no point in
 2604                          1016                 :          * outputting an ordering where members of the same lock group are not
 2618                          1017                 :          * consecutive on the wait queue: if some other waiter is between two
                               1018                 :          * requests that belong to the same group, then either it conflicts
                               1019                 :          * with both of them and is certainly not a solution; or it conflicts
                               1020                 :          * with at most one of them and is thus isomorphic to an ordering
                               1021                 :          * where the group members are consecutive.
                               1022                 :          */
 2618 rhaas                    1023 GIC           7 :         proc = topoProcs[j];
                               1024               7 :         if (proc->lockGroupLeader != NULL)
 2618 rhaas                    1025 CBC           2 :             proc = proc->lockGroupLeader;
                               1026               7 :         Assert(proc != NULL);
 2618 rhaas                    1027 GIC          28 :         for (c = 0; c <= last; ++c)
                               1028                 :         {
                               1029              21 :             if (topoProcs[c] == proc || (topoProcs[c] != NULL &&
 2118 tgl                      1030 CBC          11 :                                          topoProcs[c]->lockGroupLeader == proc))
                               1031                 :             {
 2618 rhaas                    1032 GIC           9 :                 ordering[i - nmatches] = topoProcs[c];
                               1033               9 :                 topoProcs[c] = NULL;
                               1034               9 :                 ++nmatches;
                               1035                 :             }
                               1036                 :         }
                               1037               7 :         Assert(nmatches > 0);
                               1038               7 :         i -= nmatches;
                               1039                 : 
                               1040                 :         /* Update beforeConstraints counts of its predecessors */
 8053 bruce                    1041              10 :         for (k = afterConstraints[j]; k > 0; k = constraints[k - 1].link)
                               1042               3 :             beforeConstraints[constraints[k - 1].pred]--;
                               1043                 :     }
                               1044                 : 
                               1045                 :     /* Done */
 8109 tgl                      1046               3 :     return true;
                               1047                 : }
                               1048                 : 
                               1049                 : #ifdef DEBUG_DEADLOCK
                               1050                 : static void
                               1051                 : PrintLockQueue(LOCK *lock, const char *info)
                               1052                 : {
                               1053                 :     dclist_head *waitQueue = &lock->waitProcs;
                               1054                 :     dlist_iter  proc_iter;
 8109 tgl                      1055 ECB             : 
                               1056                 :     printf("%s lock %p queue ", info, lock);
                               1057                 : 
                               1058                 :     dclist_foreach(proc_iter, waitQueue)
                               1059                 :     {
                               1060                 :         PGPROC     *proc = dlist_container(PGPROC, links, proc_iter.cur);
                               1061                 : 
                               1062                 :         printf(" %d", proc->pid);
                               1063                 :     }
                               1064                 :     printf("\n");
                               1065                 :     fflush(stdout);
                               1066                 : }
                               1067                 : #endif
 7388                          1068                 : 
                               1069                 : /*
 5773                          1070                 :  * Report a detected deadlock, with available details.
                               1071                 :  */
                               1072                 : void
 7388 tgl                      1073 GIC           5 : DeadLockReport(void)
 7388 tgl                      1074 ECB             : {
 5494                          1075                 :     StringInfoData clientbuf;   /* errdetail for client */
                               1076                 :     StringInfoData logbuf;      /* errdetail for server log */
 5497                          1077                 :     StringInfoData locktagbuf;
                               1078                 :     int         i;
                               1079                 : 
 5494 tgl                      1080 CBC           5 :     initStringInfo(&clientbuf);
 5494 tgl                      1081 GIC           5 :     initStringInfo(&logbuf);
 5497 tgl                      1082 CBC           5 :     initStringInfo(&locktagbuf);
                               1083                 : 
 5494 tgl                      1084 ECB             :     /* Generate the "waits for" lines sent to the client */
 7388 tgl                      1085 CBC          22 :     for (i = 0; i < nDeadlockDetails; i++)
                               1086                 :     {
 7188 bruce                    1087              17 :         DEADLOCK_INFO *info = &deadlockDetails[i];
 7388 tgl                      1088 ECB             :         int         nextpid;
                               1089                 : 
                               1090                 :         /* The last proc waits for the first one... */
 7188 bruce                    1091 GIC          17 :         if (i < nDeadlockDetails - 1)
 7388 tgl                      1092              12 :             nextpid = info[1].pid;
                               1093                 :         else
                               1094               5 :             nextpid = deadlockDetails[0].pid;
                               1095                 : 
                               1096                 :         /* reset locktagbuf to hold next object description */
 5497 tgl                      1097 CBC          17 :         resetStringInfo(&locktagbuf);
                               1098                 : 
 5497 tgl                      1099 GIC          17 :         DescribeLockTag(&locktagbuf, &info->locktag);
 6554 tgl                      1100 ECB             : 
 5497 tgl                      1101 GIC          17 :         if (i > 0)
 5494 tgl                      1102 CBC          12 :             appendStringInfoChar(&clientbuf, '\n');
                               1103                 : 
                               1104              34 :         appendStringInfo(&clientbuf,
 2118 tgl                      1105 GIC          17 :                          _("Process %d waits for %s on %s; blocked by process %d."),
 6554 tgl                      1106 ECB             :                          info->pid,
 6330 tgl                      1107 CBC          17 :                          GetLockmodeName(info->locktag.locktag_lockmethodid,
                               1108                 :                                          info->lockmode),
                               1109                 :                          locktagbuf.data,
                               1110                 :                          nextpid);
                               1111                 :     }
 5497 tgl                      1112 ECB             : 
                               1113                 :     /* Duplicate all the above for the server ... */
 1356 drowley                  1114 CBC           5 :     appendBinaryStringInfo(&logbuf, clientbuf.data, clientbuf.len);
                               1115                 : 
                               1116                 :     /* ... and add info about query strings */
 5494 tgl                      1117 GIC          22 :     for (i = 0; i < nDeadlockDetails; i++)
                               1118                 :     {
                               1119              17 :         DEADLOCK_INFO *info = &deadlockDetails[i];
                               1120                 : 
                               1121              17 :         appendStringInfoChar(&logbuf, '\n');
                               1122                 : 
                               1123              17 :         appendStringInfo(&logbuf,
 5497                          1124              17 :                          _("Process %d: %s"),
                               1125                 :                          info->pid,
                               1126                 :                          pgstat_get_backend_current_activity(info->pid, false));
                               1127                 :     }
 5497 tgl                      1128 ECB             : 
 4091 magnus                   1129 GIC           5 :     pgstat_report_deadlock();
                               1130                 : 
 7199 tgl                      1131               5 :     ereport(ERROR,
                               1132                 :             (errcode(ERRCODE_T_R_DEADLOCK_DETECTED),
 7199 tgl                      1133 ECB             :              errmsg("deadlock detected"),
                               1134                 :              errdetail_internal("%s", clientbuf.data),
 5494                          1135                 :              errdetail_log("%s", logbuf.data),
                               1136                 :              errhint("See server log for query details.")));
 7388                          1137                 : }
                               1138                 : 
                               1139                 : /*
                               1140                 :  * RememberSimpleDeadLock: set up info for DeadLockReport when ProcSleep
                               1141                 :  * detects a trivial (two-way) deadlock.  proc1 wants to block for lockmode
                               1142                 :  * on lock, but proc2 is already waiting and would be blocked by proc1.
                               1143                 :  */
                               1144                 : void
 7388 tgl                      1145 GIC           1 : RememberSimpleDeadLock(PGPROC *proc1,
                               1146                 :                        LOCKMODE lockmode,
                               1147                 :                        LOCK *lock,
                               1148                 :                        PGPROC *proc2)
                               1149                 : {
 7188 bruce                    1150               1 :     DEADLOCK_INFO *info = &deadlockDetails[0];
                               1151                 : 
 7388 tgl                      1152               1 :     info->locktag = lock->tag;
                               1153               1 :     info->lockmode = lockmode;
                               1154               1 :     info->pid = proc1->pid;
                               1155               1 :     info++;
                               1156               1 :     info->locktag = proc2->waitLock->tag;
                               1157               1 :     info->lockmode = proc2->waitLockMode;
                               1158               1 :     info->pid = proc2->pid;
                               1159               1 :     nDeadlockDetails = 2;
                               1160               1 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a