LCOV - code coverage report
Current view: top level - src/backend/storage/ipc - latch.c (source / functions) Hit Total Coverage
Test: PostgreSQL 19devel Lines: 73 76 96.1 %
Date: 2025-07-29 03:18:01 Functions: 9 9 100.0 %
Legend: Lines: hit not hit

          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-2025, 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       43658 : InitializeLatchWaitSet(void)
      36             : {
      37             :     int         latch_pos PG_USED_FOR_ASSERTS_ONLY;
      38             : 
      39             :     Assert(LatchWaitSet == NULL);
      40             : 
      41             :     /* Set up the WaitEventSet used by WaitLatch(). */
      42       43658 :     LatchWaitSet = CreateWaitEventSet(NULL, 2);
      43       43658 :     latch_pos = AddWaitEventToSet(LatchWaitSet, WL_LATCH_SET, PGINVALID_SOCKET,
      44             :                                   MyLatch, NULL);
      45             :     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       43658 :     if (IsUnderPostmaster)
      52             :     {
      53       43178 :         latch_pos = AddWaitEventToSet(LatchWaitSet, WL_EXIT_ON_PM_DEATH,
      54             :                                       PGINVALID_SOCKET, NULL, NULL);
      55             :         Assert(latch_pos == LatchWaitSetPostmasterDeathPos);
      56             :     }
      57       43658 : }
      58             : 
      59             : /*
      60             :  * Initialize a process-local latch.
      61             :  */
      62             : void
      63       45406 : InitLatch(Latch *latch)
      64             : {
      65       45406 :     latch->is_set = false;
      66       45406 :     latch->maybe_sleeping = false;
      67       45406 :     latch->owner_pid = MyProcPid;
      68       45406 :     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       45406 : }
      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      284174 : 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      284174 :     latch->is_set = false;
     111      284174 :     latch->maybe_sleeping = false;
     112      284174 :     latch->owner_pid = 0;
     113      284174 :     latch->is_shared = true;
     114      284174 : }
     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       42802 : OwnLatch(Latch *latch)
     127             : {
     128             :     int         owner_pid;
     129             : 
     130             :     /* Sanity checks */
     131             :     Assert(latch->is_shared);
     132             : 
     133       42802 :     owner_pid = latch->owner_pid;
     134       42802 :     if (owner_pid != 0)
     135           0 :         elog(PANIC, "latch already owned by PID %d", owner_pid);
     136             : 
     137       42802 :     latch->owner_pid = MyProcPid;
     138       42802 : }
     139             : 
     140             : /*
     141             :  * Disown a shared latch currently owned by the current process.
     142             :  */
     143             : void
     144       42682 : DisownLatch(Latch *latch)
     145             : {
     146             :     Assert(latch->is_shared);
     147             :     Assert(latch->owner_pid == MyProcPid);
     148             : 
     149       42682 :     latch->owner_pid = 0;
     150       42682 : }
     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     2028572 : WaitLatch(Latch *latch, int wakeEvents, long timeout,
     173             :           uint32 wait_event_info)
     174             : {
     175             :     WaitEvent   event;
     176             : 
     177             :     /* Postmaster-managed callers must handle postmaster death somehow. */
     178             :     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     2028572 :     if (!(wakeEvents & WL_LATCH_SET))
     188         340 :         latch = NULL;
     189     2028572 :     ModifyWaitEvent(LatchWaitSet, LatchWaitSetLatchPos, WL_LATCH_SET, latch);
     190             : 
     191     2028572 :     if (IsUnderPostmaster)
     192     2028572 :         ModifyWaitEvent(LatchWaitSet, LatchWaitSetPostmasterDeathPos,
     193     2028572 :                         (wakeEvents & (WL_EXIT_ON_PM_DEATH | WL_POSTMASTER_DEATH)),
     194             :                         NULL);
     195             : 
     196     2028572 :     if (WaitEventSetWait(LatchWaitSet,
     197     2028572 :                          (wakeEvents & WL_TIMEOUT) ? timeout : -1,
     198             :                          &event, 1,
     199             :                          wait_event_info) == 0)
     200       65878 :         return WL_TIMEOUT;
     201             :     else
     202     1962636 :         return event.events;
     203             : }
     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      232582 : WaitLatchOrSocket(Latch *latch, int wakeEvents, pgsocket sock,
     224             :                   long timeout, uint32 wait_event_info)
     225             : {
     226      232582 :     int         ret = 0;
     227             :     int         rc;
     228             :     WaitEvent   event;
     229      232582 :     WaitEventSet *set = CreateWaitEventSet(CurrentResourceOwner, 3);
     230             : 
     231      232582 :     if (wakeEvents & WL_TIMEOUT)
     232             :         Assert(timeout >= 0);
     233             :     else
     234       29294 :         timeout = -1;
     235             : 
     236      232582 :     if (wakeEvents & WL_LATCH_SET)
     237      232344 :         AddWaitEventToSet(set, WL_LATCH_SET, PGINVALID_SOCKET,
     238             :                           latch, NULL);
     239             : 
     240             :     /* Postmaster-managed callers must handle postmaster death somehow. */
     241             :     Assert(!IsUnderPostmaster ||
     242             :            (wakeEvents & WL_EXIT_ON_PM_DEATH) ||
     243             :            (wakeEvents & WL_POSTMASTER_DEATH));
     244             : 
     245      232582 :     if ((wakeEvents & WL_POSTMASTER_DEATH) && IsUnderPostmaster)
     246           0 :         AddWaitEventToSet(set, WL_POSTMASTER_DEATH, PGINVALID_SOCKET,
     247             :                           NULL, NULL);
     248             : 
     249      232582 :     if ((wakeEvents & WL_EXIT_ON_PM_DEATH) && IsUnderPostmaster)
     250      232582 :         AddWaitEventToSet(set, WL_EXIT_ON_PM_DEATH, PGINVALID_SOCKET,
     251             :                           NULL, NULL);
     252             : 
     253      232582 :     if (wakeEvents & WL_SOCKET_MASK)
     254             :     {
     255             :         int         ev;
     256             : 
     257      232582 :         ev = wakeEvents & WL_SOCKET_MASK;
     258      232582 :         AddWaitEventToSet(set, ev, sock, NULL, NULL);
     259             :     }
     260             : 
     261      232582 :     rc = WaitEventSetWait(set, timeout, &event, 1, wait_event_info);
     262             : 
     263      232582 :     if (rc == 0)
     264         552 :         ret |= WL_TIMEOUT;
     265             :     else
     266             :     {
     267      232030 :         ret |= event.events & (WL_LATCH_SET |
     268             :                                WL_POSTMASTER_DEATH |
     269             :                                WL_SOCKET_MASK);
     270             :     }
     271             : 
     272      232582 :     FreeWaitEventSet(set);
     273             : 
     274      232582 :     return ret;
     275             : }
     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     2917804 : SetLatch(Latch *latch)
     291             : {
     292             : #ifndef WIN32
     293             :     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     2917804 :     pg_memory_barrier();
     304             : 
     305             :     /* Quick exit if already set */
     306     2917804 :     if (latch->is_set)
     307      374286 :         return;
     308             : 
     309     2543518 :     latch->is_set = true;
     310             : 
     311     2543518 :     pg_memory_barrier();
     312     2543518 :     if (!latch->maybe_sleeping)
     313      147656 :         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     2395862 :     owner_pid = latch->owner_pid;
     340     2395862 :     if (owner_pid == 0)
     341           0 :         return;
     342     2395862 :     else if (owner_pid == MyProcPid)
     343      272202 :         WakeupMyProc();
     344             :     else
     345     2123660 :         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             : }
     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     3794878 : ResetLatch(Latch *latch)
     375             : {
     376             :     /* Only the owner should reset the latch */
     377             :     Assert(latch->owner_pid == MyProcPid);
     378             :     Assert(latch->maybe_sleeping == false);
     379             : 
     380     3794878 :     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     3794878 :     pg_memory_barrier();
     389     3794878 : }

Generated by: LCOV version 1.16