LCOV - code coverage report
Current view: top level - src/backend/storage/lmgr - proc.c (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 92.4 % 594 549
Test Date: 2026-07-20 15:16:30 Functions: 100.0 % 27 27
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 69.1 % 288 199

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * proc.c
       4                 :             :  *    routines to manage per-process shared memory data structure
       5                 :             :  *
       6                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :             :  *
       9                 :             :  *
      10                 :             :  * IDENTIFICATION
      11                 :             :  *    src/backend/storage/lmgr/proc.c
      12                 :             :  *
      13                 :             :  *-------------------------------------------------------------------------
      14                 :             :  */
      15                 :             : /*
      16                 :             :  * Interface (a):
      17                 :             :  *      JoinWaitQueue(), ProcSleep(), ProcWakeup()
      18                 :             :  *
      19                 :             :  * Waiting for a lock causes the backend to be put to sleep.  Whoever releases
      20                 :             :  * the lock wakes the process up again (and gives it an error code so it knows
      21                 :             :  * whether it was awoken on an error condition).
      22                 :             :  *
      23                 :             :  * Interface (b):
      24                 :             :  *
      25                 :             :  * ProcReleaseLocks -- frees the locks associated with current transaction
      26                 :             :  *
      27                 :             :  * ProcKill -- destroys the shared memory state (and locks)
      28                 :             :  * associated with the process.
      29                 :             :  */
      30                 :             : #include "postgres.h"
      31                 :             : 
      32                 :             : #include <signal.h>
      33                 :             : #include <unistd.h>
      34                 :             : #include <sys/time.h>
      35                 :             : 
      36                 :             : #include "access/clog.h"
      37                 :             : #include "access/transam.h"
      38                 :             : #include "access/twophase.h"
      39                 :             : #include "access/xlogutils.h"
      40                 :             : #include "access/xlogwait.h"
      41                 :             : #include "miscadmin.h"
      42                 :             : #include "pgstat.h"
      43                 :             : #include "postmaster/autovacuum.h"
      44                 :             : #include "replication/slotsync.h"
      45                 :             : #include "replication/syncrep.h"
      46                 :             : #include "storage/condition_variable.h"
      47                 :             : #include "storage/ipc.h"
      48                 :             : #include "storage/lmgr.h"
      49                 :             : #include "storage/pmsignal.h"
      50                 :             : #include "storage/proc.h"
      51                 :             : #include "storage/procarray.h"
      52                 :             : #include "storage/procsignal.h"
      53                 :             : #include "storage/spin.h"
      54                 :             : #include "storage/standby.h"
      55                 :             : #include "storage/subsystems.h"
      56                 :             : #include "utils/injection_point.h"
      57                 :             : #include "utils/timeout.h"
      58                 :             : #include "utils/timestamp.h"
      59                 :             : #include "utils/wait_event.h"
      60                 :             : 
      61                 :             : /* GUC variables */
      62                 :             : int         DeadlockTimeout = 1000;
      63                 :             : int         StatementTimeout = 0;
      64                 :             : int         LockTimeout = 0;
      65                 :             : int         IdleInTransactionSessionTimeout = 0;
      66                 :             : int         TransactionTimeout = 0;
      67                 :             : int         IdleSessionTimeout = 0;
      68                 :             : bool        log_lock_waits = true;
      69                 :             : 
      70                 :             : /* Pointer to this process's PGPROC struct, if any */
      71                 :             : PGPROC     *MyProc = NULL;
      72                 :             : 
      73                 :             : /* Pointers to shared-memory structures */
      74                 :             : PROC_HDR   *ProcGlobal = NULL;
      75                 :             : static void *AllProcsShmemPtr;
      76                 :             : static void *FastPathLockArrayShmemPtr;
      77                 :             : NON_EXEC_STATIC PGPROC *AuxiliaryProcs = NULL;
      78                 :             : PGPROC     *PreparedXactProcs = NULL;
      79                 :             : 
      80                 :             : static void ProcGlobalShmemRequest(void *arg);
      81                 :             : static void ProcGlobalShmemInit(void *arg);
      82                 :             : 
      83                 :             : const ShmemCallbacks ProcGlobalShmemCallbacks = {
      84                 :             :     .request_fn = ProcGlobalShmemRequest,
      85                 :             :     .init_fn = ProcGlobalShmemInit,
      86                 :             : };
      87                 :             : 
      88                 :             : static uint32 TotalProcs;
      89                 :             : static size_t ProcGlobalAllProcsShmemSize;
      90                 :             : static size_t FastPathLockArrayShmemSize;
      91                 :             : 
      92                 :             : /* Is a deadlock check pending? */
      93                 :             : static volatile sig_atomic_t got_deadlock_timeout;
      94                 :             : 
      95                 :             : static void RemoveProcFromArray(int code, Datum arg);
      96                 :             : static void ProcKill(int code, Datum arg);
      97                 :             : static void AuxiliaryProcKill(int code, Datum arg);
      98                 :             : static DeadLockState CheckDeadLock(void);
      99                 :             : 
     100                 :             : 
     101                 :             : /*
     102                 :             :  * Calculate shared-memory space needed by Fast-Path locks.
     103                 :             :  */
     104                 :             : static Size
     105                 :        1259 : CalculateFastPathLockShmemSize(void)
     106                 :             : {
     107                 :        1259 :     Size        size = 0;
     108                 :             :     Size        fpLockBitsSize,
     109                 :             :                 fpRelIdSize;
     110                 :             : 
     111                 :             :     /*
     112                 :             :      * Memory needed for PGPROC fast-path lock arrays. Make sure the sizes are
     113                 :             :      * nicely aligned in each backend.
     114                 :             :      */
     115                 :        1259 :     fpLockBitsSize = MAXALIGN(FastPathLockGroupsPerBackend * sizeof(uint64));
     116                 :        1259 :     fpRelIdSize = MAXALIGN(FastPathLockSlotsPerBackend() * sizeof(Oid));
     117                 :             : 
     118                 :        1259 :     size = add_size(size, mul_size(TotalProcs, (fpLockBitsSize + fpRelIdSize)));
     119                 :             : 
     120                 :             :     Assert(TotalProcs > 0);
     121                 :             :     Assert(size > 0);
     122                 :             : 
     123                 :        1259 :     return size;
     124                 :             : }
     125                 :             : 
     126                 :             : /*
     127                 :             :  * Report number of semaphores needed by ProcGlobalShmemInit.
     128                 :             :  */
     129                 :             : int
     130                 :        3598 : ProcGlobalSemas(void)
     131                 :             : {
     132                 :             :     /*
     133                 :             :      * We need a sema per backend (including autovacuum), plus one for each
     134                 :             :      * auxiliary process.
     135                 :             :      */
     136                 :        3598 :     return MaxBackends + NUM_AUXILIARY_PROCS;
     137                 :             : }
     138                 :             : 
     139                 :             : /*
     140                 :             :  * ProcGlobalShmemRequest
     141                 :             :  *    Register shared memory needs.
     142                 :             :  *
     143                 :             :  * This is called during postmaster or standalone backend startup, and also
     144                 :             :  * during backend startup in EXEC_BACKEND mode.
     145                 :             :  */
     146                 :             : static void
     147                 :        1259 : ProcGlobalShmemRequest(void *arg)
     148                 :             : {
     149                 :             :     Size        size;
     150                 :             : 
     151                 :             :     /*
     152                 :             :      * Reserve all the PGPROC structures we'll need.  There are six separate
     153                 :             :      * consumers: (1) normal backends, (2) autovacuum workers and special
     154                 :             :      * workers, (3) background workers, (4) walsenders, (5) auxiliary
     155                 :             :      * processes, and (6) prepared transactions.  (For largely-historical
     156                 :             :      * reasons, we combine autovacuum and special workers into one category
     157                 :             :      * with a single freelist.)  Each PGPROC structure is dedicated to exactly
     158                 :             :      * one of these purposes, and they do not move between groups.
     159                 :             :      */
     160                 :        1259 :     TotalProcs =
     161                 :        1259 :         add_size(MaxBackends, add_size(NUM_AUXILIARY_PROCS, max_prepared_xacts));
     162                 :             : 
     163                 :        1259 :     size = 0;
     164                 :        1259 :     size = add_size(size, mul_size(TotalProcs, sizeof(PGPROC)));
     165                 :        1259 :     size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->xids)));
     166                 :        1259 :     size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->subxidStates)));
     167                 :        1259 :     size = add_size(size, mul_size(TotalProcs, sizeof(*ProcGlobal->statusFlags)));
     168                 :        1259 :     ProcGlobalAllProcsShmemSize = size;
     169                 :        1259 :     ShmemRequestStruct(.name = "PGPROC structures",
     170                 :             :                        .size = ProcGlobalAllProcsShmemSize,
     171                 :             :                        .ptr = &AllProcsShmemPtr,
     172                 :             :         );
     173                 :             : 
     174         [ +  - ]:        1259 :     if (!IsUnderPostmaster)
     175                 :        1259 :         size = FastPathLockArrayShmemSize = CalculateFastPathLockShmemSize();
     176                 :             :     else
     177                 :           0 :         size = SHMEM_ATTACH_UNKNOWN_SIZE;
     178                 :        1259 :     ShmemRequestStruct(.name = "Fast-Path Lock Array",
     179                 :             :                        .size = size,
     180                 :             :                        .ptr = &FastPathLockArrayShmemPtr,
     181                 :             :         );
     182                 :             : 
     183                 :             :     /*
     184                 :             :      * ProcGlobal is registered here in .ptr as usual, but it needs to be
     185                 :             :      * propagated specially in EXEC_BACKEND mode, because ProcGlobal needs to
     186                 :             :      * be accessed early at backend startup, before ShmemAttachRequested() has
     187                 :             :      * been called.
     188                 :             :      */
     189                 :        1259 :     ShmemRequestStruct(.name = "Proc Header",
     190                 :             :                        .size = sizeof(PROC_HDR),
     191                 :             :                        .ptr = (void **) &ProcGlobal,
     192                 :             :         );
     193                 :             : 
     194                 :             :     /* Let the semaphore implementation register its shared memory needs */
     195                 :        1259 :     PGSemaphoreShmemRequest(ProcGlobalSemas());
     196                 :        1259 : }
     197                 :             : 
     198                 :             : 
     199                 :             : /*
     200                 :             :  * ProcGlobalShmemInit -
     201                 :             :  *    Initialize the global process table during postmaster or standalone
     202                 :             :  *    backend startup.
     203                 :             :  *
     204                 :             :  *    We also create all the per-process semaphores we will need to support
     205                 :             :  *    the requested number of backends.  We used to allocate semaphores
     206                 :             :  *    only when backends were actually started up, but that is bad because
     207                 :             :  *    it lets Postgres fail under load --- a lot of Unix systems are
     208                 :             :  *    (mis)configured with small limits on the number of semaphores, and
     209                 :             :  *    running out when trying to start another backend is a common failure.
     210                 :             :  *    So, now we grab enough semaphores to support the desired max number
     211                 :             :  *    of backends immediately at initialization --- if the sysadmin has set
     212                 :             :  *    MaxConnections, max_worker_processes, max_wal_senders, or
     213                 :             :  *    autovacuum_worker_slots higher than his kernel will support, he'll
     214                 :             :  *    find out sooner rather than later.
     215                 :             :  *
     216                 :             :  *    Another reason for creating semaphores here is that the semaphore
     217                 :             :  *    implementation typically requires us to create semaphores in the
     218                 :             :  *    postmaster, not in backends.
     219                 :             :  */
     220                 :             : static void
     221                 :        1256 : ProcGlobalShmemInit(void *arg)
     222                 :             : {
     223                 :             :     char       *ptr;
     224                 :             :     size_t      requestSize;
     225                 :             :     PGPROC     *procs;
     226                 :             :     int         i,
     227                 :             :                 j;
     228                 :             : 
     229                 :             :     /* Used for setup of per-backend fast-path slots. */
     230                 :             :     char       *fpPtr,
     231                 :             :                *fpEndPtr PG_USED_FOR_ASSERTS_ONLY;
     232                 :             :     Size        fpLockBitsSize,
     233                 :             :                 fpRelIdSize;
     234                 :             : 
     235                 :             :     Assert(ProcGlobal);
     236                 :        1256 :     ProcGlobal->spins_per_delay = DEFAULT_SPINS_PER_DELAY;
     237                 :        1256 :     SpinLockInit(&ProcGlobal->freeProcsLock);
     238                 :        1256 :     dlist_init(&ProcGlobal->freeProcs);
     239                 :        1256 :     dlist_init(&ProcGlobal->autovacFreeProcs);
     240                 :        1256 :     dlist_init(&ProcGlobal->bgworkerFreeProcs);
     241                 :        1256 :     dlist_init(&ProcGlobal->walsenderFreeProcs);
     242                 :        1256 :     ProcGlobal->startupBufferPinWaitBufId = -1;
     243                 :        1256 :     pg_atomic_init_u32(&ProcGlobal->avLauncherProc, INVALID_PROC_NUMBER);
     244                 :        1256 :     pg_atomic_init_u32(&ProcGlobal->walwriterProc, INVALID_PROC_NUMBER);
     245                 :        1256 :     pg_atomic_init_u32(&ProcGlobal->checkpointerProc, INVALID_PROC_NUMBER);
     246                 :        1256 :     pg_atomic_init_u32(&ProcGlobal->procArrayGroupFirst, INVALID_PROC_NUMBER);
     247                 :        1256 :     pg_atomic_init_u32(&ProcGlobal->clogGroupFirst, INVALID_PROC_NUMBER);
     248                 :             : 
     249                 :        1256 :     ptr = AllProcsShmemPtr;
     250                 :        1256 :     requestSize = ProcGlobalAllProcsShmemSize;
     251   [ +  -  +  +  :        1256 :     MemSet(ptr, 0, requestSize);
          +  -  -  +  -  
                      - ]
     252                 :             : 
     253                 :             :     /* Carve out the allProcs array from the shared memory area */
     254                 :        1256 :     procs = (PGPROC *) ptr;
     255                 :        1256 :     ptr = ptr + TotalProcs * sizeof(PGPROC);
     256                 :             : 
     257                 :        1256 :     ProcGlobal->allProcs = procs;
     258                 :             :     /* XXX allProcCount isn't really all of them; it excludes prepared xacts */
     259                 :        1256 :     ProcGlobal->allProcCount = MaxBackends + NUM_AUXILIARY_PROCS;
     260                 :             : 
     261                 :             :     /*
     262                 :             :      * Carve out arrays mirroring PGPROC fields in a dense manner. See
     263                 :             :      * PROC_HDR.
     264                 :             :      *
     265                 :             :      * XXX: It might make sense to increase padding for these arrays, given
     266                 :             :      * how hotly they are accessed.
     267                 :             :      */
     268                 :        1256 :     ProcGlobal->xids = (TransactionId *) ptr;
     269                 :        1256 :     ptr = ptr + (TotalProcs * sizeof(*ProcGlobal->xids));
     270                 :             : 
     271                 :        1256 :     ProcGlobal->subxidStates = (XidCacheStatus *) ptr;
     272                 :        1256 :     ptr = ptr + (TotalProcs * sizeof(*ProcGlobal->subxidStates));
     273                 :             : 
     274                 :        1256 :     ProcGlobal->statusFlags = (uint8 *) ptr;
     275                 :        1256 :     ptr = ptr + (TotalProcs * sizeof(*ProcGlobal->statusFlags));
     276                 :             : 
     277                 :             :     /* make sure we didn't overflow */
     278                 :             :     Assert((ptr > (char *) procs) && (ptr <= (char *) procs + requestSize));
     279                 :             : 
     280                 :             :     /*
     281                 :             :      * Initialize arrays for fast-path locks. Those are variable-length, so
     282                 :             :      * can't be included in PGPROC directly. We allocate a separate piece of
     283                 :             :      * shared memory and then divide that between backends.
     284                 :             :      */
     285                 :        1256 :     fpLockBitsSize = MAXALIGN(FastPathLockGroupsPerBackend * sizeof(uint64));
     286                 :        1256 :     fpRelIdSize = MAXALIGN(FastPathLockSlotsPerBackend() * sizeof(Oid));
     287                 :             : 
     288                 :        1256 :     fpPtr = FastPathLockArrayShmemPtr;
     289                 :        1256 :     requestSize = FastPathLockArrayShmemSize;
     290                 :        1256 :     memset(fpPtr, 0, requestSize);
     291                 :             : 
     292                 :             :     /* For asserts checking we did not overflow. */
     293                 :        1256 :     fpEndPtr = fpPtr + requestSize;
     294                 :             : 
     295                 :             :     /* Initialize semaphores */
     296                 :        1256 :     PGSemaphoreInit(ProcGlobalSemas());
     297                 :             : 
     298         [ +  + ]:      166003 :     for (i = 0; i < TotalProcs; i++)
     299                 :             :     {
     300                 :      164747 :         PGPROC     *proc = &procs[i];
     301                 :             : 
     302                 :             :         /* Common initialization for all PGPROCs, regardless of type. */
     303                 :             : 
     304                 :             :         /*
     305                 :             :          * Set the fast-path lock arrays, and move the pointer. We interleave
     306                 :             :          * the two arrays, to (hopefully) get some locality for each backend.
     307                 :             :          */
     308                 :      164747 :         proc->fpLockBits = (uint64 *) fpPtr;
     309                 :      164747 :         fpPtr += fpLockBitsSize;
     310                 :             : 
     311                 :      164747 :         proc->fpRelId = (Oid *) fpPtr;
     312                 :      164747 :         fpPtr += fpRelIdSize;
     313                 :             : 
     314                 :             :         Assert(fpPtr <= fpEndPtr);
     315                 :             : 
     316                 :             :         /*
     317                 :             :          * Set up per-PGPROC semaphore, latch, and fpInfoLock.  Prepared xact
     318                 :             :          * dummy PGPROCs don't need these though - they're never associated
     319                 :             :          * with a real process
     320                 :             :          */
     321         [ +  + ]:      164747 :         if (i < FIRST_PREPARED_XACT_PROC_NUMBER)
     322                 :             :         {
     323                 :      163861 :             proc->sem = PGSemaphoreCreate();
     324                 :      163861 :             InitSharedLatch(&(proc->procLatch));
     325                 :      163861 :             LWLockInitialize(&(proc->fpInfoLock), LWTRANCHE_LOCK_FASTPATH);
     326                 :             :         }
     327                 :             : 
     328                 :             :         /*
     329                 :             :          * Newly created PGPROCs for normal backends, autovacuum workers,
     330                 :             :          * special workers, bgworkers, and walsenders must be queued up on the
     331                 :             :          * appropriate free list.  Because there can only ever be a small,
     332                 :             :          * fixed number of auxiliary processes, no free list is used in that
     333                 :             :          * case; InitAuxiliaryProcess() instead uses a linear search.  PGPROCs
     334                 :             :          * for prepared transactions are added to a free list by
     335                 :             :          * TwoPhaseShmemInit().
     336                 :             :          */
     337         [ +  + ]:      164747 :         if (i < MaxConnections)
     338                 :             :         {
     339                 :             :             /* PGPROC for normal backend, add to freeProcs list */
     340                 :       81696 :             dlist_push_tail(&ProcGlobal->freeProcs, &proc->freeProcsLink);
     341                 :       81696 :             proc->procgloballist = &ProcGlobal->freeProcs;
     342                 :             :         }
     343         [ +  + ]:       83051 :         else if (i < MaxConnections + autovacuum_worker_slots + NUM_SPECIAL_WORKER_PROCS)
     344                 :             :         {
     345                 :             :             /* PGPROC for AV or special worker, add to autovacFreeProcs list */
     346                 :       16314 :             dlist_push_tail(&ProcGlobal->autovacFreeProcs, &proc->freeProcsLink);
     347                 :       16314 :             proc->procgloballist = &ProcGlobal->autovacFreeProcs;
     348                 :             :         }
     349         [ +  + ]:       66737 :         else if (i < MaxConnections + autovacuum_worker_slots + NUM_SPECIAL_WORKER_PROCS + max_worker_processes)
     350                 :             :         {
     351                 :             :             /* PGPROC for bgworker, add to bgworkerFreeProcs list */
     352                 :       10041 :             dlist_push_tail(&ProcGlobal->bgworkerFreeProcs, &proc->freeProcsLink);
     353                 :       10041 :             proc->procgloballist = &ProcGlobal->bgworkerFreeProcs;
     354                 :             :         }
     355         [ +  + ]:       56696 :         else if (i < MaxBackends)
     356                 :             :         {
     357                 :             :             /* PGPROC for walsender, add to walsenderFreeProcs list */
     358                 :        8082 :             dlist_push_tail(&ProcGlobal->walsenderFreeProcs, &proc->freeProcsLink);
     359                 :        8082 :             proc->procgloballist = &ProcGlobal->walsenderFreeProcs;
     360                 :             :         }
     361                 :             : 
     362                 :             :         /* Initialize myProcLocks[] shared memory queues. */
     363         [ +  + ]:     2800699 :         for (j = 0; j < NUM_LOCK_PARTITIONS; j++)
     364                 :     2635952 :             dlist_init(&(proc->myProcLocks[j]));
     365                 :             : 
     366                 :             :         /* Initialize lockGroupMembers list. */
     367                 :      164747 :         dlist_init(&proc->lockGroupMembers);
     368                 :             : 
     369                 :             :         /*
     370                 :             :          * Initialize the atomic variables, otherwise, it won't be safe to
     371                 :             :          * access them for backends that aren't currently in use.
     372                 :             :          */
     373                 :      164747 :         pg_atomic_init_u32(&(proc->procArrayGroupNext), INVALID_PROC_NUMBER);
     374                 :      164747 :         pg_atomic_init_u32(&(proc->clogGroupNext), INVALID_PROC_NUMBER);
     375                 :      164747 :         pg_atomic_init_u64(&(proc->waitStart), 0);
     376                 :             :     }
     377                 :             : 
     378                 :             :     /* Should have consumed exactly the expected amount of fast-path memory. */
     379                 :             :     Assert(fpPtr == fpEndPtr);
     380                 :             : 
     381                 :             :     /*
     382                 :             :      * Save pointers to the blocks of PGPROC structures reserved for auxiliary
     383                 :             :      * processes and prepared transactions.
     384                 :             :      */
     385                 :        1256 :     AuxiliaryProcs = &procs[MaxBackends];
     386                 :        1256 :     PreparedXactProcs = &procs[FIRST_PREPARED_XACT_PROC_NUMBER];
     387                 :        1256 : }
     388                 :             : 
     389                 :             : /*
     390                 :             :  * InitProcess -- initialize a per-process PGPROC entry for this backend
     391                 :             :  */
     392                 :             : void
     393                 :       20597 : InitProcess(void)
     394                 :             : {
     395                 :             :     dlist_head *procgloballist;
     396                 :             : 
     397                 :             :     /*
     398                 :             :      * ProcGlobal should be set up already (if we are a backend, we inherit
     399                 :             :      * this by fork() or EXEC_BACKEND mechanism from the postmaster).
     400                 :             :      */
     401         [ -  + ]:       20597 :     if (ProcGlobal == NULL)
     402         [ #  # ]:           0 :         elog(PANIC, "proc header uninitialized");
     403                 :             : 
     404         [ -  + ]:       20597 :     if (MyProc != NULL)
     405         [ #  # ]:           0 :         elog(ERROR, "you already exist");
     406                 :             : 
     407                 :             :     /*
     408                 :             :      * Before we start accessing the shared memory in a serious way, mark
     409                 :             :      * ourselves as an active postmaster child; this is so that the postmaster
     410                 :             :      * can detect it if we exit without cleaning up.
     411                 :             :      */
     412         [ +  + ]:       20597 :     if (IsUnderPostmaster)
     413                 :       20464 :         RegisterPostmasterChildActive();
     414                 :             : 
     415                 :             :     /*
     416                 :             :      * Decide which list should supply our PGPROC.  This logic must match the
     417                 :             :      * way the freelists were constructed in ProcGlobalShmemInit().
     418                 :             :      */
     419   [ +  +  +  +  :       20597 :     if (AmAutoVacuumWorkerProcess() || AmSpecialWorkerProcess())
                   +  + ]
     420                 :        2292 :         procgloballist = &ProcGlobal->autovacFreeProcs;
     421         [ +  + ]:       18305 :     else if (AmBackgroundWorkerProcess())
     422                 :        3240 :         procgloballist = &ProcGlobal->bgworkerFreeProcs;
     423         [ +  + ]:       15065 :     else if (AmWalSenderProcess())
     424                 :        1336 :         procgloballist = &ProcGlobal->walsenderFreeProcs;
     425                 :             :     else
     426                 :       13729 :         procgloballist = &ProcGlobal->freeProcs;
     427                 :             : 
     428                 :             :     /*
     429                 :             :      * Try to get a proc struct from the appropriate free list.  If this
     430                 :             :      * fails, we must be out of PGPROC structures (not to mention semaphores).
     431                 :             :      *
     432                 :             :      * While we are holding the spinlock, also copy the current shared
     433                 :             :      * estimate of spins_per_delay to local storage.
     434                 :             :      */
     435                 :       20597 :     SpinLockAcquire(&ProcGlobal->freeProcsLock);
     436                 :             : 
     437                 :       20597 :     set_spins_per_delay(ProcGlobal->spins_per_delay);
     438                 :             : 
     439         [ +  + ]:       20597 :     if (!dlist_is_empty(procgloballist))
     440                 :             :     {
     441                 :       20594 :         MyProc = dlist_container(PGPROC, freeProcsLink, dlist_pop_head_node(procgloballist));
     442                 :       20594 :         SpinLockRelease(&ProcGlobal->freeProcsLock);
     443                 :             :     }
     444                 :             :     else
     445                 :             :     {
     446                 :             :         /*
     447                 :             :          * If we reach here, all the PGPROCs are in use.  This is one of the
     448                 :             :          * possible places to detect "too many backends", so give the standard
     449                 :             :          * error message.  XXX do we need to give a different failure message
     450                 :             :          * in the autovacuum case?
     451                 :             :          */
     452                 :           3 :         SpinLockRelease(&ProcGlobal->freeProcsLock);
     453         [ +  + ]:           3 :         if (AmWalSenderProcess())
     454         [ +  - ]:           2 :             ereport(FATAL,
     455                 :             :                     (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
     456                 :             :                      errmsg("number of requested standby connections exceeds \"max_wal_senders\" (currently %d)",
     457                 :             :                             max_wal_senders)));
     458         [ +  - ]:           1 :         ereport(FATAL,
     459                 :             :                 (errcode(ERRCODE_TOO_MANY_CONNECTIONS),
     460                 :             :                  errmsg("sorry, too many clients already")));
     461                 :             :     }
     462                 :       20594 :     MyProcNumber = GetNumberFromPGProc(MyProc);
     463                 :             : 
     464                 :             :     /*
     465                 :             :      * Cross-check that the PGPROC is of the type we expect; if this were not
     466                 :             :      * the case, it would get returned to the wrong list.
     467                 :             :      */
     468                 :             :     Assert(MyProc->procgloballist == procgloballist);
     469                 :             : 
     470                 :             :     /*
     471                 :             :      * Initialize all fields of MyProc, except for those previously
     472                 :             :      * initialized by ProcGlobalShmemInit.
     473                 :             :      */
     474                 :       20594 :     dlist_node_init(&MyProc->freeProcsLink);
     475                 :       20594 :     MyProc->waitStatus = PROC_WAIT_STATUS_OK;
     476                 :       20594 :     MyProc->fpVXIDLock = false;
     477                 :       20594 :     MyProc->fpLocalTransactionId = InvalidLocalTransactionId;
     478                 :       20594 :     MyProc->xid = InvalidTransactionId;
     479                 :       20594 :     MyProc->xmin = InvalidTransactionId;
     480                 :       20594 :     MyProc->pid = MyProcPid;
     481                 :       20594 :     MyProc->vxid.procNumber = MyProcNumber;
     482                 :       20594 :     MyProc->vxid.lxid = InvalidLocalTransactionId;
     483                 :             :     /* databaseId and roleId will be filled in later */
     484                 :       20594 :     MyProc->databaseId = InvalidOid;
     485                 :       20594 :     MyProc->roleId = InvalidOid;
     486                 :       20594 :     MyProc->tempNamespaceId = InvalidOid;
     487                 :       20594 :     MyProc->backendType = MyBackendType;
     488                 :       20594 :     MyProc->delayChkptFlags = 0;
     489                 :       20594 :     MyProc->statusFlags = 0;
     490                 :             :     /* NB -- autovac launcher intentionally does not set IS_AUTOVACUUM */
     491         [ +  + ]:       20594 :     if (AmAutoVacuumWorkerProcess())
     492                 :        1806 :         MyProc->statusFlags |= PROC_IS_AUTOVACUUM;
     493                 :       20594 :     MyProc->lwWaiting = LW_WS_NOT_WAITING;
     494                 :       20594 :     MyProc->lwWaitMode = 0;
     495                 :       20594 :     MyProc->waitLock = NULL;
     496                 :       20594 :     dlist_node_init(&MyProc->waitLink);
     497                 :       20594 :     MyProc->waitProcLock = NULL;
     498                 :       20594 :     pg_atomic_write_u64(&MyProc->waitStart, 0);
     499                 :             : #ifdef USE_ASSERT_CHECKING
     500                 :             :     {
     501                 :             :         int         i;
     502                 :             : 
     503                 :             :         /* Last process should have released all locks. */
     504                 :             :         for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
     505                 :             :             Assert(dlist_is_empty(&(MyProc->myProcLocks[i])));
     506                 :             :     }
     507                 :             : #endif
     508                 :       20594 :     pg_atomic_write_u32(&MyProc->pendingRecoveryConflicts, 0);
     509                 :             : 
     510                 :             :     /* Initialize fields for sync rep */
     511                 :       20594 :     MyProc->waitLSN = InvalidXLogRecPtr;
     512                 :       20594 :     MyProc->syncRepState = SYNC_REP_NOT_WAITING;
     513                 :       20594 :     dlist_node_init(&MyProc->syncRepLinks);
     514                 :             : 
     515                 :             :     /* Initialize fields for group XID clearing. */
     516                 :       20594 :     MyProc->procArrayGroupMember = false;
     517                 :       20594 :     MyProc->procArrayGroupMemberXid = InvalidTransactionId;
     518                 :             :     Assert(pg_atomic_read_u32(&MyProc->procArrayGroupNext) == INVALID_PROC_NUMBER);
     519                 :             : 
     520                 :             :     /* Check that group locking fields are in a proper initial state. */
     521                 :             :     Assert(MyProc->lockGroupLeader == NULL);
     522                 :             :     Assert(dlist_is_empty(&MyProc->lockGroupMembers));
     523                 :             : 
     524                 :             :     /* Initialize wait event information. */
     525                 :       20594 :     MyProc->wait_event_info = 0;
     526                 :             : 
     527                 :             :     /* Initialize fields for group transaction status update. */
     528                 :       20594 :     MyProc->clogGroupMember = false;
     529                 :       20594 :     MyProc->clogGroupMemberXid = InvalidTransactionId;
     530                 :       20594 :     MyProc->clogGroupMemberXidStatus = TRANSACTION_STATUS_IN_PROGRESS;
     531                 :       20594 :     MyProc->clogGroupMemberPage = -1;
     532                 :       20594 :     MyProc->clogGroupMemberLsn = InvalidXLogRecPtr;
     533                 :             :     Assert(pg_atomic_read_u32(&MyProc->clogGroupNext) == INVALID_PROC_NUMBER);
     534                 :             : 
     535                 :             :     /*
     536                 :             :      * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
     537                 :             :      * on it.  That allows us to repoint the process latch, which so far
     538                 :             :      * points to process local one, to the shared one.
     539                 :             :      */
     540                 :       20594 :     OwnLatch(&MyProc->procLatch);
     541                 :       20594 :     SwitchToSharedLatch();
     542                 :             : 
     543                 :             :     /* now that we have a proc, report wait events to shared memory */
     544                 :       20594 :     pgstat_set_wait_event_storage(&MyProc->wait_event_info);
     545                 :             : 
     546                 :             :     /*
     547                 :             :      * We might be reusing a semaphore that belonged to a failed process. So
     548                 :             :      * be careful and reinitialize its value here.  (This is not strictly
     549                 :             :      * necessary anymore, but seems like a good idea for cleanliness.)
     550                 :             :      */
     551                 :       20594 :     PGSemaphoreReset(MyProc->sem);
     552                 :             : 
     553                 :             :     /* autovacuum launcher is specially advertised in ProcGlobal */
     554         [ +  + ]:       20594 :     if (MyBackendType == B_AUTOVAC_LAUNCHER)
     555                 :         480 :         pg_atomic_write_u32(&ProcGlobal->avLauncherProc, MyProcNumber);
     556                 :             : 
     557                 :             :     /*
     558                 :             :      * Arrange to clean up at backend exit.
     559                 :             :      */
     560                 :       20594 :     on_shmem_exit(ProcKill, 0);
     561                 :             : 
     562                 :             :     /*
     563                 :             :      * Now that we have a PGPROC, we could try to acquire locks, so initialize
     564                 :             :      * local state needed for LWLocks, and the deadlock checker.
     565                 :             :      */
     566                 :       20594 :     InitLWLockAccess();
     567                 :       20594 :     InitDeadLockChecking();
     568                 :             : 
     569                 :             : #ifdef EXEC_BACKEND
     570                 :             : 
     571                 :             :     /*
     572                 :             :      * Initialize backend-local pointers to all the shared data structures.
     573                 :             :      * (We couldn't do this until now because it needs LWLocks.)
     574                 :             :      */
     575                 :             :     if (IsUnderPostmaster)
     576                 :             :         AttachSharedMemoryStructs();
     577                 :             : #endif
     578                 :       20594 : }
     579                 :             : 
     580                 :             : /*
     581                 :             :  * InitProcessPhase2 -- make MyProc visible in the shared ProcArray.
     582                 :             :  *
     583                 :             :  * This is separate from InitProcess because we can't acquire LWLocks until
     584                 :             :  * we've created a PGPROC, but in the EXEC_BACKEND case ProcArrayAdd won't
     585                 :             :  * work until after we've done AttachSharedMemoryStructs.
     586                 :             :  */
     587                 :             : void
     588                 :       20581 : InitProcessPhase2(void)
     589                 :             : {
     590                 :             :     Assert(MyProc != NULL);
     591                 :             : 
     592                 :             :     /*
     593                 :             :      * Add our PGPROC to the PGPROC array in shared memory.
     594                 :             :      */
     595                 :       20581 :     ProcArrayAdd(MyProc);
     596                 :             : 
     597                 :             :     /*
     598                 :             :      * Arrange to clean that up at backend exit.
     599                 :             :      */
     600                 :       20581 :     on_shmem_exit(RemoveProcFromArray, 0);
     601                 :       20581 : }
     602                 :             : 
     603                 :             : /*
     604                 :             :  * InitAuxiliaryProcess -- create a PGPROC entry for an auxiliary process
     605                 :             :  *
     606                 :             :  * This is called by bgwriter and similar processes so that they will have a
     607                 :             :  * MyProc value that's real enough to let them wait for LWLocks.  The PGPROC
     608                 :             :  * and sema that are assigned are one of the extra ones created during
     609                 :             :  * ProcGlobalShmemInit.
     610                 :             :  *
     611                 :             :  * Auxiliary processes are presently not expected to wait for real (lockmgr)
     612                 :             :  * locks, so we need not set up the deadlock checker.  They are never added
     613                 :             :  * to the ProcArray or the sinval messaging mechanism, either.  They also
     614                 :             :  * don't get a VXID assigned, since this is only useful when we actually
     615                 :             :  * hold lockmgr locks.
     616                 :             :  *
     617                 :             :  * Startup process however uses locks but never waits for them in the
     618                 :             :  * normal backend sense. Startup process also takes part in sinval messaging
     619                 :             :  * as a sendOnly process, so never reads messages from sinval queue. So
     620                 :             :  * Startup process does have a VXID and does show up in pg_locks.
     621                 :             :  */
     622                 :             : void
     623                 :        4442 : InitAuxiliaryProcess(void)
     624                 :             : {
     625                 :             :     PGPROC     *auxproc;
     626                 :             :     int         proctype;
     627                 :             : 
     628                 :             :     /*
     629                 :             :      * ProcGlobal should be set up already (if we are a backend, we inherit
     630                 :             :      * this by fork() or EXEC_BACKEND mechanism from the postmaster).
     631                 :             :      */
     632   [ +  -  -  + ]:        4442 :     if (ProcGlobal == NULL || AuxiliaryProcs == NULL)
     633         [ #  # ]:           0 :         elog(PANIC, "proc header uninitialized");
     634                 :             : 
     635         [ -  + ]:        4442 :     if (MyProc != NULL)
     636         [ #  # ]:           0 :         elog(ERROR, "you already exist");
     637                 :             : 
     638         [ +  - ]:        4442 :     if (IsUnderPostmaster)
     639                 :        4442 :         RegisterPostmasterChildActive();
     640                 :             : 
     641                 :             :     /*
     642                 :             :      * We use the freeProcsLock to protect assignment and releasing of
     643                 :             :      * AuxiliaryProcs entries.
     644                 :             :      *
     645                 :             :      * While we are holding the spinlock, also copy the current shared
     646                 :             :      * estimate of spins_per_delay to local storage.
     647                 :             :      */
     648                 :        4442 :     SpinLockAcquire(&ProcGlobal->freeProcsLock);
     649                 :             : 
     650                 :        4442 :     set_spins_per_delay(ProcGlobal->spins_per_delay);
     651                 :             : 
     652                 :             :     /*
     653                 :             :      * Find a free auxproc ... *big* trouble if there isn't one ...
     654                 :             :      */
     655         [ +  - ]:       15397 :     for (proctype = 0; proctype < NUM_AUXILIARY_PROCS; proctype++)
     656                 :             :     {
     657                 :       15397 :         auxproc = &AuxiliaryProcs[proctype];
     658         [ +  + ]:       15397 :         if (auxproc->pid == 0)
     659                 :        4442 :             break;
     660                 :             :     }
     661         [ -  + ]:        4442 :     if (proctype >= NUM_AUXILIARY_PROCS)
     662                 :             :     {
     663                 :           0 :         SpinLockRelease(&ProcGlobal->freeProcsLock);
     664         [ #  # ]:           0 :         elog(FATAL, "all AuxiliaryProcs are in use");
     665                 :             :     }
     666                 :             : 
     667                 :             :     /* Mark auxiliary proc as in use by me */
     668                 :        4442 :     auxproc->pid = MyProcPid;
     669                 :             : 
     670                 :        4442 :     SpinLockRelease(&ProcGlobal->freeProcsLock);
     671                 :             : 
     672                 :        4442 :     MyProc = auxproc;
     673                 :        4442 :     MyProcNumber = GetNumberFromPGProc(MyProc);
     674                 :             : 
     675                 :             :     /*
     676                 :             :      * Initialize all fields of MyProc, except for those previously
     677                 :             :      * initialized by ProcGlobalShmemInit.
     678                 :             :      */
     679                 :        4442 :     dlist_node_init(&MyProc->freeProcsLink);
     680                 :        4442 :     MyProc->waitStatus = PROC_WAIT_STATUS_OK;
     681                 :        4442 :     MyProc->fpVXIDLock = false;
     682                 :        4442 :     MyProc->fpLocalTransactionId = InvalidLocalTransactionId;
     683                 :        4442 :     MyProc->xid = InvalidTransactionId;
     684                 :        4442 :     MyProc->xmin = InvalidTransactionId;
     685                 :        4442 :     MyProc->vxid.procNumber = INVALID_PROC_NUMBER;
     686                 :        4442 :     MyProc->vxid.lxid = InvalidLocalTransactionId;
     687                 :        4442 :     MyProc->databaseId = InvalidOid;
     688                 :        4442 :     MyProc->roleId = InvalidOid;
     689                 :        4442 :     MyProc->tempNamespaceId = InvalidOid;
     690                 :        4442 :     MyProc->backendType = MyBackendType;
     691                 :        4442 :     MyProc->delayChkptFlags = 0;
     692                 :        4442 :     MyProc->statusFlags = 0;
     693                 :        4442 :     MyProc->lwWaiting = LW_WS_NOT_WAITING;
     694                 :        4442 :     MyProc->lwWaitMode = 0;
     695                 :        4442 :     MyProc->waitLock = NULL;
     696                 :        4442 :     dlist_node_init(&MyProc->waitLink);
     697                 :        4442 :     MyProc->waitProcLock = NULL;
     698                 :        4442 :     pg_atomic_write_u64(&MyProc->waitStart, 0);
     699                 :             : #ifdef USE_ASSERT_CHECKING
     700                 :             :     {
     701                 :             :         int         i;
     702                 :             : 
     703                 :             :         /* Last process should have released all locks. */
     704                 :             :         for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
     705                 :             :             Assert(dlist_is_empty(&(MyProc->myProcLocks[i])));
     706                 :             :     }
     707                 :             : #endif
     708                 :        4442 :     pg_atomic_write_u32(&MyProc->pendingRecoveryConflicts, 0);
     709                 :             : 
     710                 :             :     /*
     711                 :             :      * Acquire ownership of the PGPROC's latch, so that we can use WaitLatch
     712                 :             :      * on it.  That allows us to repoint the process latch, which so far
     713                 :             :      * points to process local one, to the shared one.
     714                 :             :      */
     715                 :        4442 :     OwnLatch(&MyProc->procLatch);
     716                 :        4442 :     SwitchToSharedLatch();
     717                 :             : 
     718                 :             :     /* now that we have a proc, report wait events to shared memory */
     719                 :        4442 :     pgstat_set_wait_event_storage(&MyProc->wait_event_info);
     720                 :             : 
     721                 :             :     /* Check that group locking fields are in a proper initial state. */
     722                 :             :     Assert(MyProc->lockGroupLeader == NULL);
     723                 :             :     Assert(dlist_is_empty(&MyProc->lockGroupMembers));
     724                 :             : 
     725                 :             :     /*
     726                 :             :      * We might be reusing a semaphore that belonged to a failed process. So
     727                 :             :      * be careful and reinitialize its value here.  (This is not strictly
     728                 :             :      * necessary anymore, but seems like a good idea for cleanliness.)
     729                 :             :      */
     730                 :        4442 :     PGSemaphoreReset(MyProc->sem);
     731                 :             : 
     732                 :             :     /* Some aux processes are also advertised in ProcGlobal */
     733         [ +  + ]:        4442 :     if (MyBackendType == B_WAL_WRITER)
     734                 :         576 :         pg_atomic_write_u32(&ProcGlobal->walwriterProc, MyProcNumber);
     735         [ +  + ]:        4442 :     if (MyBackendType == B_CHECKPOINTER)
     736                 :         642 :         pg_atomic_write_u32(&ProcGlobal->checkpointerProc, MyProcNumber);
     737                 :             : 
     738                 :             :     /*
     739                 :             :      * Arrange to clean up at process exit.
     740                 :             :      */
     741                 :        4442 :     on_shmem_exit(AuxiliaryProcKill, Int32GetDatum(proctype));
     742                 :             : 
     743                 :             :     /*
     744                 :             :      * Now that we have a PGPROC, we could try to acquire lightweight locks.
     745                 :             :      * Initialize local state needed for them.  (Heavyweight locks cannot be
     746                 :             :      * acquired in aux processes.)
     747                 :             :      */
     748                 :        4442 :     InitLWLockAccess();
     749                 :             : 
     750                 :             : #ifdef EXEC_BACKEND
     751                 :             : 
     752                 :             :     /*
     753                 :             :      * Initialize backend-local pointers to all the shared data structures.
     754                 :             :      * (We couldn't do this until now because it needs LWLocks.)
     755                 :             :      */
     756                 :             :     if (IsUnderPostmaster)
     757                 :             :         AttachSharedMemoryStructs();
     758                 :             : #endif
     759                 :        4442 : }
     760                 :             : 
     761                 :             : /*
     762                 :             :  * Used from bufmgr to share the value of the buffer that Startup waits on,
     763                 :             :  * or to reset the value to "not waiting" (-1). This allows processing
     764                 :             :  * of recovery conflicts for buffer pins. Set is made before backends look
     765                 :             :  * at this value, so locking not required, especially since the set is
     766                 :             :  * an atomic integer set operation.
     767                 :             :  */
     768                 :             : void
     769                 :          18 : SetStartupBufferPinWaitBufId(int bufid)
     770                 :             : {
     771                 :             :     /* use volatile pointer to prevent code rearrangement */
     772                 :          18 :     volatile PROC_HDR *procglobal = ProcGlobal;
     773                 :             : 
     774                 :          18 :     procglobal->startupBufferPinWaitBufId = bufid;
     775                 :          18 : }
     776                 :             : 
     777                 :             : /*
     778                 :             :  * Used by backends when they receive a request to check for buffer pin waits.
     779                 :             :  */
     780                 :             : int
     781                 :           3 : GetStartupBufferPinWaitBufId(void)
     782                 :             : {
     783                 :             :     /* use volatile pointer to prevent code rearrangement */
     784                 :           3 :     volatile PROC_HDR *procglobal = ProcGlobal;
     785                 :             : 
     786                 :           3 :     return procglobal->startupBufferPinWaitBufId;
     787                 :             : }
     788                 :             : 
     789                 :             : /*
     790                 :             :  * Check whether there are at least N free PGPROC objects.  If false is
     791                 :             :  * returned, *nfree will be set to the number of free PGPROC objects.
     792                 :             :  * Otherwise, *nfree will be set to n.
     793                 :             :  *
     794                 :             :  * Note: this is designed on the assumption that N will generally be small.
     795                 :             :  */
     796                 :             : bool
     797                 :         284 : HaveNFreeProcs(int n, int *nfree)
     798                 :             : {
     799                 :             :     dlist_iter  iter;
     800                 :             : 
     801                 :             :     Assert(n > 0);
     802                 :             :     Assert(nfree);
     803                 :             : 
     804                 :         284 :     SpinLockAcquire(&ProcGlobal->freeProcsLock);
     805                 :             : 
     806                 :         284 :     *nfree = 0;
     807   [ +  -  +  + ]:         849 :     dlist_foreach(iter, &ProcGlobal->freeProcs)
     808                 :             :     {
     809                 :         845 :         (*nfree)++;
     810         [ +  + ]:         845 :         if (*nfree == n)
     811                 :         280 :             break;
     812                 :             :     }
     813                 :             : 
     814                 :         284 :     SpinLockRelease(&ProcGlobal->freeProcsLock);
     815                 :             : 
     816                 :         284 :     return (*nfree == n);
     817                 :             : }
     818                 :             : 
     819                 :             : /*
     820                 :             :  * Cancel any pending wait for lock, when aborting a transaction, and revert
     821                 :             :  * any strong lock count acquisition for a lock being acquired.
     822                 :             :  *
     823                 :             :  * (Normally, this would only happen if we accept a cancel/die
     824                 :             :  * interrupt while waiting; but an ereport(ERROR) before or during the lock
     825                 :             :  * wait is within the realm of possibility, too.)
     826                 :             :  */
     827                 :             : void
     828                 :      711102 : LockErrorCleanup(void)
     829                 :             : {
     830                 :             :     LOCALLOCK  *lockAwaited;
     831                 :             :     LWLock     *partitionLock;
     832                 :             :     DisableTimeoutParams timeouts[2];
     833                 :             : 
     834                 :      711102 :     HOLD_INTERRUPTS();
     835                 :             : 
     836                 :      711102 :     AbortStrongLockAcquire();
     837                 :             : 
     838                 :             :     /* Nothing to do if we weren't waiting for a lock */
     839                 :      711102 :     lockAwaited = GetAwaitedLock();
     840         [ +  + ]:      711102 :     if (lockAwaited == NULL)
     841                 :             :     {
     842                 :      711060 :         RESUME_INTERRUPTS();
     843                 :      711060 :         return;
     844                 :             :     }
     845                 :             : 
     846                 :             :     /*
     847                 :             :      * Turn off the deadlock and lock timeout timers, if they are still
     848                 :             :      * running (see ProcSleep).  Note we must preserve the LOCK_TIMEOUT
     849                 :             :      * indicator flag, since this function is executed before
     850                 :             :      * ProcessInterrupts when responding to SIGINT; else we'd lose the
     851                 :             :      * knowledge that the SIGINT came from a lock timeout and not an external
     852                 :             :      * source.
     853                 :             :      */
     854                 :          42 :     timeouts[0].id = DEADLOCK_TIMEOUT;
     855                 :          42 :     timeouts[0].keep_indicator = false;
     856                 :          42 :     timeouts[1].id = LOCK_TIMEOUT;
     857                 :          42 :     timeouts[1].keep_indicator = true;
     858                 :          42 :     disable_timeouts(timeouts, 2);
     859                 :             : 
     860                 :             :     /* Unlink myself from the wait queue, if on it (might not be anymore!) */
     861                 :          42 :     partitionLock = LockHashPartitionLock(lockAwaited->hashcode);
     862                 :          42 :     LWLockAcquire(partitionLock, LW_EXCLUSIVE);
     863                 :             : 
     864         [ +  + ]:          42 :     if (!dlist_node_is_detached(&MyProc->waitLink))
     865                 :             :     {
     866                 :             :         /* We could not have been granted the lock yet */
     867                 :          41 :         RemoveFromWaitQueue(MyProc, lockAwaited->hashcode);
     868                 :             :     }
     869                 :             :     else
     870                 :             :     {
     871                 :             :         /*
     872                 :             :          * Somebody kicked us off the lock queue already.  Perhaps they
     873                 :             :          * granted us the lock, or perhaps they detected a deadlock. If they
     874                 :             :          * did grant us the lock, we'd better remember it in our local lock
     875                 :             :          * table.
     876                 :             :          */
     877         [ +  - ]:           1 :         if (MyProc->waitStatus == PROC_WAIT_STATUS_OK)
     878                 :           1 :             GrantAwaitedLock();
     879                 :             :     }
     880                 :             : 
     881                 :          42 :     ResetAwaitedLock();
     882                 :             : 
     883                 :          42 :     LWLockRelease(partitionLock);
     884                 :             : 
     885                 :          42 :     RESUME_INTERRUPTS();
     886                 :             : }
     887                 :             : 
     888                 :             : 
     889                 :             : /*
     890                 :             :  * ProcReleaseLocks() -- release locks associated with current transaction
     891                 :             :  *          at main transaction commit or abort
     892                 :             :  *
     893                 :             :  * At main transaction commit, we release standard locks except session locks.
     894                 :             :  * At main transaction abort, we release all locks including session locks.
     895                 :             :  *
     896                 :             :  * Advisory locks are released only if they are transaction-level;
     897                 :             :  * session-level holds remain, whether this is a commit or not.
     898                 :             :  *
     899                 :             :  * At subtransaction commit, we don't release any locks (so this func is not
     900                 :             :  * needed at all); we will defer the releasing to the parent transaction.
     901                 :             :  * At subtransaction abort, we release all locks held by the subtransaction;
     902                 :             :  * this is implemented by retail releasing of the locks under control of
     903                 :             :  * the ResourceOwner mechanism.
     904                 :             :  */
     905                 :             : void
     906                 :      668841 : ProcReleaseLocks(bool isCommit)
     907                 :             : {
     908         [ -  + ]:      668841 :     if (!MyProc)
     909                 :           0 :         return;
     910                 :             :     /* If waiting, get off wait queue (should only be needed after error) */
     911                 :      668841 :     LockErrorCleanup();
     912                 :             :     /* Release standard locks, including session-level if aborting */
     913                 :      668841 :     LockReleaseAll(DEFAULT_LOCKMETHOD, !isCommit);
     914                 :             :     /* Release transaction-level advisory locks */
     915                 :      668841 :     LockReleaseAll(USER_LOCKMETHOD, false);
     916                 :             : }
     917                 :             : 
     918                 :             : 
     919                 :             : /*
     920                 :             :  * RemoveProcFromArray() -- Remove this process from the shared ProcArray.
     921                 :             :  */
     922                 :             : static void
     923                 :       20581 : RemoveProcFromArray(int code, Datum arg)
     924                 :             : {
     925                 :             :     Assert(MyProc != NULL);
     926                 :       20581 :     ProcArrayRemove(MyProc, InvalidTransactionId);
     927                 :       20581 : }
     928                 :             : 
     929                 :             : /*
     930                 :             :  * ProcKill() -- Destroy the per-proc data structure for
     931                 :             :  *      this process. Release any of its held LW locks.
     932                 :             :  */
     933                 :             : static void
     934                 :       20594 : ProcKill(int code, Datum arg)
     935                 :             : {
     936                 :             :     PGPROC     *proc;
     937                 :             :     PGPROC     *leader;
     938                 :             :     dlist_head *procgloballist;
     939                 :             :     bool        push_leader;
     940                 :             :     bool        push_self;
     941                 :             : 
     942                 :             :     Assert(MyProc != NULL);
     943                 :             : 
     944                 :             :     /* not safe if forked by system(), etc. */
     945         [ -  + ]:       20594 :     if (MyProc->pid != (int) getpid())
     946         [ #  # ]:           0 :         elog(PANIC, "ProcKill() called in child process");
     947                 :             : 
     948                 :             :     /* Make sure we're out of the sync rep lists */
     949                 :       20594 :     SyncRepCleanupAtProcExit();
     950                 :             : 
     951                 :             : #ifdef USE_ASSERT_CHECKING
     952                 :             :     {
     953                 :             :         int         i;
     954                 :             : 
     955                 :             :         /* Last process should have released all locks. */
     956                 :             :         for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
     957                 :             :             Assert(dlist_is_empty(&(MyProc->myProcLocks[i])));
     958                 :             :     }
     959                 :             : #endif
     960                 :             : 
     961                 :             :     /*
     962                 :             :      * Release any LW locks I am holding.  There really shouldn't be any, but
     963                 :             :      * it's cheap to check again before we cut the knees off the LWLock
     964                 :             :      * facility by releasing our PGPROC ...
     965                 :             :      */
     966                 :       20594 :     LWLockReleaseAll();
     967                 :             : 
     968                 :             :     /*
     969                 :             :      * Cleanup waiting for LSN if any.
     970                 :             :      */
     971                 :       20594 :     WaitLSNCleanup();
     972                 :             : 
     973                 :             :     /* Cancel any pending condition variable sleep, too */
     974                 :       20594 :     ConditionVariableCancelSleep();
     975                 :             : 
     976                 :             :     /*
     977                 :             :      * Reset MyLatch to the process local one and disown the shared latch, so
     978                 :             :      * that signal handlers et al can continue using the latch after the
     979                 :             :      * shared latch isn't ours anymore.
     980                 :             :      *
     981                 :             :      * DisownLatch() must happen before our PGPROC can appear on a freelist: a
     982                 :             :      * newly-forked backend that pops our slot and calls OwnLatch() would
     983                 :             :      * PANIC on a still-owned latch.
     984                 :             :      *
     985                 :             :      * pgstat_reset_wait_event_storage() is intentionally deferred until after
     986                 :             :      * the lock-group block so that wait_event_info remains visible in our
     987                 :             :      * PGPROC slot while we may be observed there.  It is safe to defer
     988                 :             :      * because our slot is not yet on any freelist at this point, and useful
     989                 :             :      * for testing purposes.
     990                 :             :      */
     991                 :       20594 :     SwitchBackToLocalLatch();
     992                 :       20594 :     DisownLatch(&MyProc->procLatch);
     993                 :             : 
     994         [ +  + ]:       20594 :     if (MyBackendType == B_AUTOVAC_LAUNCHER)
     995                 :             :     {
     996                 :             :         Assert(pg_atomic_read_u32(&ProcGlobal->avLauncherProc) == MyProcNumber);
     997                 :         480 :         pg_atomic_write_u32(&ProcGlobal->avLauncherProc, INVALID_PROC_NUMBER);
     998                 :             :     }
     999                 :             : 
    1000                 :       20594 :     proc = MyProc;
    1001                 :       20594 :     procgloballist = proc->procgloballist;
    1002                 :             : 
    1003                 :             :     /*
    1004                 :             :      * Detach from any lock group of which we are a member, deciding under
    1005                 :             :      * leader_lwlock whether we (via push_self) and/or the leader (via
    1006                 :             :      * push_leader) need to be pushed onto a freelist.  The actual pushes
    1007                 :             :      * happen after evaluating if any of these are required, under a single
    1008                 :             :      * ProcGlobal->freeProcsLock.
    1009                 :             :      *
    1010                 :             :      * The decision whether any of the freelists needs to be updated is taken
    1011                 :             :      * under a single leader_lwlock.
    1012                 :             :      */
    1013                 :       20594 :     push_leader = false;
    1014                 :       20594 :     push_self = true;
    1015                 :       20594 :     leader = NULL;
    1016                 :             : 
    1017         [ +  + ]:       20594 :     if (proc->lockGroupLeader != NULL)
    1018                 :             :     {
    1019                 :             :         LWLock     *leader_lwlock;
    1020                 :             : 
    1021                 :        2142 :         leader = proc->lockGroupLeader;
    1022                 :        2142 :         leader_lwlock = LockHashPartitionLockByProc(leader);
    1023                 :             : 
    1024                 :        2142 :         LWLockAcquire(leader_lwlock, LW_EXCLUSIVE);
    1025                 :             :         Assert(!dlist_is_empty(&leader->lockGroupMembers));
    1026                 :        2142 :         dlist_delete(&proc->lockGroupLink);
    1027         [ +  + ]:        2142 :         if (dlist_is_empty(&leader->lockGroupMembers))
    1028                 :             :         {
    1029                 :         124 :             leader->lockGroupLeader = NULL;
    1030         [ -  + ]:         124 :             if (leader != proc)
    1031                 :             :             {
    1032                 :             :                 /*
    1033                 :             :                  * We are the last follower and the leader exited earlier; its
    1034                 :             :                  * PGPROC is still allocated and must be pushed here.
    1035                 :             :                  */
    1036                 :           0 :                 push_leader = true;
    1037                 :           0 :                 proc->lockGroupLeader = NULL;
    1038                 :             :             }
    1039                 :             :         }
    1040         [ +  - ]:        2018 :         else if (leader != proc)
    1041                 :             :         {
    1042                 :             :             /* Non-last follower; leader still present in the group. */
    1043                 :        2018 :             proc->lockGroupLeader = NULL;
    1044                 :             :         }
    1045                 :             :         else
    1046                 :             :         {
    1047                 :             :             /*
    1048                 :             :              * We are the leader and followers remain.  Skip our own push; the
    1049                 :             :              * last follower to exit will push us back to the freelist.
    1050                 :             :              */
    1051                 :           0 :             push_self = false;
    1052                 :             :         }
    1053                 :        2142 :         LWLockRelease(leader_lwlock);
    1054                 :             :     }
    1055                 :             : 
    1056                 :             :     /* See comment above, close to DisownLatch() */
    1057                 :       20594 :     pgstat_reset_wait_event_storage();
    1058                 :             : 
    1059                 :       20594 :     MyProc = NULL;
    1060                 :       20594 :     MyProcNumber = INVALID_PROC_NUMBER;
    1061                 :             : 
    1062                 :             :     /* Mark the proc no longer in use */
    1063                 :       20594 :     proc->pid = 0;
    1064                 :       20594 :     proc->vxid.procNumber = INVALID_PROC_NUMBER;
    1065                 :       20594 :     proc->vxid.lxid = InvalidTransactionId;
    1066                 :             : 
    1067                 :       20594 :     SpinLockAcquire(&ProcGlobal->freeProcsLock);
    1068         [ -  + ]:       20594 :     if (push_leader)
    1069                 :             :     {
    1070                 :             :         /* Return leader PGPROC (and semaphore) to appropriate freelist */
    1071                 :           0 :         dlist_push_head(leader->procgloballist, &leader->freeProcsLink);
    1072                 :             :     }
    1073         [ +  - ]:       20594 :     if (push_self)
    1074                 :             :     {
    1075                 :             :         Assert(proc->lockGroupLeader == NULL);
    1076                 :             :         /* Since lockGroupLeader is NULL, lockGroupMembers should be empty. */
    1077                 :             :         Assert(dlist_is_empty(&proc->lockGroupMembers));
    1078                 :             : 
    1079                 :             :         /* Return PGPROC structure (and semaphore) to appropriate freelist */
    1080                 :       20594 :         dlist_push_tail(procgloballist, &proc->freeProcsLink);
    1081                 :             :     }
    1082                 :             : 
    1083                 :             :     /* Update shared estimate of spins_per_delay */
    1084                 :       20594 :     ProcGlobal->spins_per_delay = update_spins_per_delay(ProcGlobal->spins_per_delay);
    1085                 :             : 
    1086                 :       20594 :     SpinLockRelease(&ProcGlobal->freeProcsLock);
    1087                 :       20594 : }
    1088                 :             : 
    1089                 :             : /*
    1090                 :             :  * AuxiliaryProcKill() -- Cut-down version of ProcKill for auxiliary
    1091                 :             :  *      processes (bgwriter, etc).  The PGPROC and sema are not released, only
    1092                 :             :  *      marked as not-in-use.
    1093                 :             :  */
    1094                 :             : static void
    1095                 :        4442 : AuxiliaryProcKill(int code, Datum arg)
    1096                 :             : {
    1097                 :        4442 :     int         proctype = DatumGetInt32(arg);
    1098                 :             :     PGPROC     *auxproc PG_USED_FOR_ASSERTS_ONLY;
    1099                 :             :     PGPROC     *proc;
    1100                 :             : 
    1101                 :             :     Assert(proctype >= 0 && proctype < NUM_AUXILIARY_PROCS);
    1102                 :             : 
    1103                 :             :     /* not safe if forked by system(), etc. */
    1104         [ -  + ]:        4442 :     if (MyProc->pid != (int) getpid())
    1105         [ #  # ]:           0 :         elog(PANIC, "AuxiliaryProcKill() called in child process");
    1106                 :             : 
    1107                 :        4442 :     auxproc = &AuxiliaryProcs[proctype];
    1108                 :             : 
    1109                 :             :     Assert(MyProc == auxproc);
    1110                 :             : 
    1111                 :             :     /* Release any LW locks I am holding (see notes above) */
    1112                 :        4442 :     LWLockReleaseAll();
    1113                 :             : 
    1114                 :             :     /* Cancel any pending condition variable sleep, too */
    1115                 :        4442 :     ConditionVariableCancelSleep();
    1116                 :             : 
    1117                 :             :     /* look at the equivalent ProcKill() code for comments */
    1118                 :        4442 :     SwitchBackToLocalLatch();
    1119                 :        4442 :     pgstat_reset_wait_event_storage();
    1120                 :             : 
    1121                 :             :     /*
    1122                 :             :      * If this was one of the aux processes advertised in ProcGlobal, clear it
    1123                 :             :      */
    1124         [ +  + ]:        4442 :     if (MyBackendType == B_WAL_WRITER)
    1125                 :             :     {
    1126                 :             :         Assert(pg_atomic_read_u32(&ProcGlobal->walwriterProc) == MyProcNumber);
    1127                 :         576 :         pg_atomic_write_u32(&ProcGlobal->walwriterProc, INVALID_PROC_NUMBER);
    1128                 :             :     }
    1129         [ +  + ]:        4442 :     if (MyBackendType == B_CHECKPOINTER)
    1130                 :             :     {
    1131                 :             :         Assert(pg_atomic_read_u32(&ProcGlobal->checkpointerProc) == MyProcNumber);
    1132                 :         642 :         pg_atomic_write_u32(&ProcGlobal->checkpointerProc, INVALID_PROC_NUMBER);
    1133                 :             :     }
    1134                 :             : 
    1135                 :        4442 :     proc = MyProc;
    1136                 :        4442 :     MyProc = NULL;
    1137                 :        4442 :     MyProcNumber = INVALID_PROC_NUMBER;
    1138                 :        4442 :     DisownLatch(&proc->procLatch);
    1139                 :             : 
    1140                 :        4442 :     SpinLockAcquire(&ProcGlobal->freeProcsLock);
    1141                 :             : 
    1142                 :             :     /* Mark auxiliary proc no longer in use */
    1143                 :        4442 :     proc->pid = 0;
    1144                 :        4442 :     proc->vxid.procNumber = INVALID_PROC_NUMBER;
    1145                 :        4442 :     proc->vxid.lxid = InvalidTransactionId;
    1146                 :             : 
    1147                 :             :     /* Update shared estimate of spins_per_delay */
    1148                 :        4442 :     ProcGlobal->spins_per_delay = update_spins_per_delay(ProcGlobal->spins_per_delay);
    1149                 :             : 
    1150                 :        4442 :     SpinLockRelease(&ProcGlobal->freeProcsLock);
    1151                 :        4442 : }
    1152                 :             : 
    1153                 :             : /*
    1154                 :             :  * AuxiliaryPidGetProc -- get PGPROC for an auxiliary process
    1155                 :             :  * given its PID
    1156                 :             :  *
    1157                 :             :  * Returns NULL if not found.
    1158                 :             :  */
    1159                 :             : PGPROC *
    1160                 :        3810 : AuxiliaryPidGetProc(int pid)
    1161                 :             : {
    1162                 :        3810 :     PGPROC     *result = NULL;
    1163                 :             :     int         index;
    1164                 :             : 
    1165         [ +  + ]:        3810 :     if (pid == 0)               /* never match dummy PGPROCs */
    1166                 :           4 :         return NULL;
    1167                 :             : 
    1168         [ +  - ]:       14191 :     for (index = 0; index < NUM_AUXILIARY_PROCS; index++)
    1169                 :             :     {
    1170                 :       14191 :         PGPROC     *proc = &AuxiliaryProcs[index];
    1171                 :             : 
    1172         [ +  + ]:       14191 :         if (proc->pid == pid)
    1173                 :             :         {
    1174                 :        3806 :             result = proc;
    1175                 :        3806 :             break;
    1176                 :             :         }
    1177                 :             :     }
    1178                 :        3806 :     return result;
    1179                 :             : }
    1180                 :             : 
    1181                 :             : 
    1182                 :             : /*
    1183                 :             :  * JoinWaitQueue -- join the wait queue on the specified lock
    1184                 :             :  *
    1185                 :             :  * It's not actually guaranteed that we need to wait when this function is
    1186                 :             :  * called, because it could be that when we try to find a position at which
    1187                 :             :  * to insert ourself into the wait queue, we discover that we must be inserted
    1188                 :             :  * ahead of everyone who wants a lock that conflict with ours. In that case,
    1189                 :             :  * we get the lock immediately. Because of this, it's sensible for this function
    1190                 :             :  * to have a dontWait argument, despite the name.
    1191                 :             :  *
    1192                 :             :  * On entry, the caller has already set up LOCK and PROCLOCK entries to
    1193                 :             :  * reflect that we have "requested" the lock.  The caller is responsible for
    1194                 :             :  * cleaning that up, if we end up not joining the queue after all.
    1195                 :             :  *
    1196                 :             :  * The lock table's partition lock must be held at entry, and is still held
    1197                 :             :  * at exit.  The caller must release it before calling ProcSleep().
    1198                 :             :  *
    1199                 :             :  * Result is one of the following:
    1200                 :             :  *
    1201                 :             :  *  PROC_WAIT_STATUS_OK       - lock was immediately granted
    1202                 :             :  *  PROC_WAIT_STATUS_WAITING  - joined the wait queue; call ProcSleep()
    1203                 :             :  *  PROC_WAIT_STATUS_ERROR    - immediate deadlock was detected, or would
    1204                 :             :  *                              need to wait and dontWait == true
    1205                 :             :  *
    1206                 :             :  * NOTES: The process queue is now a priority queue for locking.
    1207                 :             :  */
    1208                 :             : ProcWaitStatus
    1209                 :        2206 : JoinWaitQueue(LOCALLOCK *locallock, LockMethod lockMethodTable, bool dontWait)
    1210                 :             : {
    1211                 :        2206 :     LOCKMODE    lockmode = locallock->tag.mode;
    1212                 :        2206 :     LOCK       *lock = locallock->lock;
    1213                 :        2206 :     PROCLOCK   *proclock = locallock->proclock;
    1214                 :        2206 :     uint32      hashcode = locallock->hashcode;
    1215                 :        2206 :     LWLock     *partitionLock PG_USED_FOR_ASSERTS_ONLY = LockHashPartitionLock(hashcode);
    1216                 :        2206 :     dclist_head *waitQueue = &lock->waitProcs;
    1217                 :        2206 :     PGPROC     *insert_before = NULL;
    1218                 :             :     LOCKMASK    myProcHeldLocks;
    1219                 :             :     LOCKMASK    myHeldLocks;
    1220                 :        2206 :     bool        early_deadlock = false;
    1221                 :        2206 :     PGPROC     *leader = MyProc->lockGroupLeader;
    1222                 :             : 
    1223                 :             :     Assert(LWLockHeldByMeInMode(partitionLock, LW_EXCLUSIVE));
    1224                 :             : 
    1225                 :             :     /*
    1226                 :             :      * Set bitmask of locks this process already holds on this object.
    1227                 :             :      */
    1228                 :        2206 :     myHeldLocks = MyProc->heldLocks = proclock->holdMask;
    1229                 :             : 
    1230                 :             :     /*
    1231                 :             :      * Determine which locks we're already holding.
    1232                 :             :      *
    1233                 :             :      * If group locking is in use, locks held by members of my locking group
    1234                 :             :      * need to be included in myHeldLocks.  This is not required for relation
    1235                 :             :      * extension lock which conflict among group members. However, including
    1236                 :             :      * them in myHeldLocks will give group members the priority to get those
    1237                 :             :      * locks as compared to other backends which are also trying to acquire
    1238                 :             :      * those locks.  OTOH, we can avoid giving priority to group members for
    1239                 :             :      * that kind of locks, but there doesn't appear to be a clear advantage of
    1240                 :             :      * the same.
    1241                 :             :      */
    1242                 :        2206 :     myProcHeldLocks = proclock->holdMask;
    1243                 :        2206 :     myHeldLocks = myProcHeldLocks;
    1244         [ +  + ]:        2206 :     if (leader != NULL)
    1245                 :             :     {
    1246                 :             :         dlist_iter  iter;
    1247                 :             : 
    1248   [ +  -  +  + ]:          42 :         dlist_foreach(iter, &lock->procLocks)
    1249                 :             :         {
    1250                 :             :             PROCLOCK   *otherproclock;
    1251                 :             : 
    1252                 :          31 :             otherproclock = dlist_container(PROCLOCK, lockLink, iter.cur);
    1253                 :             : 
    1254         [ +  + ]:          31 :             if (otherproclock->groupLeader == leader)
    1255                 :          15 :                 myHeldLocks |= otherproclock->holdMask;
    1256                 :             :         }
    1257                 :             :     }
    1258                 :             : 
    1259                 :             :     /*
    1260                 :             :      * Determine where to add myself in the wait queue.
    1261                 :             :      *
    1262                 :             :      * Normally I should go at the end of the queue.  However, if I already
    1263                 :             :      * hold locks that conflict with the request of any previous waiter, put
    1264                 :             :      * myself in the queue just in front of the first such waiter. This is not
    1265                 :             :      * a necessary step, since deadlock detection would move me to before that
    1266                 :             :      * waiter anyway; but it's relatively cheap to detect such a conflict
    1267                 :             :      * immediately, and avoid delaying till deadlock timeout.
    1268                 :             :      *
    1269                 :             :      * Special case: if I find I should go in front of some waiter, check to
    1270                 :             :      * see if I conflict with already-held locks or the requests before that
    1271                 :             :      * waiter.  If not, then just grant myself the requested lock immediately.
    1272                 :             :      * This is the same as the test for immediate grant in LockAcquire, except
    1273                 :             :      * we are only considering the part of the wait queue before my insertion
    1274                 :             :      * point.
    1275                 :             :      */
    1276   [ +  +  +  + ]:        2206 :     if (myHeldLocks != 0 && !dclist_is_empty(waitQueue))
    1277                 :             :     {
    1278                 :           7 :         LOCKMASK    aheadRequests = 0;
    1279                 :             :         dlist_iter  iter;
    1280                 :             : 
    1281   [ +  -  +  - ]:           7 :         dclist_foreach(iter, waitQueue)
    1282                 :             :         {
    1283                 :           7 :             PGPROC     *proc = dlist_container(PGPROC, waitLink, iter.cur);
    1284                 :             : 
    1285                 :             :             /*
    1286                 :             :              * If we're part of the same locking group as this waiter, its
    1287                 :             :              * locks neither conflict with ours nor contribute to
    1288                 :             :              * aheadRequests.
    1289                 :             :              */
    1290   [ -  +  -  - ]:           7 :             if (leader != NULL && leader == proc->lockGroupLeader)
    1291                 :           0 :                 continue;
    1292                 :             : 
    1293                 :             :             /* Must he wait for me? */
    1294         [ +  - ]:           7 :             if (lockMethodTable->conflictTab[proc->waitLockMode] & myHeldLocks)
    1295                 :             :             {
    1296                 :             :                 /* Must I wait for him ? */
    1297         [ +  + ]:           7 :                 if (lockMethodTable->conflictTab[lockmode] & proc->heldLocks)
    1298                 :             :                 {
    1299                 :             :                     /*
    1300                 :             :                      * Yes, so we have a deadlock.  Easiest way to clean up
    1301                 :             :                      * correctly is to call RemoveFromWaitQueue(), but we
    1302                 :             :                      * can't do that until we are *on* the wait queue. So, set
    1303                 :             :                      * a flag to check below, and break out of loop.  Also,
    1304                 :             :                      * record deadlock info for later message.
    1305                 :             :                      */
    1306                 :           1 :                     RememberSimpleDeadLock(MyProc, lockmode, lock, proc);
    1307                 :           1 :                     early_deadlock = true;
    1308                 :           1 :                     break;
    1309                 :             :                 }
    1310                 :             :                 /* I must go before this waiter.  Check special case. */
    1311         [ +  - ]:           6 :                 if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
    1312         [ +  - ]:           6 :                     !LockCheckConflicts(lockMethodTable, lockmode, lock,
    1313                 :             :                                         proclock))
    1314                 :             :                 {
    1315                 :             :                     /* Skip the wait and just grant myself the lock. */
    1316                 :           6 :                     GrantLock(lock, proclock, lockmode);
    1317                 :           6 :                     return PROC_WAIT_STATUS_OK;
    1318                 :             :                 }
    1319                 :             : 
    1320                 :             :                 /* Put myself into wait queue before conflicting process */
    1321                 :           0 :                 insert_before = proc;
    1322                 :           0 :                 break;
    1323                 :             :             }
    1324                 :             :             /* Nope, so advance to next waiter */
    1325                 :           0 :             aheadRequests |= LOCKBIT_ON(proc->waitLockMode);
    1326                 :             :         }
    1327                 :             :     }
    1328                 :             : 
    1329                 :             :     /*
    1330                 :             :      * If we detected deadlock, give up without waiting.  This must agree with
    1331                 :             :      * CheckDeadLock's recovery code.
    1332                 :             :      */
    1333         [ +  + ]:        2200 :     if (early_deadlock)
    1334                 :           1 :         return PROC_WAIT_STATUS_ERROR;
    1335                 :             : 
    1336                 :             :     /*
    1337                 :             :      * At this point we know that we'd really need to sleep. If we've been
    1338                 :             :      * commanded not to do that, bail out.
    1339                 :             :      */
    1340         [ +  + ]:        2199 :     if (dontWait)
    1341                 :         735 :         return PROC_WAIT_STATUS_ERROR;
    1342                 :             : 
    1343                 :             :     /*
    1344                 :             :      * Insert self into queue, at the position determined above.
    1345                 :             :      */
    1346         [ -  + ]:        1464 :     if (insert_before)
    1347                 :           0 :         dclist_insert_before(waitQueue, &insert_before->waitLink, &MyProc->waitLink);
    1348                 :             :     else
    1349                 :        1464 :         dclist_push_tail(waitQueue, &MyProc->waitLink);
    1350                 :             : 
    1351                 :        1464 :     lock->waitMask |= LOCKBIT_ON(lockmode);
    1352                 :             : 
    1353                 :             :     /* Set up wait information in PGPROC object, too */
    1354                 :        1464 :     MyProc->heldLocks = myProcHeldLocks;
    1355                 :        1464 :     MyProc->waitLock = lock;
    1356                 :        1464 :     MyProc->waitProcLock = proclock;
    1357                 :        1464 :     MyProc->waitLockMode = lockmode;
    1358                 :             : 
    1359                 :        1464 :     MyProc->waitStatus = PROC_WAIT_STATUS_WAITING;
    1360                 :             : 
    1361                 :        1464 :     return PROC_WAIT_STATUS_WAITING;
    1362                 :             : }
    1363                 :             : 
    1364                 :             : /*
    1365                 :             :  * ProcSleep -- put process to sleep waiting on lock
    1366                 :             :  *
    1367                 :             :  * This must be called when JoinWaitQueue() returns PROC_WAIT_STATUS_WAITING.
    1368                 :             :  * Returns after the lock has been granted, or if a deadlock is detected.  Can
    1369                 :             :  * also bail out with ereport(ERROR), if some other error condition, or a
    1370                 :             :  * timeout or cancellation is triggered.
    1371                 :             :  *
    1372                 :             :  * Result is one of the following:
    1373                 :             :  *
    1374                 :             :  *  PROC_WAIT_STATUS_OK      - lock was granted
    1375                 :             :  *  PROC_WAIT_STATUS_ERROR   - a deadlock was detected
    1376                 :             :  */
    1377                 :             : ProcWaitStatus
    1378                 :        1464 : ProcSleep(LOCALLOCK *locallock)
    1379                 :             : {
    1380                 :        1464 :     LOCKMODE    lockmode = locallock->tag.mode;
    1381                 :        1464 :     LOCK       *lock = locallock->lock;
    1382                 :        1464 :     uint32      hashcode = locallock->hashcode;
    1383                 :        1464 :     LWLock     *partitionLock = LockHashPartitionLock(hashcode);
    1384                 :        1464 :     TimestampTz standbyWaitStart = 0;
    1385                 :        1464 :     bool        allow_autovacuum_cancel = true;
    1386                 :        1464 :     bool        logged_recovery_conflict = false;
    1387                 :        1464 :     bool        logged_lock_wait = false;
    1388                 :             :     ProcWaitStatus myWaitStatus;
    1389                 :             :     DeadLockState deadlock_state;
    1390                 :             : 
    1391                 :             :     /* The caller must've armed the on-error cleanup mechanism */
    1392                 :             :     Assert(GetAwaitedLock() == locallock);
    1393                 :             :     Assert(!LWLockHeldByMe(partitionLock));
    1394                 :             : 
    1395                 :             :     /*
    1396                 :             :      * Now that we will successfully clean up after an ereport, it's safe to
    1397                 :             :      * check to see if there's a buffer pin deadlock against the Startup
    1398                 :             :      * process.  Of course, that's only necessary if we're doing Hot Standby
    1399                 :             :      * and are not the Startup process ourselves.
    1400                 :             :      */
    1401   [ +  +  +  + ]:        1464 :     if (RecoveryInProgress() && !InRecovery)
    1402                 :           1 :         CheckRecoveryConflictDeadlock();
    1403                 :             : 
    1404                 :             :     /* Reset deadlock_state before enabling the timeout handler */
    1405                 :        1464 :     deadlock_state = DS_NOT_YET_CHECKED;
    1406                 :        1464 :     got_deadlock_timeout = false;
    1407                 :             : 
    1408                 :             :     /*
    1409                 :             :      * Set timer so we can wake up after awhile and check for a deadlock. If a
    1410                 :             :      * deadlock is detected, the handler sets MyProc->waitStatus =
    1411                 :             :      * PROC_WAIT_STATUS_ERROR, allowing us to know that we must report failure
    1412                 :             :      * rather than success.
    1413                 :             :      *
    1414                 :             :      * By delaying the check until we've waited for a bit, we can avoid
    1415                 :             :      * running the rather expensive deadlock-check code in most cases.
    1416                 :             :      *
    1417                 :             :      * If LockTimeout is set, also enable the timeout for that.  We can save a
    1418                 :             :      * few cycles by enabling both timeout sources in one call.
    1419                 :             :      *
    1420                 :             :      * If InHotStandby we set lock waits slightly later for clarity with other
    1421                 :             :      * code.
    1422                 :             :      */
    1423         [ +  + ]:        1464 :     if (!InHotStandby)
    1424                 :             :     {
    1425         [ +  + ]:        1463 :         if (LockTimeout > 0)
    1426                 :             :         {
    1427                 :             :             EnableTimeoutParams timeouts[2];
    1428                 :             : 
    1429                 :         114 :             timeouts[0].id = DEADLOCK_TIMEOUT;
    1430                 :         114 :             timeouts[0].type = TMPARAM_AFTER;
    1431                 :         114 :             timeouts[0].delay_ms = DeadlockTimeout;
    1432                 :         114 :             timeouts[1].id = LOCK_TIMEOUT;
    1433                 :         114 :             timeouts[1].type = TMPARAM_AFTER;
    1434                 :         114 :             timeouts[1].delay_ms = LockTimeout;
    1435                 :         114 :             enable_timeouts(timeouts, 2);
    1436                 :             :         }
    1437                 :             :         else
    1438                 :        1349 :             enable_timeout_after(DEADLOCK_TIMEOUT, DeadlockTimeout);
    1439                 :             : 
    1440                 :             :         /*
    1441                 :             :          * Use the current time obtained for the deadlock timeout timer as
    1442                 :             :          * waitStart (i.e., the time when this process started waiting for the
    1443                 :             :          * lock). Since getting the current time newly can cause overhead, we
    1444                 :             :          * reuse the already-obtained time to avoid that overhead.
    1445                 :             :          *
    1446                 :             :          * Note that waitStart is updated without holding the lock table's
    1447                 :             :          * partition lock, to avoid the overhead by additional lock
    1448                 :             :          * acquisition. This can cause "waitstart" in pg_locks to become NULL
    1449                 :             :          * for a very short period of time after the wait started even though
    1450                 :             :          * "granted" is false. This is OK in practice because we can assume
    1451                 :             :          * that users are likely to look at "waitstart" when waiting for the
    1452                 :             :          * lock for a long time.
    1453                 :             :          */
    1454                 :        1463 :         pg_atomic_write_u64(&MyProc->waitStart,
    1455                 :        1463 :                             get_timeout_start_time(DEADLOCK_TIMEOUT));
    1456                 :             :     }
    1457         [ +  - ]:           1 :     else if (log_recovery_conflict_waits)
    1458                 :             :     {
    1459                 :             :         /*
    1460                 :             :          * Set the wait start timestamp if logging is enabled and in hot
    1461                 :             :          * standby.
    1462                 :             :          */
    1463                 :           1 :         standbyWaitStart = GetCurrentTimestamp();
    1464                 :             :     }
    1465                 :             : 
    1466                 :             :     /*
    1467                 :             :      * If somebody wakes us between LWLockRelease and WaitLatch, the latch
    1468                 :             :      * will not wait. But a set latch does not necessarily mean that the lock
    1469                 :             :      * is free now, as there are many other sources for latch sets than
    1470                 :             :      * somebody releasing the lock.
    1471                 :             :      *
    1472                 :             :      * We process interrupts whenever the latch has been set, so cancel/die
    1473                 :             :      * interrupts are processed quickly. This means we must not mind losing
    1474                 :             :      * control to a cancel/die interrupt here.  We don't, because we have no
    1475                 :             :      * shared-state-change work to do after being granted the lock (the
    1476                 :             :      * grantor did it all).  We do have to worry about canceling the deadlock
    1477                 :             :      * timeout and updating the locallock table, but if we lose control to an
    1478                 :             :      * error, LockErrorCleanup will fix that up.
    1479                 :             :      */
    1480                 :             :     do
    1481                 :             :     {
    1482         [ +  + ]:        3497 :         if (InHotStandby)
    1483                 :             :         {
    1484                 :           4 :             bool        maybe_log_conflict =
    1485   [ +  -  +  + ]:           4 :                 (standbyWaitStart != 0 && !logged_recovery_conflict);
    1486                 :             : 
    1487                 :             :             /* Set a timer and wait for that or for the lock to be granted */
    1488                 :           4 :             ResolveRecoveryConflictWithLock(locallock->tag.lock,
    1489                 :             :                                             maybe_log_conflict);
    1490                 :             : 
    1491                 :             :             /*
    1492                 :             :              * Emit the log message if the startup process is waiting longer
    1493                 :             :              * than deadlock_timeout for recovery conflict on lock.
    1494                 :             :              */
    1495         [ +  + ]:           4 :             if (maybe_log_conflict)
    1496                 :             :             {
    1497                 :           2 :                 TimestampTz now = GetCurrentTimestamp();
    1498                 :             : 
    1499         [ +  + ]:           2 :                 if (TimestampDifferenceExceeds(standbyWaitStart, now,
    1500                 :             :                                                DeadlockTimeout))
    1501                 :             :                 {
    1502                 :             :                     VirtualTransactionId *vxids;
    1503                 :             :                     int         cnt;
    1504                 :             : 
    1505                 :           1 :                     vxids = GetLockConflicts(&locallock->tag.lock,
    1506                 :             :                                              AccessExclusiveLock, &cnt);
    1507                 :             : 
    1508                 :             :                     /*
    1509                 :             :                      * Log the recovery conflict and the list of PIDs of
    1510                 :             :                      * backends holding the conflicting lock. Note that we do
    1511                 :             :                      * logging even if there are no such backends right now
    1512                 :             :                      * because the startup process here has already waited
    1513                 :             :                      * longer than deadlock_timeout.
    1514                 :             :                      */
    1515                 :           1 :                     LogRecoveryConflict(RECOVERY_CONFLICT_LOCK,
    1516                 :             :                                         standbyWaitStart, now,
    1517         [ +  - ]:           1 :                                         cnt > 0 ? vxids : NULL, true);
    1518                 :           1 :                     logged_recovery_conflict = true;
    1519                 :             :                 }
    1520                 :             :             }
    1521                 :             :         }
    1522                 :             :         else
    1523                 :             :         {
    1524                 :        3493 :             (void) WaitLatch(MyLatch, WL_LATCH_SET | WL_EXIT_ON_PM_DEATH, 0,
    1525                 :        3493 :                              PG_WAIT_LOCK | locallock->tag.lock.locktag_type);
    1526                 :        3493 :             ResetLatch(MyLatch);
    1527                 :             :             /* check for deadlocks first, as that's probably log-worthy */
    1528         [ +  + ]:        3493 :             if (got_deadlock_timeout)
    1529                 :             :             {
    1530                 :          35 :                 deadlock_state = CheckDeadLock();
    1531                 :          35 :                 got_deadlock_timeout = false;
    1532                 :             :             }
    1533         [ +  + ]:        3493 :             CHECK_FOR_INTERRUPTS();
    1534                 :             :         }
    1535                 :             : 
    1536                 :             :         /*
    1537                 :             :          * waitStatus could change from PROC_WAIT_STATUS_WAITING to something
    1538                 :             :          * else asynchronously.  Read it just once per loop to prevent
    1539                 :             :          * surprising behavior (such as missing log messages).
    1540                 :             :          */
    1541                 :        3454 :         myWaitStatus = *((volatile ProcWaitStatus *) &MyProc->waitStatus);
    1542                 :             : 
    1543                 :             :         /*
    1544                 :             :          * If we are not deadlocked, but are waiting on an autovacuum-induced
    1545                 :             :          * task, send a signal to interrupt it.
    1546                 :             :          */
    1547   [ -  +  -  - ]:        3454 :         if (deadlock_state == DS_BLOCKED_BY_AUTOVACUUM && allow_autovacuum_cancel)
    1548                 :             :         {
    1549                 :           0 :             PGPROC     *autovac = GetBlockingAutoVacuumPgproc();
    1550                 :             :             uint8       statusFlags;
    1551                 :             :             uint8       lockmethod_copy;
    1552                 :             :             LOCKTAG     locktag_copy;
    1553                 :             : 
    1554                 :             :             /*
    1555                 :             :              * Grab info we need, then release lock immediately.  Note this
    1556                 :             :              * coding means that there is a tiny chance that the process
    1557                 :             :              * terminates its current transaction and starts a different one
    1558                 :             :              * before we have a change to send the signal; the worst possible
    1559                 :             :              * consequence is that a for-wraparound vacuum is canceled.  But
    1560                 :             :              * that could happen in any case unless we were to do kill() with
    1561                 :             :              * the lock held, which is much more undesirable.
    1562                 :             :              */
    1563                 :           0 :             LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
    1564                 :           0 :             statusFlags = ProcGlobal->statusFlags[autovac->pgxactoff];
    1565                 :           0 :             lockmethod_copy = lock->tag.locktag_lockmethodid;
    1566                 :           0 :             locktag_copy = lock->tag;
    1567                 :           0 :             LWLockRelease(ProcArrayLock);
    1568                 :             : 
    1569                 :             :             /*
    1570                 :             :              * Only do it if the worker is not working to protect against Xid
    1571                 :             :              * wraparound.
    1572                 :             :              */
    1573         [ #  # ]:           0 :             if ((statusFlags & PROC_IS_AUTOVACUUM) &&
    1574         [ #  # ]:           0 :                 !(statusFlags & PROC_VACUUM_FOR_WRAPAROUND))
    1575                 :             :             {
    1576                 :           0 :                 int         pid = autovac->pid;
    1577                 :             : 
    1578                 :             :                 /* report the case, if configured to do so */
    1579         [ #  # ]:           0 :                 if (message_level_is_interesting(DEBUG1))
    1580                 :             :                 {
    1581                 :             :                     StringInfoData locktagbuf;
    1582                 :             :                     StringInfoData logbuf;  /* errdetail for server log */
    1583                 :             : 
    1584                 :           0 :                     initStringInfo(&locktagbuf);
    1585                 :           0 :                     initStringInfo(&logbuf);
    1586                 :           0 :                     DescribeLockTag(&locktagbuf, &locktag_copy);
    1587                 :           0 :                     appendStringInfo(&logbuf,
    1588                 :             :                                      "Process %d waits for %s on %s.",
    1589                 :             :                                      MyProcPid,
    1590                 :             :                                      GetLockmodeName(lockmethod_copy, lockmode),
    1591                 :             :                                      locktagbuf.data);
    1592                 :             : 
    1593         [ #  # ]:           0 :                     ereport(DEBUG1,
    1594                 :             :                             (errmsg_internal("sending cancel to blocking autovacuum PID %d",
    1595                 :             :                                              pid),
    1596                 :             :                              errdetail_log("%s", logbuf.data)));
    1597                 :             : 
    1598                 :           0 :                     pfree(locktagbuf.data);
    1599                 :           0 :                     pfree(logbuf.data);
    1600                 :             :                 }
    1601                 :             : 
    1602                 :             :                 /* send the autovacuum worker Back to Old Kent Road */
    1603         [ #  # ]:           0 :                 if (kill(pid, SIGINT) < 0)
    1604                 :             :                 {
    1605                 :             :                     /*
    1606                 :             :                      * There's a race condition here: once we release the
    1607                 :             :                      * ProcArrayLock, it's possible for the autovac worker to
    1608                 :             :                      * close up shop and exit before we can do the kill().
    1609                 :             :                      * Therefore, we do not whinge about no-such-process.
    1610                 :             :                      * Other errors such as EPERM could conceivably happen if
    1611                 :             :                      * the kernel recycles the PID fast enough, but such cases
    1612                 :             :                      * seem improbable enough that it's probably best to issue
    1613                 :             :                      * a warning if we see some other errno.
    1614                 :             :                      */
    1615         [ #  # ]:           0 :                     if (errno != ESRCH)
    1616         [ #  # ]:           0 :                         ereport(WARNING,
    1617                 :             :                                 (errmsg("could not send signal to process %d: %m",
    1618                 :             :                                         pid)));
    1619                 :             :                 }
    1620                 :             :             }
    1621                 :             : 
    1622                 :             :             /* prevent signal from being sent again more than once */
    1623                 :           0 :             allow_autovacuum_cancel = false;
    1624                 :             :         }
    1625                 :             : 
    1626                 :             :         /*
    1627                 :             :          * If awoken after the deadlock check interrupt has run, increment the
    1628                 :             :          * lock statistics counters and if log_lock_waits is on, then report
    1629                 :             :          * about the wait.
    1630                 :             :          */
    1631         [ +  + ]:        3454 :         if (deadlock_state != DS_NOT_YET_CHECKED)
    1632                 :             :         {
    1633                 :             :             long        secs;
    1634                 :             :             int         usecs;
    1635                 :             :             long        msecs;
    1636                 :             : 
    1637                 :        1593 :             INJECTION_POINT("deadlock-timeout-fired", NULL);
    1638                 :        1593 :             TimestampDifference(get_timeout_start_time(DEADLOCK_TIMEOUT),
    1639                 :             :                                 GetCurrentTimestamp(),
    1640                 :             :                                 &secs, &usecs);
    1641                 :             :             /* Increment the lock statistics counters if done waiting. */
    1642         [ +  + ]:        1593 :             if (myWaitStatus == PROC_WAIT_STATUS_OK)
    1643                 :          27 :                 pgstat_count_lock_waits(locallock->tag.lock.locktag_type,
    1644                 :          27 :                                         (PgStat_Counter) secs * 1000000 + usecs);
    1645                 :             : 
    1646                 :        1593 :             msecs = secs * 1000 + usecs / 1000;
    1647                 :        1593 :             usecs = usecs % 1000;
    1648                 :             : 
    1649         [ +  + ]:        1593 :             if (log_lock_waits)
    1650                 :             :             {
    1651                 :             :                 StringInfoData buf,
    1652                 :             :                             lock_waiters_sbuf,
    1653                 :             :                             lock_holders_sbuf;
    1654                 :             :                 const char *modename;
    1655                 :        1591 :                 int         lockHoldersNum = 0;
    1656                 :             : 
    1657                 :        1591 :                 initStringInfo(&buf);
    1658                 :        1591 :                 initStringInfo(&lock_waiters_sbuf);
    1659                 :        1591 :                 initStringInfo(&lock_holders_sbuf);
    1660                 :             : 
    1661                 :        1591 :                 DescribeLockTag(&buf, &locallock->tag.lock);
    1662                 :        1591 :                 modename = GetLockmodeName(locallock->tag.lock.locktag_lockmethodid,
    1663                 :             :                                            lockmode);
    1664                 :             : 
    1665                 :             :                 /* Gather a list of all lock holders and waiters */
    1666                 :        1591 :                 LWLockAcquire(partitionLock, LW_SHARED);
    1667                 :        1591 :                 GetLockHoldersAndWaiters(locallock, &lock_holders_sbuf,
    1668                 :             :                                          &lock_waiters_sbuf, &lockHoldersNum);
    1669                 :        1591 :                 LWLockRelease(partitionLock);
    1670                 :             : 
    1671         [ +  + ]:        1591 :                 if (deadlock_state == DS_SOFT_DEADLOCK)
    1672         [ +  - ]:           3 :                     ereport(LOG,
    1673                 :             :                             (errmsg("process %d avoided deadlock for %s on %s by rearranging queue order after %ld.%03d ms",
    1674                 :             :                                     MyProcPid, modename, buf.data, msecs, usecs),
    1675                 :             :                              (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
    1676                 :             :                                                    "Processes holding the lock: %s. Wait queue: %s.",
    1677                 :             :                                                    lockHoldersNum, lock_holders_sbuf.data, lock_waiters_sbuf.data))));
    1678         [ +  + ]:        1588 :                 else if (deadlock_state == DS_HARD_DEADLOCK)
    1679                 :             :                 {
    1680                 :             :                     /*
    1681                 :             :                      * This message is a bit redundant with the error that
    1682                 :             :                      * will be reported subsequently, but in some cases the
    1683                 :             :                      * error report might not make it to the log (eg, if it's
    1684                 :             :                      * caught by an exception handler), and we want to ensure
    1685                 :             :                      * all long-wait events get logged.
    1686                 :             :                      */
    1687         [ +  - ]:           5 :                     ereport(LOG,
    1688                 :             :                             (errmsg("process %d detected deadlock while waiting for %s on %s after %ld.%03d ms",
    1689                 :             :                                     MyProcPid, modename, buf.data, msecs, usecs),
    1690                 :             :                              (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
    1691                 :             :                                                    "Processes holding the lock: %s. Wait queue: %s.",
    1692                 :             :                                                    lockHoldersNum, lock_holders_sbuf.data, lock_waiters_sbuf.data))));
    1693                 :             :                 }
    1694                 :             : 
    1695         [ +  + ]:        1591 :                 if (myWaitStatus == PROC_WAIT_STATUS_WAITING)
    1696                 :             :                 {
    1697                 :             :                     /*
    1698                 :             :                      * Guard the "still waiting on lock" log message so it is
    1699                 :             :                      * reported at most once while waiting for the lock.
    1700                 :             :                      *
    1701                 :             :                      * Without this guard, the message can be emitted whenever
    1702                 :             :                      * the lock-wait sleep is interrupted (for example by
    1703                 :             :                      * SIGHUP for config reload or by
    1704                 :             :                      * client_connection_check_interval). For example, if
    1705                 :             :                      * client_connection_check_interval is set very low (e.g.,
    1706                 :             :                      * 100 ms), the message could be logged repeatedly,
    1707                 :             :                      * flooding the log and making it difficult to use.
    1708                 :             :                      */
    1709         [ +  + ]:        1560 :                     if (!logged_lock_wait)
    1710                 :             :                     {
    1711         [ +  - ]:          28 :                         ereport(LOG,
    1712                 :             :                                 (errmsg("process %d still waiting for %s on %s after %ld.%03d ms",
    1713                 :             :                                         MyProcPid, modename, buf.data, msecs, usecs),
    1714                 :             :                                  (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
    1715                 :             :                                                        "Processes holding the lock: %s. Wait queue: %s.",
    1716                 :             :                                                        lockHoldersNum, lock_holders_sbuf.data, lock_waiters_sbuf.data))));
    1717                 :          28 :                         logged_lock_wait = true;
    1718                 :             :                     }
    1719                 :             :                 }
    1720         [ +  + ]:          31 :                 else if (myWaitStatus == PROC_WAIT_STATUS_OK)
    1721         [ +  - ]:          26 :                     ereport(LOG,
    1722                 :             :                             (errmsg("process %d acquired %s on %s after %ld.%03d ms",
    1723                 :             :                                     MyProcPid, modename, buf.data, msecs, usecs)));
    1724                 :             :                 else
    1725                 :             :                 {
    1726                 :             :                     Assert(myWaitStatus == PROC_WAIT_STATUS_ERROR);
    1727                 :             : 
    1728                 :             :                     /*
    1729                 :             :                      * Currently, the deadlock checker always kicks its own
    1730                 :             :                      * process, which means that we'll only see
    1731                 :             :                      * PROC_WAIT_STATUS_ERROR when deadlock_state ==
    1732                 :             :                      * DS_HARD_DEADLOCK, and there's no need to print
    1733                 :             :                      * redundant messages.  But for completeness and
    1734                 :             :                      * future-proofing, print a message if it looks like
    1735                 :             :                      * someone else kicked us off the lock.
    1736                 :             :                      */
    1737         [ -  + ]:           5 :                     if (deadlock_state != DS_HARD_DEADLOCK)
    1738         [ #  # ]:           0 :                         ereport(LOG,
    1739                 :             :                                 (errmsg("process %d failed to acquire %s on %s after %ld.%03d ms",
    1740                 :             :                                         MyProcPid, modename, buf.data, msecs, usecs),
    1741                 :             :                                  (errdetail_log_plural("Process holding the lock: %s. Wait queue: %s.",
    1742                 :             :                                                        "Processes holding the lock: %s. Wait queue: %s.",
    1743                 :             :                                                        lockHoldersNum, lock_holders_sbuf.data, lock_waiters_sbuf.data))));
    1744                 :             :                 }
    1745                 :        1591 :                 pfree(buf.data);
    1746                 :        1591 :                 pfree(lock_holders_sbuf.data);
    1747                 :        1591 :                 pfree(lock_waiters_sbuf.data);
    1748                 :             :             }
    1749                 :             : 
    1750                 :             :             /*
    1751                 :             :              * At this point we might still need to wait for the lock. Reset
    1752                 :             :              * state so we don't print the above messages again if
    1753                 :             :              * log_lock_waits is on.
    1754                 :             :              */
    1755                 :        1593 :             deadlock_state = DS_NO_DEADLOCK;
    1756                 :             :         }
    1757         [ +  + ]:        3454 :     } while (myWaitStatus == PROC_WAIT_STATUS_WAITING);
    1758                 :             : 
    1759                 :             :     /*
    1760                 :             :      * Disable the timers, if they are still running.  As in LockErrorCleanup,
    1761                 :             :      * we must preserve the LOCK_TIMEOUT indicator flag: if a lock timeout has
    1762                 :             :      * already caused QueryCancelPending to become set, we want the cancel to
    1763                 :             :      * be reported as a lock timeout, not a user cancel.
    1764                 :             :      */
    1765         [ +  + ]:        1421 :     if (!InHotStandby)
    1766                 :             :     {
    1767         [ +  + ]:        1420 :         if (LockTimeout > 0)
    1768                 :             :         {
    1769                 :             :             DisableTimeoutParams timeouts[2];
    1770                 :             : 
    1771                 :         108 :             timeouts[0].id = DEADLOCK_TIMEOUT;
    1772                 :         108 :             timeouts[0].keep_indicator = false;
    1773                 :         108 :             timeouts[1].id = LOCK_TIMEOUT;
    1774                 :         108 :             timeouts[1].keep_indicator = true;
    1775                 :         108 :             disable_timeouts(timeouts, 2);
    1776                 :             :         }
    1777                 :             :         else
    1778                 :        1312 :             disable_timeout(DEADLOCK_TIMEOUT, false);
    1779                 :             :     }
    1780                 :             : 
    1781                 :             :     /*
    1782                 :             :      * Emit the log message if recovery conflict on lock was resolved but the
    1783                 :             :      * startup process waited longer than deadlock_timeout for it.
    1784                 :             :      */
    1785   [ +  +  +  - ]:        1421 :     if (InHotStandby && logged_recovery_conflict)
    1786                 :           1 :         LogRecoveryConflict(RECOVERY_CONFLICT_LOCK,
    1787                 :             :                             standbyWaitStart, GetCurrentTimestamp(),
    1788                 :             :                             NULL, false);
    1789                 :             : 
    1790                 :             :     /*
    1791                 :             :      * We don't have to do anything else, because the awaker did all the
    1792                 :             :      * necessary updates of the lock table and MyProc. (The caller is
    1793                 :             :      * responsible for updating the local lock table.)
    1794                 :             :      */
    1795                 :        1421 :     return myWaitStatus;
    1796                 :             : }
    1797                 :             : 
    1798                 :             : 
    1799                 :             : /*
    1800                 :             :  * ProcWakeup -- wake up a process by setting its latch.
    1801                 :             :  *
    1802                 :             :  *   Also remove the process from the wait queue and set its waitLink invalid.
    1803                 :             :  *
    1804                 :             :  * The appropriate lock partition lock must be held by caller.
    1805                 :             :  *
    1806                 :             :  * XXX: presently, this code is only used for the "success" case, and only
    1807                 :             :  * works correctly for that case.  To clean up in failure case, would need
    1808                 :             :  * to twiddle the lock's request counts too --- see RemoveFromWaitQueue.
    1809                 :             :  * Hence, in practice the waitStatus parameter must be PROC_WAIT_STATUS_OK.
    1810                 :             :  */
    1811                 :             : void
    1812                 :        1418 : ProcWakeup(PGPROC *proc, ProcWaitStatus waitStatus)
    1813                 :             : {
    1814         [ -  + ]:        1418 :     if (dlist_node_is_detached(&proc->waitLink))
    1815                 :           0 :         return;
    1816                 :             : 
    1817                 :             :     Assert(proc->waitStatus == PROC_WAIT_STATUS_WAITING);
    1818                 :             : 
    1819                 :             :     /* Remove process from wait queue */
    1820                 :        1418 :     dclist_delete_from_thoroughly(&proc->waitLock->waitProcs, &proc->waitLink);
    1821                 :             : 
    1822                 :             :     /* Clean up process' state and pass it the ok/fail signal */
    1823                 :        1418 :     proc->waitLock = NULL;
    1824                 :        1418 :     proc->waitProcLock = NULL;
    1825                 :        1418 :     proc->waitStatus = waitStatus;
    1826                 :        1418 :     pg_atomic_write_u64(&proc->waitStart, 0);
    1827                 :             : 
    1828                 :             :     /* And awaken it */
    1829                 :        1418 :     SetLatch(&proc->procLatch);
    1830                 :             : }
    1831                 :             : 
    1832                 :             : /*
    1833                 :             :  * ProcLockWakeup -- routine for waking up processes when a lock is
    1834                 :             :  *      released (or a prior waiter is aborted).  Scan all waiters
    1835                 :             :  *      for lock, waken any that are no longer blocked.
    1836                 :             :  *
    1837                 :             :  * The appropriate lock partition lock must be held by caller.
    1838                 :             :  */
    1839                 :             : void
    1840                 :        1422 : ProcLockWakeup(LockMethod lockMethodTable, LOCK *lock)
    1841                 :             : {
    1842                 :        1422 :     dclist_head *waitQueue = &lock->waitProcs;
    1843                 :        1422 :     LOCKMASK    aheadRequests = 0;
    1844                 :             :     dlist_mutable_iter miter;
    1845                 :             : 
    1846         [ +  + ]:        1422 :     if (dclist_is_empty(waitQueue))
    1847                 :          46 :         return;
    1848                 :             : 
    1849   [ +  -  +  + ]:        3148 :     dclist_foreach_modify(miter, waitQueue)
    1850                 :             :     {
    1851                 :        1772 :         PGPROC     *proc = dlist_container(PGPROC, waitLink, miter.cur);
    1852                 :        1772 :         LOCKMODE    lockmode = proc->waitLockMode;
    1853                 :             : 
    1854                 :             :         /*
    1855                 :             :          * Waken if (a) doesn't conflict with requests of earlier waiters, and
    1856                 :             :          * (b) doesn't conflict with already-held locks.
    1857                 :             :          */
    1858         [ +  + ]:        1772 :         if ((lockMethodTable->conflictTab[lockmode] & aheadRequests) == 0 &&
    1859         [ +  + ]:        1626 :             !LockCheckConflicts(lockMethodTable, lockmode, lock,
    1860                 :             :                                 proc->waitProcLock))
    1861                 :             :         {
    1862                 :             :             /* OK to waken */
    1863                 :        1418 :             GrantLock(lock, proc->waitProcLock, lockmode);
    1864                 :             :             /* removes proc from the lock's waiting process queue */
    1865                 :        1418 :             ProcWakeup(proc, PROC_WAIT_STATUS_OK);
    1866                 :             :         }
    1867                 :             :         else
    1868                 :             :         {
    1869                 :             :             /*
    1870                 :             :              * Lock conflicts: Don't wake, but remember requested mode for
    1871                 :             :              * later checks.
    1872                 :             :              */
    1873                 :         354 :             aheadRequests |= LOCKBIT_ON(lockmode);
    1874                 :             :         }
    1875                 :             :     }
    1876                 :             : }
    1877                 :             : 
    1878                 :             : /*
    1879                 :             :  * CheckDeadLock
    1880                 :             :  *
    1881                 :             :  * We only get to this routine, if DEADLOCK_TIMEOUT fired while waiting for a
    1882                 :             :  * lock to be released by some other process.  Check if there's a deadlock; if
    1883                 :             :  * not, just return.  If we have a real deadlock, remove ourselves from the
    1884                 :             :  * lock's wait queue.
    1885                 :             :  */
    1886                 :             : static DeadLockState
    1887                 :          35 : CheckDeadLock(void)
    1888                 :             : {
    1889                 :             :     int         i;
    1890                 :             :     DeadLockState result;
    1891                 :             : 
    1892                 :             :     /*
    1893                 :             :      * Acquire exclusive lock on the entire shared lock data structures. Must
    1894                 :             :      * grab LWLocks in partition-number order to avoid LWLock deadlock.
    1895                 :             :      *
    1896                 :             :      * Note that the deadlock check interrupt had better not be enabled
    1897                 :             :      * anywhere that this process itself holds lock partition locks, else this
    1898                 :             :      * will wait forever.  Also note that LWLockAcquire creates a critical
    1899                 :             :      * section, so that this routine cannot be interrupted by cancel/die
    1900                 :             :      * interrupts.
    1901                 :             :      */
    1902         [ +  + ]:         595 :     for (i = 0; i < NUM_LOCK_PARTITIONS; i++)
    1903                 :         560 :         LWLockAcquire(LockHashPartitionLockByIndex(i), LW_EXCLUSIVE);
    1904                 :             : 
    1905                 :             :     /*
    1906                 :             :      * Check to see if we've been awoken by anyone in the interim.
    1907                 :             :      *
    1908                 :             :      * If we have, we can return and resume our transaction -- happy day.
    1909                 :             :      * Before we are awoken the process releasing the lock grants it to us so
    1910                 :             :      * we know that we don't have to wait anymore.
    1911                 :             :      *
    1912                 :             :      * We check by looking to see if we've been unlinked from the wait queue.
    1913                 :             :      * This is safe because we hold the lock partition lock.
    1914                 :             :      */
    1915         [ -  + ]:          35 :     if (dlist_node_is_detached(&MyProc->waitLink))
    1916                 :             :     {
    1917                 :           0 :         result = DS_NO_DEADLOCK;
    1918                 :           0 :         goto check_done;
    1919                 :             :     }
    1920                 :             : 
    1921                 :             : #ifdef LOCK_DEBUG
    1922                 :             :     if (Debug_deadlocks)
    1923                 :             :         DumpAllLocks();
    1924                 :             : #endif
    1925                 :             : 
    1926                 :             :     /* Run the deadlock check */
    1927                 :          35 :     result = DeadLockCheck(MyProc);
    1928                 :             : 
    1929         [ +  + ]:          35 :     if (result == DS_HARD_DEADLOCK)
    1930                 :             :     {
    1931                 :             :         /*
    1932                 :             :          * Oops.  We have a deadlock.
    1933                 :             :          *
    1934                 :             :          * Get this process out of wait state. (Note: we could do this more
    1935                 :             :          * efficiently by relying on lockAwaited, but use this coding to
    1936                 :             :          * preserve the flexibility to kill some other transaction than the
    1937                 :             :          * one detecting the deadlock.)
    1938                 :             :          *
    1939                 :             :          * RemoveFromWaitQueue sets MyProc->waitStatus to
    1940                 :             :          * PROC_WAIT_STATUS_ERROR, so ProcSleep will report an error after we
    1941                 :             :          * return.
    1942                 :             :          */
    1943                 :             :         Assert(MyProc->waitLock != NULL);
    1944                 :           5 :         RemoveFromWaitQueue(MyProc, LockTagHashCode(&(MyProc->waitLock->tag)));
    1945                 :             : 
    1946                 :             :         /*
    1947                 :             :          * We're done here.  Transaction abort caused by the error that
    1948                 :             :          * ProcSleep will raise will cause any other locks we hold to be
    1949                 :             :          * released, thus allowing other processes to wake up; we don't need
    1950                 :             :          * to do that here.  NOTE: an exception is that releasing locks we
    1951                 :             :          * hold doesn't consider the possibility of waiters that were blocked
    1952                 :             :          * behind us on the lock we just failed to get, and might now be
    1953                 :             :          * wakable because we're not in front of them anymore.  However,
    1954                 :             :          * RemoveFromWaitQueue took care of waking up any such processes.
    1955                 :             :          */
    1956                 :             :     }
    1957                 :             : 
    1958                 :             :     /*
    1959                 :             :      * And release locks.  We do this in reverse order for two reasons: (1)
    1960                 :             :      * Anyone else who needs more than one of the locks will be trying to lock
    1961                 :             :      * them in increasing order; we don't want to release the other process
    1962                 :             :      * until it can get all the locks it needs. (2) This avoids O(N^2)
    1963                 :             :      * behavior inside LWLockRelease.
    1964                 :             :      */
    1965                 :          30 : check_done:
    1966         [ +  + ]:         595 :     for (i = NUM_LOCK_PARTITIONS; --i >= 0;)
    1967                 :         560 :         LWLockRelease(LockHashPartitionLockByIndex(i));
    1968                 :             : 
    1969                 :          35 :     return result;
    1970                 :             : }
    1971                 :             : 
    1972                 :             : /*
    1973                 :             :  * CheckDeadLockAlert - Handle the expiry of deadlock_timeout.
    1974                 :             :  *
    1975                 :             :  * NB: Runs inside a signal handler, be careful.
    1976                 :             :  */
    1977                 :             : void
    1978                 :          35 : CheckDeadLockAlert(void)
    1979                 :             : {
    1980                 :          35 :     int         save_errno = errno;
    1981                 :             : 
    1982                 :          35 :     got_deadlock_timeout = true;
    1983                 :             : 
    1984                 :             :     /*
    1985                 :             :      * Have to set the latch again, even if handle_sig_alarm already did. Back
    1986                 :             :      * then got_deadlock_timeout wasn't yet set... It's unlikely that this
    1987                 :             :      * ever would be a problem, but setting a set latch again is cheap.
    1988                 :             :      *
    1989                 :             :      * Note that, when this function runs inside procsignal_sigusr1_handler(),
    1990                 :             :      * the handler function sets the latch again after the latch is set here.
    1991                 :             :      */
    1992                 :          35 :     SetLatch(MyLatch);
    1993                 :          35 :     errno = save_errno;
    1994                 :          35 : }
    1995                 :             : 
    1996                 :             : /*
    1997                 :             :  * GetLockHoldersAndWaiters - get lock holders and waiters for a lock
    1998                 :             :  *
    1999                 :             :  * Fill lock_holders_sbuf and lock_waiters_sbuf with the PIDs of processes holding
    2000                 :             :  * and waiting for the lock, and set lockHoldersNum to the number of lock holders.
    2001                 :             :  *
    2002                 :             :  * The lock table's partition lock must be held on entry and remains held on exit.
    2003                 :             :  */
    2004                 :             : void
    2005                 :        1591 : GetLockHoldersAndWaiters(LOCALLOCK *locallock, StringInfo lock_holders_sbuf,
    2006                 :             :                          StringInfo lock_waiters_sbuf, int *lockHoldersNum)
    2007                 :             : {
    2008                 :             :     dlist_iter  proc_iter;
    2009                 :             :     PROCLOCK   *curproclock;
    2010                 :        1591 :     LOCK       *lock = locallock->lock;
    2011                 :        1591 :     bool        first_holder = true,
    2012                 :        1591 :                 first_waiter = true;
    2013                 :             : 
    2014                 :             : #ifdef USE_ASSERT_CHECKING
    2015                 :             :     {
    2016                 :             :         uint32      hashcode = locallock->hashcode;
    2017                 :             :         LWLock     *partitionLock = LockHashPartitionLock(hashcode);
    2018                 :             : 
    2019                 :             :         Assert(LWLockHeldByMe(partitionLock));
    2020                 :             :     }
    2021                 :             : #endif
    2022                 :             : 
    2023                 :        1591 :     *lockHoldersNum = 0;
    2024                 :             : 
    2025                 :             :     /*
    2026                 :             :      * Loop over the lock's procLocks to gather a list of all holders and
    2027                 :             :      * waiters. Thus we will be able to provide more detailed information for
    2028                 :             :      * lock debugging purposes.
    2029                 :             :      *
    2030                 :             :      * lock->procLocks contains all processes which hold or wait for this
    2031                 :             :      * lock.
    2032                 :             :      */
    2033   [ +  -  +  + ]:        4770 :     dlist_foreach(proc_iter, &lock->procLocks)
    2034                 :             :     {
    2035                 :        3179 :         curproclock =
    2036                 :        3179 :             dlist_container(PROCLOCK, lockLink, proc_iter.cur);
    2037                 :             : 
    2038                 :             :         /*
    2039                 :             :          * We are a waiter if myProc->waitProcLock == curproclock; we are a
    2040                 :             :          * holder if it is NULL or something different.
    2041                 :             :          */
    2042         [ +  + ]:        3179 :         if (curproclock->tag.myProc->waitProcLock == curproclock)
    2043                 :             :         {
    2044         [ +  + ]:        1581 :             if (first_waiter)
    2045                 :             :             {
    2046                 :        1561 :                 appendStringInfo(lock_waiters_sbuf, "%d",
    2047                 :        1561 :                                  curproclock->tag.myProc->pid);
    2048                 :        1561 :                 first_waiter = false;
    2049                 :             :             }
    2050                 :             :             else
    2051                 :          20 :                 appendStringInfo(lock_waiters_sbuf, ", %d",
    2052                 :          20 :                                  curproclock->tag.myProc->pid);
    2053                 :             :         }
    2054                 :             :         else
    2055                 :             :         {
    2056         [ +  + ]:        1598 :             if (first_holder)
    2057                 :             :             {
    2058                 :        1591 :                 appendStringInfo(lock_holders_sbuf, "%d",
    2059                 :        1591 :                                  curproclock->tag.myProc->pid);
    2060                 :        1591 :                 first_holder = false;
    2061                 :             :             }
    2062                 :             :             else
    2063                 :           7 :                 appendStringInfo(lock_holders_sbuf, ", %d",
    2064                 :           7 :                                  curproclock->tag.myProc->pid);
    2065                 :             : 
    2066                 :        1598 :             (*lockHoldersNum)++;
    2067                 :             :         }
    2068                 :             :     }
    2069                 :        1591 : }
    2070                 :             : 
    2071                 :             : /*
    2072                 :             :  * ProcWaitForSignal - wait for a signal from another backend.
    2073                 :             :  *
    2074                 :             :  * As this uses the generic process latch the caller has to be robust against
    2075                 :             :  * unrelated wakeups: Always check that the desired state has occurred, and
    2076                 :             :  * wait again if not.
    2077                 :             :  */
    2078                 :             : void
    2079                 :         104 : ProcWaitForSignal(uint32 wait_event_info)
    2080                 :             : {
    2081                 :         104 :     (void) WaitLatch(MyLatch, WL_LATCH_SET | WL_EXIT_ON_PM_DEATH, 0,
    2082                 :             :                      wait_event_info);
    2083                 :         104 :     ResetLatch(MyLatch);
    2084         [ -  + ]:         104 :     CHECK_FOR_INTERRUPTS();
    2085                 :         104 : }
    2086                 :             : 
    2087                 :             : /*
    2088                 :             :  * ProcSendSignal - set the latch of a backend identified by ProcNumber
    2089                 :             :  */
    2090                 :             : void
    2091                 :          92 : ProcSendSignal(ProcNumber procNumber)
    2092                 :             : {
    2093   [ +  -  -  + ]:          92 :     if (procNumber < 0 || procNumber >= ProcGlobal->allProcCount)
    2094         [ #  # ]:           0 :         elog(ERROR, "procNumber out of range");
    2095                 :             : 
    2096                 :          92 :     SetLatch(&GetPGProcByNumber(procNumber)->procLatch);
    2097                 :          92 : }
    2098                 :             : 
    2099                 :             : /*
    2100                 :             :  * BecomeLockGroupLeader - designate process as lock group leader
    2101                 :             :  *
    2102                 :             :  * Once this function has returned, other processes can join the lock group
    2103                 :             :  * by calling BecomeLockGroupMember.
    2104                 :             :  */
    2105                 :             : void
    2106                 :         869 : BecomeLockGroupLeader(void)
    2107                 :             : {
    2108                 :             :     LWLock     *leader_lwlock;
    2109                 :             : 
    2110                 :             :     /* If we already did it, we don't need to do it again. */
    2111         [ +  + ]:         869 :     if (MyProc->lockGroupLeader == MyProc)
    2112                 :         745 :         return;
    2113                 :             : 
    2114                 :             :     /* We had better not be a follower. */
    2115                 :             :     Assert(MyProc->lockGroupLeader == NULL);
    2116                 :             : 
    2117                 :             :     /* Create single-member group, containing only ourselves. */
    2118                 :         124 :     leader_lwlock = LockHashPartitionLockByProc(MyProc);
    2119                 :         124 :     LWLockAcquire(leader_lwlock, LW_EXCLUSIVE);
    2120                 :         124 :     MyProc->lockGroupLeader = MyProc;
    2121                 :         124 :     dlist_push_head(&MyProc->lockGroupMembers, &MyProc->lockGroupLink);
    2122                 :         124 :     LWLockRelease(leader_lwlock);
    2123                 :             : }
    2124                 :             : 
    2125                 :             : /*
    2126                 :             :  * BecomeLockGroupMember - designate process as lock group member
    2127                 :             :  *
    2128                 :             :  * This is pretty straightforward except for the possibility that the leader
    2129                 :             :  * whose group we're trying to join might exit before we manage to do so;
    2130                 :             :  * and the PGPROC might get recycled for an unrelated process.  To avoid
    2131                 :             :  * that, we require the caller to pass the PID of the intended PGPROC as
    2132                 :             :  * an interlock.  Returns true if we successfully join the intended lock
    2133                 :             :  * group, and false if not.
    2134                 :             :  */
    2135                 :             : bool
    2136                 :        2018 : BecomeLockGroupMember(PGPROC *leader, int pid)
    2137                 :             : {
    2138                 :             :     LWLock     *leader_lwlock;
    2139                 :        2018 :     bool        ok = false;
    2140                 :             : 
    2141                 :             :     /* Group leader can't become member of group */
    2142                 :             :     Assert(MyProc != leader);
    2143                 :             : 
    2144                 :             :     /* Can't already be a member of a group */
    2145                 :             :     Assert(MyProc->lockGroupLeader == NULL);
    2146                 :             : 
    2147                 :             :     /* PID must be valid. */
    2148                 :             :     Assert(pid != 0);
    2149                 :             : 
    2150                 :             :     /*
    2151                 :             :      * Get lock protecting the group fields.  Note LockHashPartitionLockByProc
    2152                 :             :      * calculates the proc number based on the PGPROC slot without looking at
    2153                 :             :      * its contents, so we will acquire the correct lock even if the leader
    2154                 :             :      * PGPROC is in process of being recycled.
    2155                 :             :      */
    2156                 :        2018 :     leader_lwlock = LockHashPartitionLockByProc(leader);
    2157                 :        2018 :     LWLockAcquire(leader_lwlock, LW_EXCLUSIVE);
    2158                 :             : 
    2159                 :             :     /* Is this the leader we're looking for? */
    2160   [ +  -  +  - ]:        2018 :     if (leader->pid == pid && leader->lockGroupLeader == leader)
    2161                 :             :     {
    2162                 :             :         /* OK, join the group */
    2163                 :        2018 :         ok = true;
    2164                 :        2018 :         MyProc->lockGroupLeader = leader;
    2165                 :        2018 :         dlist_push_tail(&leader->lockGroupMembers, &MyProc->lockGroupLink);
    2166                 :             :     }
    2167                 :        2018 :     LWLockRelease(leader_lwlock);
    2168                 :             : 
    2169                 :        2018 :     return ok;
    2170                 :             : }
        

Generated by: LCOV version 2.0-1