LCOV - differential code coverage report
Current view: top level - src/backend/storage/ipc - latch.c (source / functions) Coverage Total Hit UBC CBC
Current: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 96.6 % 87 84 3 84
Current Date: 2025-09-06 07:49:51 +0900 Functions: 100.0 % 9 9 9
Baseline: lcov-20250906-005545-baseline Branches: 61.8 % 68 42 26 42
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 100.0 % 8 8 8
(360..) days: 96.2 % 79 76 3 76
Function coverage date bins:
(360..) days: 100.0 % 9 9 9
Branch coverage date bins:
(30,360] days: 66.7 % 6 4 2 4
(360..) days: 61.3 % 62 38 24 38

 Age         Owner                    Branch data    TLA  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
 1864 tmunro@postgresql.or       35                 :CBC       19220 : InitializeLatchWaitSet(void)
                                 36                 :                : {
                                 37                 :                :     int         latch_pos PG_USED_FOR_ASSERTS_ONLY;
                                 38                 :                : 
                                 39         [ -  + ]:          19220 :     Assert(LatchWaitSet == NULL);
                                 40                 :                : 
                                 41                 :                :     /* Set up the WaitEventSet used by WaitLatch(). */
  653 heikki.linnakangas@i       42                 :          19220 :     LatchWaitSet = CreateWaitEventSet(NULL, 2);
 1864 tmunro@postgresql.or       43                 :          19220 :     latch_pos = AddWaitEventToSet(LatchWaitSet, WL_LATCH_SET, PGINVALID_SOCKET,
                                 44                 :                :                                   MyLatch, NULL);
                                 45         [ -  + ]:          19220 :     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                 :                :      */
  184 heikki.linnakangas@i       51         [ +  + ]:          19220 :     if (IsUnderPostmaster)
                                 52                 :                :     {
                                 53                 :          18974 :         latch_pos = AddWaitEventToSet(LatchWaitSet, WL_EXIT_ON_PM_DEATH,
                                 54                 :                :                                       PGINVALID_SOCKET, NULL, NULL);
                                 55         [ -  + ]:          18974 :         Assert(latch_pos == LatchWaitSetPostmasterDeathPos);
                                 56                 :                :     }
 1864 tmunro@postgresql.or       57                 :          19220 : }
                                 58                 :                : 
                                 59                 :                : /*
                                 60                 :                :  * Initialize a process-local latch.
                                 61                 :                :  */
                                 62                 :                : void
 2385 peter@eisentraut.org       63                 :          20041 : InitLatch(Latch *latch)
                                 64                 :                : {
 5474 heikki.linnakangas@i       65                 :          20041 :     latch->is_set = false;
 1650 tmunro@postgresql.or       66                 :          20041 :     latch->maybe_sleeping = false;
 5474 heikki.linnakangas@i       67                 :          20041 :     latch->owner_pid = MyProcPid;
                                 68                 :          20041 :     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                 :          20041 : }
                                 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
 2385 peter@eisentraut.org       93                 :         134389 : 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                 :                : 
 5474 heikki.linnakangas@i      110                 :         134389 :     latch->is_set = false;
 1650 tmunro@postgresql.or      111                 :         134389 :     latch->maybe_sleeping = false;
 5474 heikki.linnakangas@i      112                 :         134389 :     latch->owner_pid = 0;
                                113                 :         134389 :     latch->is_shared = true;
                                114                 :         134389 : }
                                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
 2385 peter@eisentraut.org      126                 :          18867 : OwnLatch(Latch *latch)
                                127                 :                : {
                                128                 :                :     int         owner_pid;
                                129                 :                : 
                                130                 :                :     /* Sanity checks */
 3456 andres@anarazel.de        131         [ -  + ]:          18867 :     Assert(latch->is_shared);
                                132                 :                : 
 1194 tmunro@postgresql.or      133                 :          18867 :     owner_pid = latch->owner_pid;
                                134         [ -  + ]:          18867 :     if (owner_pid != 0)
 1194 tmunro@postgresql.or      135         [ #  # ]:UBC           0 :         elog(PANIC, "latch already owned by PID %d", owner_pid);
                                136                 :                : 
 5474 heikki.linnakangas@i      137                 :CBC       18867 :     latch->owner_pid = MyProcPid;
                                138                 :          18867 : }
                                139                 :                : 
                                140                 :                : /*
                                141                 :                :  * Disown a shared latch currently owned by the current process.
                                142                 :                :  */
                                143                 :                : void
 2385 peter@eisentraut.org      144                 :          18812 : DisownLatch(Latch *latch)
                                145                 :                : {
 5474 heikki.linnakangas@i      146         [ -  + ]:          18812 :     Assert(latch->is_shared);
                                147         [ -  + ]:          18812 :     Assert(latch->owner_pid == MyProcPid);
                                148                 :                : 
                                149                 :          18812 :     latch->owner_pid = 0;
                                150                 :          18812 : }
                                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
 2385 peter@eisentraut.org      172                 :        1005828 : 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. */
 1864 tmunro@postgresql.or      178   [ +  -  +  +  :        1005828 :     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         [ +  + ]:        1005828 :     if (!(wakeEvents & WL_LATCH_SET))
                                188                 :             10 :         latch = NULL;
                                189                 :        1005828 :     ModifyWaitEvent(LatchWaitSet, LatchWaitSetLatchPos, WL_LATCH_SET, latch);
                                190                 :                : 
   43 michael@paquier.xyz       191         [ +  - ]:        1005828 :     if (IsUnderPostmaster)
                                192                 :        1005828 :         ModifyWaitEvent(LatchWaitSet, LatchWaitSetPostmasterDeathPos,
                                193                 :        1005828 :                         (wakeEvents & (WL_EXIT_ON_PM_DEATH | WL_POSTMASTER_DEATH)),
                                194                 :                :                         NULL);
                                195                 :                : 
 1864 tmunro@postgresql.or      196         [ +  + ]:        1005828 :     if (WaitEventSetWait(LatchWaitSet,
                                197         [ +  + ]:        1005828 :                          (wakeEvents & WL_TIMEOUT) ? timeout : -1,
                                198                 :                :                          &event, 1,
                                199                 :                :                          wait_event_info) == 0)
                                200                 :          23902 :         return WL_TIMEOUT;
                                201                 :                :     else
                                202                 :         981902 :         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
 2385 peter@eisentraut.org      223                 :         116821 : WaitLatchOrSocket(Latch *latch, int wakeEvents, pgsocket sock,
                                224                 :                :                   long timeout, uint32 wait_event_info)
                                225                 :                : {
 3456 andres@anarazel.de        226                 :         116821 :     int         ret = 0;
                                227                 :                :     int         rc;
                                228                 :                :     WaitEvent   event;
  653 heikki.linnakangas@i      229                 :         116821 :     WaitEventSet *set = CreateWaitEventSet(CurrentResourceOwner, 3);
                                230                 :                : 
 5174                           231         [ +  + ]:         116821 :     if (wakeEvents & WL_TIMEOUT)
 3456 andres@anarazel.de        232         [ -  + ]:         101797 :         Assert(timeout >= 0);
                                233                 :                :     else
                                234                 :          15024 :         timeout = -1;
                                235                 :                : 
                                236         [ +  + ]:         116821 :     if (wakeEvents & WL_LATCH_SET)
                                237                 :         116428 :         AddWaitEventToSet(set, WL_LATCH_SET, PGINVALID_SOCKET,
                                238                 :                :                           latch, NULL);
                                239                 :                : 
                                240                 :                :     /* Postmaster-managed callers must handle postmaster death somehow. */
 2479 tmunro@postgresql.or      241   [ +  -  -  +  :         116821 :     Assert(!IsUnderPostmaster ||
                                              -  - ]
                                242                 :                :            (wakeEvents & WL_EXIT_ON_PM_DEATH) ||
                                243                 :                :            (wakeEvents & WL_POSTMASTER_DEATH));
                                244                 :                : 
                                245   [ -  +  -  - ]:         116821 :     if ((wakeEvents & WL_POSTMASTER_DEATH) && IsUnderPostmaster)
 3456 andres@anarazel.de        246                 :UBC           0 :         AddWaitEventToSet(set, WL_POSTMASTER_DEATH, PGINVALID_SOCKET,
                                247                 :                :                           NULL, NULL);
                                248                 :                : 
 2479 tmunro@postgresql.or      249   [ +  -  +  - ]:CBC      116821 :     if ((wakeEvents & WL_EXIT_ON_PM_DEATH) && IsUnderPostmaster)
                                250                 :         116821 :         AddWaitEventToSet(set, WL_EXIT_ON_PM_DEATH, PGINVALID_SOCKET,
                                251                 :                :                           NULL, NULL);
                                252                 :                : 
 2944 tgl@sss.pgh.pa.us         253         [ +  - ]:         116821 :     if (wakeEvents & WL_SOCKET_MASK)
                                254                 :                :     {
                                255                 :                :         int         ev;
                                256                 :                : 
                                257                 :         116821 :         ev = wakeEvents & WL_SOCKET_MASK;
 3456 andres@anarazel.de        258                 :         116821 :         AddWaitEventToSet(set, ev, sock, NULL, NULL);
                                259                 :                :     }
                                260                 :                : 
 3259 rhaas@postgresql.org      261                 :         116821 :     rc = WaitEventSetWait(set, timeout, &event, 1, wait_event_info);
                                262                 :                : 
 3456 andres@anarazel.de        263         [ +  + ]:         116821 :     if (rc == 0)
                                264                 :            218 :         ret |= WL_TIMEOUT;
                                265                 :                :     else
                                266                 :                :     {
                                267                 :         116603 :         ret |= event.events & (WL_LATCH_SET |
                                268                 :                :                                WL_POSTMASTER_DEATH |
                                269                 :                :                                WL_SOCKET_MASK);
                                270                 :                :     }
                                271                 :                : 
                                272                 :         116821 :     FreeWaitEventSet(set);
                                273                 :                : 
                                274                 :         116821 :     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
 2385 peter@eisentraut.org      290                 :        1340949 : 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                 :                :      */
 3889 andres@anarazel.de        303                 :        1340949 :     pg_memory_barrier();
                                304                 :                : 
                                305                 :                :     /* Quick exit if already set */
 5474 heikki.linnakangas@i      306         [ +  + ]:        1340949 :     if (latch->is_set)
                                307                 :         207077 :         return;
                                308                 :                : 
                                309                 :        1133872 :     latch->is_set = true;
                                310                 :                : 
 1650 tmunro@postgresql.or      311                 :        1133872 :     pg_memory_barrier();
                                312         [ +  + ]:        1133872 :     if (!latch->maybe_sleeping)
                                313                 :          77695 :         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                 :                :      */
 5474 heikki.linnakangas@i      339                 :        1056177 :     owner_pid = latch->owner_pid;
                                340         [ -  + ]:        1056177 :     if (owner_pid == 0)
 5474 heikki.linnakangas@i      341                 :UBC           0 :         return;
 5474 heikki.linnakangas@i      342         [ +  + ]:CBC     1056177 :     else if (owner_pid == MyProcPid)
  184                           343                 :          34771 :         WakeupMyProc();
                                344                 :                :     else
                                345                 :        1021406 :         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
 2385 peter@eisentraut.org      374                 :        1785456 : ResetLatch(Latch *latch)
                                375                 :                : {
                                376                 :                :     /* Only the owner should reset the latch */
 5474 heikki.linnakangas@i      377         [ -  + ]:        1785456 :     Assert(latch->owner_pid == MyProcPid);
 1650 tmunro@postgresql.or      378         [ -  + ]:        1785456 :     Assert(latch->maybe_sleeping == false);
                                379                 :                : 
 5474 heikki.linnakangas@i      380                 :        1785456 :     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                 :                :      */
 3889 andres@anarazel.de        388                 :        1785456 :     pg_memory_barrier();
 5474 heikki.linnakangas@i      389                 :        1785456 : }
        

Generated by: LCOV version 2.4-beta