123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- /*-------------------------------------------------------------------------
- *
- * latch.h
- * Routines for interprocess latches
- *
- * A latch is a boolean variable, with operations that let processes sleep
- * until it is set. A latch can be set from another process, or a signal
- * handler within the same process.
- *
- * The latch interface is a reliable replacement for the common pattern of
- * using pg_usleep() or select() to wait until a signal arrives, where the
- * signal handler sets a flag variable. Because on some platforms an
- * incoming signal doesn't interrupt sleep, and even on platforms where it
- * does there is a race condition if the signal arrives just before
- * entering the sleep, the common pattern must periodically wake up and
- * poll the flag variable. The pselect() system call was invented to solve
- * this problem, but it is not portable enough. Latches are designed to
- * overcome these limitations, allowing you to sleep without polling and
- * ensuring quick response to signals from other processes.
- *
- * There are two kinds of latches: local and shared. A local latch is
- * initialized by InitLatch, and can only be set from the same process.
- * A local latch can be used to wait for a signal to arrive, by calling
- * SetLatch in the signal handler. A shared latch resides in shared memory,
- * and must be initialized at postmaster startup by InitSharedLatch. Before
- * a shared latch can be waited on, it must be associated with a process
- * with OwnLatch. Only the process owning the latch can wait on it, but any
- * process can set it.
- *
- * There are three basic operations on a latch:
- *
- * SetLatch - Sets the latch
- * ResetLatch - Clears the latch, allowing it to be set again
- * WaitLatch - Waits for the latch to become set
- *
- * WaitLatch includes a provision for timeouts (which should be avoided
- * when possible, as they incur extra overhead) and a provision for
- * postmaster child processes to wake up immediately on postmaster death.
- * See latch.c for detailed specifications for the exported functions.
- *
- * The correct pattern to wait for event(s) is:
- *
- * for (;;)
- * {
- * ResetLatch();
- * if (work to do)
- * Do Stuff();
- * WaitLatch();
- * }
- *
- * It's important to reset the latch *before* checking if there's work to
- * do. Otherwise, if someone sets the latch between the check and the
- * ResetLatch call, you will miss it and Wait will incorrectly block.
- *
- * Another valid coding pattern looks like:
- *
- * for (;;)
- * {
- * if (work to do)
- * Do Stuff(); // in particular, exit loop if some condition satisfied
- * WaitLatch();
- * ResetLatch();
- * }
- *
- * This is useful to reduce latch traffic if it's expected that the loop's
- * termination condition will often be satisfied in the first iteration;
- * the cost is an extra loop iteration before blocking when it is not.
- * What must be avoided is placing any checks for asynchronous events after
- * WaitLatch and before ResetLatch, as that creates a race condition.
- *
- * To wake up the waiter, you must first set a global flag or something
- * else that the wait loop tests in the "if (work to do)" part, and call
- * SetLatch *after* that. SetLatch is designed to return quickly if the
- * latch is already set.
- *
- * On some platforms, signals will not interrupt the latch wait primitive
- * by themselves. Therefore, it is critical that any signal handler that
- * is meant to terminate a WaitLatch wait calls SetLatch.
- *
- * Note that use of the process latch (PGPROC.procLatch) is generally better
- * than an ad-hoc shared latch for signaling auxiliary processes. This is
- * because generic signal handlers will call SetLatch on the process latch
- * only, so using any latch other than the process latch effectively precludes
- * use of any generic handler.
- *
- *
- * WaitEventSets allow to wait for latches being set and additional events -
- * postmaster dying and socket readiness of several sockets currently - at the
- * same time. On many platforms using a long lived event set is more
- * efficient than using WaitLatch or WaitLatchOrSocket.
- *
- *
- * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- * src/include/storage/latch.h
- *
- *-------------------------------------------------------------------------
- */
- #ifndef LATCH_H
- #define LATCH_H
- #include <signal.h>
- /*
- * Latch structure should be treated as opaque and only accessed through
- * the public functions. It is defined here to allow embedding Latches as
- * part of bigger structs.
- */
- typedef struct Latch
- {
- sig_atomic_t is_set;
- sig_atomic_t maybe_sleeping;
- bool is_shared;
- int owner_pid;
- #ifdef WIN32
- HANDLE event;
- #endif
- } Latch;
- /*
- * Bitmasks for events that may wake-up WaitLatch(), WaitLatchOrSocket(), or
- * WaitEventSetWait().
- */
- #define WL_LATCH_SET (1 << 0)
- #define WL_SOCKET_READABLE (1 << 1)
- #define WL_SOCKET_WRITEABLE (1 << 2)
- #define WL_TIMEOUT (1 << 3) /* not for WaitEventSetWait() */
- #define WL_POSTMASTER_DEATH (1 << 4)
- #define WL_EXIT_ON_PM_DEATH (1 << 5)
- #ifdef WIN32
- #define WL_SOCKET_CONNECTED (1 << 6)
- #else
- /* avoid having to deal with case on platforms not requiring it */
- #define WL_SOCKET_CONNECTED WL_SOCKET_WRITEABLE
- #endif
- #define WL_SOCKET_CLOSED (1 << 7)
- #define WL_SOCKET_MASK (WL_SOCKET_READABLE | \
- WL_SOCKET_WRITEABLE | \
- WL_SOCKET_CONNECTED | \
- WL_SOCKET_CLOSED)
- typedef struct WaitEvent
- {
- int pos; /* position in the event data structure */
- uint32 events; /* triggered events */
- pgsocket fd; /* socket fd associated with event */
- void *user_data; /* pointer provided in AddWaitEventToSet */
- #ifdef WIN32
- bool reset; /* Is reset of the event required? */
- #endif
- } WaitEvent;
- /* forward declaration to avoid exposing latch.c implementation details */
- typedef struct WaitEventSet WaitEventSet;
- /*
- * prototypes for functions in latch.c
- */
- extern void InitializeLatchSupport(void);
- extern void InitLatch(Latch *latch);
- extern void InitSharedLatch(Latch *latch);
- extern void OwnLatch(Latch *latch);
- extern void DisownLatch(Latch *latch);
- extern void SetLatch(Latch *latch);
- extern void ResetLatch(Latch *latch);
- extern void ShutdownLatchSupport(void);
- extern WaitEventSet *CreateWaitEventSet(MemoryContext context, int nevents);
- extern void FreeWaitEventSet(WaitEventSet *set);
- extern int AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd,
- Latch *latch, void *user_data);
- extern void ModifyWaitEvent(WaitEventSet *set, int pos, uint32 events, Latch *latch);
- extern int WaitEventSetWait(WaitEventSet *set, long timeout,
- WaitEvent *occurred_events, int nevents,
- uint32 wait_event_info);
- extern int WaitLatch(Latch *latch, int wakeEvents, long timeout,
- uint32 wait_event_info);
- extern int WaitLatchOrSocket(Latch *latch, int wakeEvents,
- pgsocket sock, long timeout, uint32 wait_event_info);
- extern void InitializeLatchWaitSet(void);
- extern int GetNumRegisteredWaitEvents(WaitEventSet *set);
- extern bool WaitEventSetCanReportClosed(void);
- #endif /* LATCH_H */
|