LCOV - code coverage report
Current view: top level - src/backend/storage/ipc - latch.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 96.1 % 76 73
Test Date: 2026-03-04 04:14:49 Functions: 100.0 % 9 9
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-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        23730 : 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        23730 :     LatchWaitSet = CreateWaitEventSet(NULL, 2);
      43        23730 :     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        23730 :     if (IsUnderPostmaster)
      52              :     {
      53        23480 :         latch_pos = AddWaitEventToSet(LatchWaitSet, WL_EXIT_ON_PM_DEATH,
      54              :                                       PGINVALID_SOCKET, NULL, NULL);
      55              :         Assert(latch_pos == LatchWaitSetPostmasterDeathPos);
      56              :     }
      57        23730 : }
      58              : 
      59              : /*
      60              :  * Initialize a process-local latch.
      61              :  */
      62              : void
      63        24668 : InitLatch(Latch *latch)
      64              : {
      65        24668 :     latch->is_set = false;
      66        24668 :     latch->maybe_sleeping = false;
      67        24668 :     latch->owner_pid = MyProcPid;
      68        24668 :     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        24668 : }
      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       150885 : 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       150885 :     latch->is_set = false;
     111       150885 :     latch->maybe_sleeping = false;
     112       150885 :     latch->owner_pid = 0;
     113       150885 :     latch->is_shared = true;
     114       150885 : }
     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        23446 : OwnLatch(Latch *latch)
     127              : {
     128              :     int         owner_pid;
     129              : 
     130              :     /* Sanity checks */
     131              :     Assert(latch->is_shared);
     132              : 
     133        23446 :     owner_pid = latch->owner_pid;
     134        23446 :     if (owner_pid != 0)
     135            0 :         elog(PANIC, "latch already owned by PID %d", owner_pid);
     136              : 
     137        23446 :     latch->owner_pid = MyProcPid;
     138        23446 : }
     139              : 
     140              : /*
     141              :  * Disown a shared latch currently owned by the current process.
     142              :  */
     143              : void
     144        23384 : DisownLatch(Latch *latch)
     145              : {
     146              :     Assert(latch->is_shared);
     147              :     Assert(latch->owner_pid == MyProcPid);
     148              : 
     149        23384 :     latch->owner_pid = 0;
     150        23384 : }
     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      1076912 : 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      1076912 :     if (!(wakeEvents & WL_LATCH_SET))
     188           86 :         latch = NULL;
     189      1076912 :     ModifyWaitEvent(LatchWaitSet, LatchWaitSetLatchPos, WL_LATCH_SET, latch);
     190              : 
     191      1076912 :     if (IsUnderPostmaster)
     192      1076912 :         ModifyWaitEvent(LatchWaitSet, LatchWaitSetPostmasterDeathPos,
     193      1076912 :                         (wakeEvents & (WL_EXIT_ON_PM_DEATH | WL_POSTMASTER_DEATH)),
     194              :                         NULL);
     195              : 
     196      1076912 :     if (WaitEventSetWait(LatchWaitSet,
     197      1076912 :                          (wakeEvents & WL_TIMEOUT) ? timeout : -1,
     198              :                          &event, 1,
     199              :                          wait_event_info) == 0)
     200        31743 :         return WL_TIMEOUT;
     201              :     else
     202      1045130 :         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        91611 : WaitLatchOrSocket(Latch *latch, int wakeEvents, pgsocket sock,
     224              :                   long timeout, uint32 wait_event_info)
     225              : {
     226        91611 :     int         ret = 0;
     227              :     int         rc;
     228              :     WaitEvent   event;
     229        91611 :     WaitEventSet *set = CreateWaitEventSet(CurrentResourceOwner, 3);
     230              : 
     231        91611 :     if (wakeEvents & WL_TIMEOUT)
     232              :         Assert(timeout >= 0);
     233              :     else
     234        15489 :         timeout = -1;
     235              : 
     236        91611 :     if (wakeEvents & WL_LATCH_SET)
     237        91263 :         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        91611 :     if ((wakeEvents & WL_POSTMASTER_DEATH) && IsUnderPostmaster)
     246            0 :         AddWaitEventToSet(set, WL_POSTMASTER_DEATH, PGINVALID_SOCKET,
     247              :                           NULL, NULL);
     248              : 
     249        91611 :     if ((wakeEvents & WL_EXIT_ON_PM_DEATH) && IsUnderPostmaster)
     250        91611 :         AddWaitEventToSet(set, WL_EXIT_ON_PM_DEATH, PGINVALID_SOCKET,
     251              :                           NULL, NULL);
     252              : 
     253        91611 :     if (wakeEvents & WL_SOCKET_MASK)
     254              :     {
     255              :         int         ev;
     256              : 
     257        91611 :         ev = wakeEvents & WL_SOCKET_MASK;
     258        91611 :         AddWaitEventToSet(set, ev, sock, NULL, NULL);
     259              :     }
     260              : 
     261        91611 :     rc = WaitEventSetWait(set, timeout, &event, 1, wait_event_info);
     262              : 
     263        91611 :     if (rc == 0)
     264          337 :         ret |= WL_TIMEOUT;
     265              :     else
     266              :     {
     267        91274 :         ret |= event.events & (WL_LATCH_SET |
     268              :                                WL_POSTMASTER_DEATH |
     269              :                                WL_SOCKET_MASK);
     270              :     }
     271              : 
     272        91611 :     FreeWaitEventSet(set);
     273              : 
     274        91611 :     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      1513689 : 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      1513689 :     pg_memory_barrier();
     304              : 
     305              :     /* Quick exit if already set */
     306      1513689 :     if (latch->is_set)
     307       188009 :         return;
     308              : 
     309      1325680 :     latch->is_set = true;
     310              : 
     311      1325680 :     pg_memory_barrier();
     312      1325680 :     if (!latch->maybe_sleeping)
     313       120634 :         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      1205046 :     owner_pid = latch->owner_pid;
     340      1205046 :     if (owner_pid == 0)
     341            0 :         return;
     342      1205046 :     else if (owner_pid == MyProcPid)
     343       160603 :         WakeupMyProc();
     344              :     else
     345      1044443 :         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      2305881 : 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      2305881 :     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      2305881 :     pg_memory_barrier();
     389      2305881 : }
        

Generated by: LCOV version 2.0-1