1/*-------------------------------------------------------------------------
4 * Implementation of condition variables. Condition variables provide
5 * a way for one process to wait until a specific condition occurs,
6 * without needing to know the specific identity of the process for
7 * which they are waiting. Waits for condition variables can be
8 * interrupted, unlike LWLock waits. Condition variables are safe
9 * to use within dynamic shared memory segments.
11 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
12 * Portions Copyright (c) 1994, Regents of the University of California
14 * src/backend/storage/lmgr/condition_variable.c
16 *-------------------------------------------------------------------------
28/* Initially, we are not prepared to sleep on any condition variable. */
32 * Initialize a condition variable.
42 * Prepare to wait on a given condition variable.
44 * This can optionally be called before entering a test/sleep loop.
45 * Doing so is more efficient if we'll need to sleep at least once.
46 * However, if the first test of the exit condition is likely to succeed,
47 * it's more efficient to omit the ConditionVariablePrepareToSleep call.
48 * See comments in ConditionVariableSleep for more detail.
50 * Caution: "before entering the loop" means you *must* test the exit
51 * condition between calling ConditionVariablePrepareToSleep and calling
52 * ConditionVariableSleep. If that is inconvenient, omit calling
53 * ConditionVariablePrepareToSleep.
61 * If some other sleep is already prepared, cancel it; this is necessary
62 * because we have just one static variable tracking the prepared sleep,
63 * and also only one cvWaitLink in our PGPROC. It's okay to do this
64 * because whenever control does return to the other test-and-sleep loop,
65 * its ConditionVariableSleep call will just re-establish that sleep as
71 /* Record the condition variable on which we will sleep. */
74 /* Add myself to the wait queue. */
81 * Wait for the given condition variable to be signaled.
83 * This should be called in a predicate loop that tests for a specific exit
84 * condition and otherwise sleeps, like so:
86 * ConditionVariablePrepareToSleep(cv); // optional
87 * while (condition for which we are waiting is not true)
88 * ConditionVariableSleep(cv, wait_event_info);
89 * ConditionVariableCancelSleep();
91 * wait_event_info should be a value from one of the WaitEventXXX enums
92 * defined in pgstat.h. This controls the contents of pg_stat_activity's
93 * wait_event_type and wait_event columns while waiting.
103 * Wait for a condition variable to be signaled or a timeout to be reached.
105 * The "timeout" is given in milliseconds.
107 * Returns true when timeout expires, otherwise returns false.
109 * See ConditionVariableSleep() for general usage.
115 long cur_timeout = -1;
121 * If the caller didn't prepare to sleep explicitly, then do so now and
122 * return immediately. The caller's predicate loop should immediately
123 * call again if its exit condition is not yet met. This will result in
124 * the exit condition being tested twice before we first sleep. The extra
125 * test can be prevented by calling ConditionVariablePrepareToSleep(cv)
126 * first. Whether it's worth doing that depends on whether you expect the
127 * exit condition to be met initially, in which case skipping the prepare
128 * is recommended because it avoids manipulations of the wait list, or not
129 * met initially, in which case preparing first is better because it
130 * avoids one extra test of the exit condition.
132 * If we are currently prepared to sleep on some other CV, we just cancel
133 * that and prepare this one; see ConditionVariablePrepareToSleep.
142 * Record the current time so that we can calculate the remaining timeout
143 * if we are woken up spuriously.
148 Assert(timeout >= 0 && timeout <= INT_MAX);
149 cur_timeout = timeout;
160 * Wait for latch to be set. (If we're awakened for some other
161 * reason, the code below will cope anyway.)
165 /* Reset latch before examining the state of the wait list. */
169 * If this process has been taken out of the wait list, then we know
170 * that it has been signaled by ConditionVariableSignal (or
171 * ConditionVariableBroadcast), so we should return to the caller. But
172 * that doesn't guarantee that the exit condition is met, only that we
173 * ought to check it. So we must put the process back into the wait
174 * list, to ensure we don't miss any additional wakeup occurring while
175 * the caller checks its exit condition. We can take ourselves out of
176 * the wait list only when the caller calls
177 * ConditionVariableCancelSleep.
179 * If we're still in the wait list, then the latch must have been set
180 * by something other than ConditionVariableSignal; though we don't
181 * guarantee not to return spuriously, we'll avoid this obvious case.
192 * Check for interrupts, and return spuriously if that caused the
193 * current sleep target to change (meaning that interrupt handler code
194 * waited for a different condition variable).
200 /* We were signaled, so return */
204 /* If we're not done, update cur_timeout for next iteration */
211 /* Have we crossed the timeout threshold? */
212 if (cur_timeout <= 0)
219 * Cancel any pending sleep operation.
221 * We just need to remove ourselves from the wait queue of any condition
222 * variable for which we have previously prepared a sleep.
224 * Do nothing if nothing is pending; this allows this function to be called
225 * during transaction abort to clean up any unfinished CV sleep.
227 * Return true if we've been signaled.
233 bool signaled =
false;
251 * Wake up the oldest process sleeping on the CV, if there is any.
253 * Note: it's difficult to tell whether this has any real effect: we know
254 * whether we took an entry off the list, but the entry might only be a
255 * sentinel. Hence, think twice before proposing that this should return
256 * a flag telling whether it woke somebody.
263 /* Remove the first process from the wakeup queue (if any). */
269 /* If we found someone sleeping, set their latch to wake them up. */
275 * Wake up all processes sleeping on the given CV.
277 * This guarantees to wake all processes that were sleeping on the CV
278 * at time of call, but processes that add themselves to the list mid-call
279 * will typically not get awakened.
286 bool have_sentinel =
false;
289 * In some use-cases, it is common for awakened processes to immediately
290 * re-queue themselves. If we just naively try to reduce the wakeup list
291 * to empty, we'll get into a potentially-indefinite loop against such a
292 * process. The semantics we really want are just to be sure that we have
293 * wakened all processes that were in the list at entry. We can use our
294 * own cvWaitLink as a sentinel to detect when we've finished.
296 * A seeming flaw in this approach is that someone else might signal the
297 * CV and in doing so remove our sentinel entry. But that's fine: since
298 * CV waiters are always added and removed in order, that must mean that
299 * every previous waiter has been wakened, so we're done. We'll get an
300 * extra "set" on our latch from the someone else's signal, which is
301 * slightly inefficient but harmless.
303 * We can't insert our cvWaitLink as a sentinel if it's already in use in
304 * some other proclist. While that's not expected to be true for typical
305 * uses of this function, we can deal with it by simply canceling any
306 * prepared CV sleep. The next call to ConditionVariableSleep will take
307 * care of re-establishing the lost state.
313 * Inspect the state of the queue. If it's empty, we have nothing to do.
314 * If there's exactly one entry, we need only remove and signal that
315 * entry. Otherwise, remove the first entry and insert our sentinel.
318 /* While we're here, let's assert we're not in the list. */
327 have_sentinel =
true;
332 /* Awaken first waiter, if there was one. */
336 while (have_sentinel)
339 * Each time through the loop, remove the first wakeup list entry, and
340 * signal it unless it's our sentinel. Repeat as long as the sentinel
341 * remains in the list.
343 * Notice that if someone else removes our sentinel, we will waken one
344 * additional process before exiting. That's intentional, because if
345 * someone else signals the CV, they may be intending to waken some
346 * third process that added itself to the list after we added the
347 * sentinel. Better to give a spurious wakeup (which should be
348 * harmless beyond wasting some cycles) than to lose a wakeup.
357 if (proc != NULL && proc !=
MyProc)
bool ConditionVariableCancelSleep(void)
bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout, uint32 wait_event_info)
static ConditionVariable * cv_sleep_target
void ConditionVariableBroadcast(ConditionVariable *cv)
void ConditionVariablePrepareToSleep(ConditionVariable *cv)
void ConditionVariableInit(ConditionVariable *cv)
void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info)
void ConditionVariableSignal(ConditionVariable *cv)
Assert(PointerIsAligned(start, uint64))
#define INSTR_TIME_SET_CURRENT(t)
#define INSTR_TIME_SUBTRACT(x, y)
#define INSTR_TIME_GET_MILLISEC(t)
void SetLatch(Latch *latch)
void ResetLatch(Latch *latch)
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
#define CHECK_FOR_INTERRUPTS()
#define proclist_pop_head_node(list, link_member)
#define proclist_delete(list, procno, link_member)
static void proclist_init(proclist_head *list)
#define proclist_push_tail(list, procno, link_member)
#define proclist_contains(list, procno, link_member)
static bool proclist_is_empty(const proclist_head *list)
#define SpinLockInit(lock)
#define SpinLockRelease(lock)
#define SpinLockAcquire(lock)
#define WL_EXIT_ON_PM_DEATH