2016-11-22 14:26:40 -05:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* condition_variable.h
|
|
|
|
|
* Condition variables
|
|
|
|
|
*
|
|
|
|
|
* A condition variable is a method of waiting until a certain condition
|
|
|
|
|
* becomes true. Conventionally, a condition variable supports three
|
|
|
|
|
* operations: (1) sleep; (2) signal, which wakes up one process sleeping
|
|
|
|
|
* on the condition variable; and (3) broadcast, which wakes up every
|
|
|
|
|
* process sleeping on the condition variable. In our implementation,
|
|
|
|
|
* condition variables put a process into an interruptible sleep (so it
|
2020-06-07 09:06:51 -04:00
|
|
|
* can be canceled prior to the fulfillment of the condition) and do not
|
2016-11-22 14:26:40 -05:00
|
|
|
* use pointers internally (so that they are safe to use within DSMs).
|
|
|
|
|
*
|
2022-01-07 19:04:57 -05:00
|
|
|
* Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
|
2016-11-22 14:26:40 -05:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
|
|
|
*
|
|
|
|
|
* src/include/storage/condition_variable.h
|
|
|
|
|
*
|
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
#ifndef CONDITION_VARIABLE_H
|
|
|
|
|
#define CONDITION_VARIABLE_H
|
|
|
|
|
|
|
|
|
|
#include "storage/proclist_types.h"
|
2020-06-18 22:40:09 -04:00
|
|
|
#include "storage/spin.h"
|
2016-11-22 14:26:40 -05:00
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
|
{
|
2018-01-08 18:28:03 -05:00
|
|
|
slock_t mutex; /* spinlock protecting the wakeup list */
|
|
|
|
|
proclist_head wakeup; /* list of wake-able processes */
|
2016-11-22 14:26:40 -05:00
|
|
|
} ConditionVariable;
|
|
|
|
|
|
2021-03-10 16:05:58 -05:00
|
|
|
/*
|
|
|
|
|
* Pad a condition variable to a power-of-two size so that an array of
|
|
|
|
|
* condition variables does not cross a cache line boundary.
|
|
|
|
|
*/
|
|
|
|
|
#define CV_MINIMAL_SIZE (sizeof(ConditionVariable) <= 16 ? 16 : 32)
|
|
|
|
|
typedef union ConditionVariableMinimallyPadded
|
|
|
|
|
{
|
|
|
|
|
ConditionVariable cv;
|
|
|
|
|
char pad[CV_MINIMAL_SIZE];
|
|
|
|
|
} ConditionVariableMinimallyPadded;
|
|
|
|
|
|
2016-11-22 14:26:40 -05:00
|
|
|
/* Initialize a condition variable. */
|
2018-01-08 18:28:03 -05:00
|
|
|
extern void ConditionVariableInit(ConditionVariable *cv);
|
2016-11-22 14:26:40 -05:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* To sleep on a condition variable, a process should use a loop which first
|
|
|
|
|
* checks the condition, exiting the loop if it is met, and then calls
|
|
|
|
|
* ConditionVariableSleep. Spurious wakeups are possible, but should be
|
2018-01-08 18:28:03 -05:00
|
|
|
* infrequent. After exiting the loop, ConditionVariableCancelSleep must
|
2016-11-22 14:26:40 -05:00
|
|
|
* be called to ensure that the process is no longer in the wait list for
|
2018-01-09 11:39:10 -05:00
|
|
|
* the condition variable.
|
2016-11-22 14:26:40 -05:00
|
|
|
*/
|
2018-01-08 18:28:03 -05:00
|
|
|
extern void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info);
|
2019-07-12 21:40:36 -04:00
|
|
|
extern bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout,
|
|
|
|
|
uint32 wait_event_info);
|
2016-11-22 14:26:40 -05:00
|
|
|
extern void ConditionVariableCancelSleep(void);
|
|
|
|
|
|
|
|
|
|
/*
|
2018-01-08 18:28:03 -05:00
|
|
|
* Optionally, ConditionVariablePrepareToSleep can be called before entering
|
|
|
|
|
* the test-and-sleep loop described above. Doing so is more efficient if
|
|
|
|
|
* at least one sleep is needed, whereas not doing so is more efficient when
|
|
|
|
|
* no sleep is needed because the test condition is true the first time.
|
2016-11-22 14:26:40 -05:00
|
|
|
*/
|
2018-01-08 18:28:03 -05:00
|
|
|
extern void ConditionVariablePrepareToSleep(ConditionVariable *cv);
|
2016-11-22 14:26:40 -05:00
|
|
|
|
|
|
|
|
/* Wake up a single waiter (via signal) or all waiters (via broadcast). */
|
Remove return values of ConditionVariableSignal/Broadcast.
In the wake of commit aced5a92b, the semantics of these results are
a bit squishy: we can tell whether we signaled some other process(es),
but we do not know which ones were real waiters versus mere sentinels
for ConditionVariableBroadcast operations. It does not help much that
ConditionVariableBroadcast will attempt to pass on the signal to the
next real waiter, because (a) there might not be one, and (b) that will
only happen awhile later, anyway. So these results could overstate how
much effect the calls really had.
However, no existing caller of either function pays any attention to its
result value, so it seems reasonable to just define that as a required
property of a correct algorithm. To encourage correctness and save some
tiny number of cycles, change both functions to return void.
Patch by me, per an observation by Thomas Munro. No back-patch, since
if any third parties happen to be using these functions, they might not
appreciate an API break in a minor release.
Discussion: https://postgr.es/m/CAEepm=0NWKehYw7NDoUSf8juuKOPRnCyY3vuaSvhrEWsOTAa3w@mail.gmail.com
2018-01-05 20:33:26 -05:00
|
|
|
extern void ConditionVariableSignal(ConditionVariable *cv);
|
|
|
|
|
extern void ConditionVariableBroadcast(ConditionVariable *cv);
|
2016-11-22 14:26:40 -05:00
|
|
|
|
Phase 2 of pgindent updates.
Change pg_bsd_indent to follow upstream rules for placement of comments
to the right of code, and remove pgindent hack that caused comments
following #endif to not obey the general rule.
Commit e3860ffa4dd0dad0dd9eea4be9cc1412373a8c89 wasn't actually using
the published version of pg_bsd_indent, but a hacked-up version that
tried to minimize the amount of movement of comments to the right of
code. The situation of interest is where such a comment has to be
moved to the right of its default placement at column 33 because there's
code there. BSD indent has always moved right in units of tab stops
in such cases --- but in the previous incarnation, indent was working
in 8-space tab stops, while now it knows we use 4-space tabs. So the
net result is that in about half the cases, such comments are placed
one tab stop left of before. This is better all around: it leaves
more room on the line for comment text, and it means that in such
cases the comment uniformly starts at the next 4-space tab stop after
the code, rather than sometimes one and sometimes two tabs after.
Also, ensure that comments following #endif are indented the same
as comments following other preprocessor commands such as #else.
That inconsistency turns out to have been self-inflicted damage
from a poorly-thought-through post-indent "fixup" in pgindent.
This patch is much less interesting than the first round of indent
changes, but also bulkier, so I thought it best to separate the effects.
Discussion: https://postgr.es/m/E1dAmxK-0006EE-1r@gemulon.postgresql.org
Discussion: https://postgr.es/m/30527.1495162840@sss.pgh.pa.us
2017-06-21 15:18:54 -04:00
|
|
|
#endif /* CONDITION_VARIABLE_H */
|