LCOV - code coverage report
Current view: top level - src/backend/storage/ipc - latch.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 69.6 % 102 71
Test Date: 2026-01-26 10:56:24 Functions: 88.9 % 9 8
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 41.9 % 74 31

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * latch.c
       4                 :             :  *        Routines for inter-process latches
       5                 :             :  *
       6                 :             :  * The latch interface is a reliable replacement for the common pattern of
       7                 :             :  * using pg_usleep() or select() to wait until a signal arrives, where the
       8                 :             :  * signal handler sets a flag variable.  See latch.h for more information
       9                 :             :  * on how to use them.
      10                 :             :  *
      11                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
      12                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
      13                 :             :  *
      14                 :             :  * IDENTIFICATION
      15                 :             :  *        src/backend/storage/ipc/latch.c
      16                 :             :  *
      17                 :             :  *-------------------------------------------------------------------------
      18                 :             :  */
      19                 :             : #include "postgres.h"
      20                 :             : 
      21                 :             : #include "miscadmin.h"
      22                 :             : #include "port/atomics.h"
      23                 :             : #include "storage/latch.h"
      24                 :             : #include "storage/waiteventset.h"
      25                 :             : #include "utils/resowner.h"
      26                 :             : 
      27                 :             : /* A common WaitEventSet used to implement WaitLatch() */
      28                 :             : static WaitEventSet *LatchWaitSet;
      29                 :             : 
      30                 :             : /* The positions of the latch and PM death events in LatchWaitSet */
      31                 :             : #define LatchWaitSetLatchPos 0
      32                 :             : #define LatchWaitSetPostmasterDeathPos 1
      33                 :             : 
      34                 :             : void
      35                 :         808 : InitializeLatchWaitSet(void)
      36                 :             : {
      37                 :         808 :         int                     latch_pos PG_USED_FOR_ASSERTS_ONLY;
      38                 :             : 
      39         [ +  - ]:         808 :         Assert(LatchWaitSet == NULL);
      40                 :             : 
      41                 :             :         /* Set up the WaitEventSet used by WaitLatch(). */
      42                 :         808 :         LatchWaitSet = CreateWaitEventSet(NULL, 2);
      43                 :        1616 :         latch_pos = AddWaitEventToSet(LatchWaitSet, WL_LATCH_SET, PGINVALID_SOCKET,
      44                 :         808 :                                                                   MyLatch, NULL);
      45         [ +  - ]:         808 :         Assert(latch_pos == LatchWaitSetLatchPos);
      46                 :             : 
      47                 :             :         /*
      48                 :             :          * WaitLatch will modify this to WL_EXIT_ON_PM_DEATH or
      49                 :             :          * WL_POSTMASTER_DEATH on each call.
      50                 :             :          */
      51         [ +  + ]:         808 :         if (IsUnderPostmaster)
      52                 :             :         {
      53                 :         804 :                 latch_pos = AddWaitEventToSet(LatchWaitSet, WL_EXIT_ON_PM_DEATH,
      54                 :             :                                                                           PGINVALID_SOCKET, NULL, NULL);
      55         [ +  - ]:         804 :                 Assert(latch_pos == LatchWaitSetPostmasterDeathPos);
      56                 :         804 :         }
      57                 :         808 : }
      58                 :             : 
      59                 :             : /*
      60                 :             :  * Initialize a process-local latch.
      61                 :             :  */
      62                 :             : void
      63                 :         810 : InitLatch(Latch *latch)
      64                 :             : {
      65                 :         810 :         latch->is_set = false;
      66                 :         810 :         latch->maybe_sleeping = false;
      67                 :         810 :         latch->owner_pid = MyProcPid;
      68                 :         810 :         latch->is_shared = false;
      69                 :             : 
      70                 :             : #ifdef WIN32
      71                 :             :         latch->event = CreateEvent(NULL, TRUE, FALSE, NULL);
      72                 :             :         if (latch->event == NULL)
      73                 :             :                 elog(ERROR, "CreateEvent failed: error code %lu", GetLastError());
      74                 :             : #endif                                                  /* WIN32 */
      75                 :         810 : }
      76                 :             : 
      77                 :             : /*
      78                 :             :  * Initialize a shared latch that can be set from other processes. The latch
      79                 :             :  * is initially owned by no-one; use OwnLatch to associate it with the
      80                 :             :  * current process.
      81                 :             :  *
      82                 :             :  * InitSharedLatch needs to be called in postmaster before forking child
      83                 :             :  * processes, usually right after allocating the shared memory block
      84                 :             :  * containing the latch with ShmemInitStruct. (The Unix implementation
      85                 :             :  * doesn't actually require that, but the Windows one does.) Because of
      86                 :             :  * this restriction, we have no concurrency issues to worry about here.
      87                 :             :  *
      88                 :             :  * Note that other handles created in this module are never marked as
      89                 :             :  * inheritable.  Thus we do not need to worry about cleaning up child
      90                 :             :  * process references to postmaster-private latches or WaitEventSets.
      91                 :             :  */
      92                 :             : void
      93                 :        1040 : InitSharedLatch(Latch *latch)
      94                 :             : {
      95                 :             : #ifdef WIN32
      96                 :             :         SECURITY_ATTRIBUTES sa;
      97                 :             : 
      98                 :             :         /*
      99                 :             :          * Set up security attributes to specify that the events are inherited.
     100                 :             :          */
     101                 :             :         ZeroMemory(&sa, sizeof(sa));
     102                 :             :         sa.nLength = sizeof(sa);
     103                 :             :         sa.bInheritHandle = TRUE;
     104                 :             : 
     105                 :             :         latch->event = CreateEvent(&sa, TRUE, FALSE, NULL);
     106                 :             :         if (latch->event == NULL)
     107                 :             :                 elog(ERROR, "CreateEvent failed: error code %lu", GetLastError());
     108                 :             : #endif
     109                 :             : 
     110                 :        1040 :         latch->is_set = false;
     111                 :        1040 :         latch->maybe_sleeping = false;
     112                 :        1040 :         latch->owner_pid = 0;
     113                 :        1040 :         latch->is_shared = true;
     114                 :        1040 : }
     115                 :             : 
     116                 :             : /*
     117                 :             :  * Associate a shared latch with the current process, allowing it to
     118                 :             :  * wait on the latch.
     119                 :             :  *
     120                 :             :  * Although there is a sanity check for latch-already-owned, we don't do
     121                 :             :  * any sort of locking here, meaning that we could fail to detect the error
     122                 :             :  * if two processes try to own the same latch at about the same time.  If
     123                 :             :  * there is any risk of that, caller must provide an interlock to prevent it.
     124                 :             :  */
     125                 :             : void
     126                 :         806 : OwnLatch(Latch *latch)
     127                 :             : {
     128                 :         806 :         int                     owner_pid;
     129                 :             : 
     130                 :             :         /* Sanity checks */
     131         [ +  - ]:         806 :         Assert(latch->is_shared);
     132                 :             : 
     133                 :         806 :         owner_pid = latch->owner_pid;
     134         [ +  - ]:         806 :         if (owner_pid != 0)
     135   [ #  #  #  # ]:           0 :                 elog(PANIC, "latch already owned by PID %d", owner_pid);
     136                 :             : 
     137                 :         806 :         latch->owner_pid = MyProcPid;
     138                 :         806 : }
     139                 :             : 
     140                 :             : /*
     141                 :             :  * Disown a shared latch currently owned by the current process.
     142                 :             :  */
     143                 :             : void
     144                 :         806 : DisownLatch(Latch *latch)
     145                 :             : {
     146         [ +  - ]:         806 :         Assert(latch->is_shared);
     147         [ +  - ]:         806 :         Assert(latch->owner_pid == MyProcPid);
     148                 :             : 
     149                 :         806 :         latch->owner_pid = 0;
     150                 :         806 : }
     151                 :             : 
     152                 :             : /*
     153                 :             :  * Wait for a given latch to be set, or for postmaster death, or until timeout
     154                 :             :  * is exceeded. 'wakeEvents' is a bitmask that specifies which of those events
     155                 :             :  * to wait for. If the latch is already set (and WL_LATCH_SET is given), the
     156                 :             :  * function returns immediately.
     157                 :             :  *
     158                 :             :  * The "timeout" is given in milliseconds. It must be >= 0 if WL_TIMEOUT flag
     159                 :             :  * is given.  Although it is declared as "long", we don't actually support
     160                 :             :  * timeouts longer than INT_MAX milliseconds.  Note that some extra overhead
     161                 :             :  * is incurred when WL_TIMEOUT is given, so avoid using a timeout if possible.
     162                 :             :  *
     163                 :             :  * The latch must be owned by the current process, ie. it must be a
     164                 :             :  * process-local latch initialized with InitLatch, or a shared latch
     165                 :             :  * associated with the current process by calling OwnLatch.
     166                 :             :  *
     167                 :             :  * Returns bit mask indicating which condition(s) caused the wake-up. Note
     168                 :             :  * that if multiple wake-up conditions are true, there is no guarantee that
     169                 :             :  * we return all of them in one call, but we will return at least one.
     170                 :             :  */
     171                 :             : int
     172                 :        3321 : WaitLatch(Latch *latch, int wakeEvents, long timeout,
     173                 :             :                   uint32 wait_event_info)
     174                 :             : {
     175                 :        3321 :         WaitEvent       event;
     176                 :             : 
     177                 :             :         /* Postmaster-managed callers must handle postmaster death somehow. */
     178   [ +  -  +  +  :        3321 :         Assert(!IsUnderPostmaster ||
                   +  - ]
     179                 :             :                    (wakeEvents & WL_EXIT_ON_PM_DEATH) ||
     180                 :             :                    (wakeEvents & WL_POSTMASTER_DEATH));
     181                 :             : 
     182                 :             :         /*
     183                 :             :          * Some callers may have a latch other than MyLatch, or no latch at all,
     184                 :             :          * or want to handle postmaster death differently.  It's cheap to assign
     185                 :             :          * those, so just do it every time.
     186                 :             :          */
     187         [ +  - ]:        3321 :         if (!(wakeEvents & WL_LATCH_SET))
     188                 :           0 :                 latch = NULL;
     189                 :        3321 :         ModifyWaitEvent(LatchWaitSet, LatchWaitSetLatchPos, WL_LATCH_SET, latch);
     190                 :             : 
     191         [ -  + ]:        3321 :         if (IsUnderPostmaster)
     192                 :        6642 :                 ModifyWaitEvent(LatchWaitSet, LatchWaitSetPostmasterDeathPos,
     193                 :        3321 :                                                 (wakeEvents & (WL_EXIT_ON_PM_DEATH | WL_POSTMASTER_DEATH)),
     194                 :             :                                                 NULL);
     195                 :             : 
     196                 :        6642 :         if (WaitEventSetWait(LatchWaitSet,
     197         [ +  + ]:        3321 :                                                  (wakeEvents & WL_TIMEOUT) ? timeout : -1,
     198                 :             :                                                  &event, 1,
     199   [ +  +  +  + ]:        6642 :                                                  wait_event_info) == 0)
     200                 :          62 :                 return WL_TIMEOUT;
     201                 :             :         else
     202                 :        3259 :                 return event.events;
     203                 :        3321 : }
     204                 :             : 
     205                 :             : /*
     206                 :             :  * Like WaitLatch, but with an extra socket argument for WL_SOCKET_*
     207                 :             :  * conditions.
     208                 :             :  *
     209                 :             :  * When waiting on a socket, EOF and error conditions always cause the socket
     210                 :             :  * to be reported as readable/writable/connected, so that the caller can deal
     211                 :             :  * with the condition.
     212                 :             :  *
     213                 :             :  * wakeEvents must include either WL_EXIT_ON_PM_DEATH for automatic exit
     214                 :             :  * if the postmaster dies or WL_POSTMASTER_DEATH for a flag set in the
     215                 :             :  * return value if the postmaster dies.  The latter is useful for rare cases
     216                 :             :  * where some behavior other than immediate exit is needed.
     217                 :             :  *
     218                 :             :  * NB: These days this is just a wrapper around the WaitEventSet API. When
     219                 :             :  * using a latch very frequently, consider creating a longer living
     220                 :             :  * WaitEventSet instead; that's more efficient.
     221                 :             :  */
     222                 :             : int
     223                 :           0 : WaitLatchOrSocket(Latch *latch, int wakeEvents, pgsocket sock,
     224                 :             :                                   long timeout, uint32 wait_event_info)
     225                 :             : {
     226                 :           0 :         int                     ret = 0;
     227                 :           0 :         int                     rc;
     228                 :           0 :         WaitEvent       event;
     229                 :           0 :         WaitEventSet *set = CreateWaitEventSet(CurrentResourceOwner, 3);
     230                 :             : 
     231         [ #  # ]:           0 :         if (wakeEvents & WL_TIMEOUT)
     232         [ #  # ]:           0 :                 Assert(timeout >= 0);
     233                 :             :         else
     234                 :           0 :                 timeout = -1;
     235                 :             : 
     236         [ #  # ]:           0 :         if (wakeEvents & WL_LATCH_SET)
     237                 :           0 :                 AddWaitEventToSet(set, WL_LATCH_SET, PGINVALID_SOCKET,
     238                 :           0 :                                                   latch, NULL);
     239                 :             : 
     240                 :             :         /* Postmaster-managed callers must handle postmaster death somehow. */
     241   [ #  #  #  #  :           0 :         Assert(!IsUnderPostmaster ||
                   #  # ]
     242                 :             :                    (wakeEvents & WL_EXIT_ON_PM_DEATH) ||
     243                 :             :                    (wakeEvents & WL_POSTMASTER_DEATH));
     244                 :             : 
     245   [ #  #  #  # ]:           0 :         if ((wakeEvents & WL_POSTMASTER_DEATH) && IsUnderPostmaster)
     246                 :           0 :                 AddWaitEventToSet(set, WL_POSTMASTER_DEATH, PGINVALID_SOCKET,
     247                 :             :                                                   NULL, NULL);
     248                 :             : 
     249   [ #  #  #  # ]:           0 :         if ((wakeEvents & WL_EXIT_ON_PM_DEATH) && IsUnderPostmaster)
     250                 :           0 :                 AddWaitEventToSet(set, WL_EXIT_ON_PM_DEATH, PGINVALID_SOCKET,
     251                 :             :                                                   NULL, NULL);
     252                 :             : 
     253         [ #  # ]:           0 :         if (wakeEvents & WL_SOCKET_MASK)
     254                 :             :         {
     255                 :           0 :                 int                     ev;
     256                 :             : 
     257                 :           0 :                 ev = wakeEvents & WL_SOCKET_MASK;
     258                 :           0 :                 AddWaitEventToSet(set, ev, sock, NULL, NULL);
     259                 :           0 :         }
     260                 :             : 
     261                 :           0 :         rc = WaitEventSetWait(set, timeout, &event, 1, wait_event_info);
     262                 :             : 
     263         [ #  # ]:           0 :         if (rc == 0)
     264                 :           0 :                 ret |= WL_TIMEOUT;
     265                 :             :         else
     266                 :             :         {
     267                 :           0 :                 ret |= event.events & (WL_LATCH_SET |
     268                 :             :                                                            WL_POSTMASTER_DEATH |
     269                 :             :                                                            WL_SOCKET_MASK);
     270                 :             :         }
     271                 :             : 
     272                 :           0 :         FreeWaitEventSet(set);
     273                 :             : 
     274                 :           0 :         return ret;
     275                 :           0 : }
     276                 :             : 
     277                 :             : /*
     278                 :             :  * Sets a latch and wakes up anyone waiting on it.
     279                 :             :  *
     280                 :             :  * This is cheap if the latch is already set, otherwise not so much.
     281                 :             :  *
     282                 :             :  * NB: when calling this in a signal handler, be sure to save and restore
     283                 :             :  * errno around it.  (That's standard practice in most signal handlers, of
     284                 :             :  * course, but we used to omit it in handlers that only set a flag.)
     285                 :             :  *
     286                 :             :  * NB: this function is called from critical sections and signal handlers so
     287                 :             :  * throwing an error is not a good idea.
     288                 :             :  */
     289                 :             : void
     290                 :       10037 : SetLatch(Latch *latch)
     291                 :             : {
     292                 :             : #ifndef WIN32
     293                 :       10037 :         pid_t           owner_pid;
     294                 :             : #else
     295                 :             :         HANDLE          handle;
     296                 :             : #endif
     297                 :             : 
     298                 :             :         /*
     299                 :             :          * The memory barrier has to be placed here to ensure that any flag
     300                 :             :          * variables possibly changed by this process have been flushed to main
     301                 :             :          * memory, before we check/set is_set.
     302                 :             :          */
     303                 :       10037 :         pg_memory_barrier();
     304                 :             : 
     305                 :             :         /* Quick exit if already set */
     306         [ +  + ]:       10037 :         if (latch->is_set)
     307                 :        4655 :                 return;
     308                 :             : 
     309                 :        5382 :         latch->is_set = true;
     310                 :             : 
     311                 :        5382 :         pg_memory_barrier();
     312         [ +  + ]:        5382 :         if (!latch->maybe_sleeping)
     313                 :        1717 :                 return;
     314                 :             : 
     315                 :             : #ifndef WIN32
     316                 :             : 
     317                 :             :         /*
     318                 :             :          * See if anyone's waiting for the latch. It can be the current process if
     319                 :             :          * we're in a signal handler. We use the self-pipe or SIGURG to ourselves
     320                 :             :          * to wake up WaitEventSetWaitBlock() without races in that case. If it's
     321                 :             :          * another process, send a signal.
     322                 :             :          *
     323                 :             :          * Fetch owner_pid only once, in case the latch is concurrently getting
     324                 :             :          * owned or disowned. XXX: This assumes that pid_t is atomic, which isn't
     325                 :             :          * guaranteed to be true! In practice, the effective range of pid_t fits
     326                 :             :          * in a 32 bit integer, and so should be atomic. In the worst case, we
     327                 :             :          * might end up signaling the wrong process. Even then, you're very
     328                 :             :          * unlucky if a process with that bogus pid exists and belongs to
     329                 :             :          * Postgres; and PG database processes should handle excess SIGUSR1
     330                 :             :          * interrupts without a problem anyhow.
     331                 :             :          *
     332                 :             :          * Another sort of race condition that's possible here is for a new
     333                 :             :          * process to own the latch immediately after we look, so we don't signal
     334                 :             :          * it. This is okay so long as all callers of ResetLatch/WaitLatch follow
     335                 :             :          * the standard coding convention of waiting at the bottom of their loops,
     336                 :             :          * not the top, so that they'll correctly process latch-setting events
     337                 :             :          * that happen before they enter the loop.
     338                 :             :          */
     339                 :        3665 :         owner_pid = latch->owner_pid;
     340         [ +  - ]:        3665 :         if (owner_pid == 0)
     341                 :           0 :                 return;
     342         [ +  + ]:        3665 :         else if (owner_pid == MyProcPid)
     343                 :        1361 :                 WakeupMyProc();
     344                 :             :         else
     345                 :        2304 :                 WakeupOtherProc(owner_pid);
     346                 :             : 
     347                 :             : #else
     348                 :             : 
     349                 :             :         /*
     350                 :             :          * See if anyone's waiting for the latch. It can be the current process if
     351                 :             :          * we're in a signal handler.
     352                 :             :          *
     353                 :             :          * Use a local variable here just in case somebody changes the event field
     354                 :             :          * concurrently (which really should not happen).
     355                 :             :          */
     356                 :             :         handle = latch->event;
     357                 :             :         if (handle)
     358                 :             :         {
     359                 :             :                 SetEvent(handle);
     360                 :             : 
     361                 :             :                 /*
     362                 :             :                  * Note that we silently ignore any errors. We might be in a signal
     363                 :             :                  * handler or other critical path where it's not safe to call elog().
     364                 :             :                  */
     365                 :             :         }
     366                 :             : #endif
     367         [ -  + ]:       10037 : }
     368                 :             : 
     369                 :             : /*
     370                 :             :  * Clear the latch. Calling WaitLatch after this will sleep, unless
     371                 :             :  * the latch is set again before the WaitLatch call.
     372                 :             :  */
     373                 :             : void
     374                 :        4574 : ResetLatch(Latch *latch)
     375                 :             : {
     376                 :             :         /* Only the owner should reset the latch */
     377         [ +  - ]:        4574 :         Assert(latch->owner_pid == MyProcPid);
     378         [ +  - ]:        4574 :         Assert(latch->maybe_sleeping == false);
     379                 :             : 
     380                 :        4574 :         latch->is_set = false;
     381                 :             : 
     382                 :             :         /*
     383                 :             :          * Ensure that the write to is_set gets flushed to main memory before we
     384                 :             :          * examine any flag variables.  Otherwise a concurrent SetLatch might
     385                 :             :          * falsely conclude that it needn't signal us, even though we have missed
     386                 :             :          * seeing some flag updates that SetLatch was supposed to inform us of.
     387                 :             :          */
     388                 :        4574 :         pg_memory_barrier();
     389                 :        4574 : }
        

Generated by: LCOV version 2.3.2-1