PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
condition_variable.c File Reference
#include "postgres.h"
#include "miscadmin.h"
#include "storage/condition_variable.h"
#include "storage/ipc.h"
#include "storage/proc.h"
#include "storage/proclist.h"
#include "storage/spin.h"
#include "utils/memutils.h"
Include dependency graph for condition_variable.c:

Go to the source code of this file.

Functions

void ConditionVariableInit (ConditionVariable *cv)
 
void ConditionVariablePrepareToSleep (ConditionVariable *cv)
 
void ConditionVariableSleep (ConditionVariable *cv, uint32 wait_event_info)
 
void ConditionVariableCancelSleep (void)
 
bool ConditionVariableSignal (ConditionVariable *cv)
 
int ConditionVariableBroadcast (ConditionVariable *cv)
 

Variables

static ConditionVariablecv_sleep_target = NULL
 
static WaitEventSetcv_wait_event_set = NULL
 

Function Documentation

int ConditionVariableBroadcast ( ConditionVariable cv)

Definition at line 214 of file condition_variable.c.

References ConditionVariableSignal().

Referenced by _bt_parallel_done(), BitmapDoneInitializingSharedState(), ReplicationOriginExitCleanup(), ReplicationSlotAcquire(), ReplicationSlotCleanup(), ReplicationSlotCreate(), ReplicationSlotDropPtr(), ReplicationSlotRelease(), replorigin_session_reset(), and replorigin_session_setup().

215 {
216  int nwoken = 0;
217 
218  /*
219  * Let's just do this the dumbest way possible. We could try to dequeue
220  * all the sleepers at once to save spinlock cycles, but it's a bit hard
221  * to get that right in the face of possible sleep cancelations, and we
222  * don't want to loop holding the mutex.
223  */
224  while (ConditionVariableSignal(cv))
225  ++nwoken;
226 
227  return nwoken;
228 }
bool ConditionVariableSignal(ConditionVariable *cv)
void ConditionVariableCancelSleep ( void  )

Definition at line 166 of file condition_variable.c.

References cv_sleep_target, ConditionVariable::mutex, MyProc, PGPROC::pgprocno, proclist_contains, proclist_delete, SpinLockAcquire, SpinLockRelease, and ConditionVariable::wakeup.

Referenced by _bt_parallel_seize(), AbortTransaction(), AuxiliaryProcKill(), BackgroundWriterMain(), BitmapShouldInitializeSharedState(), CheckpointerMain(), ProcKill(), ReplicationSlotAcquire(), replorigin_drop(), ShutdownAuxiliaryProcess(), WalSndErrorCleanup(), and WalWriterMain().

167 {
169 
170  if (cv == NULL)
171  return;
172 
173  SpinLockAcquire(&cv->mutex);
174  if (proclist_contains(&cv->wakeup, MyProc->pgprocno, cvWaitLink))
175  proclist_delete(&cv->wakeup, MyProc->pgprocno, cvWaitLink);
176  SpinLockRelease(&cv->mutex);
177 
178  cv_sleep_target = NULL;
179 }
proclist_head wakeup
PGPROC * MyProc
Definition: proc.c:67
#define proclist_delete(list, procno, link_member)
Definition: proclist.h:176
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define SpinLockRelease(lock)
Definition: spin.h:64
static ConditionVariable * cv_sleep_target
int pgprocno
Definition: proc.h:110
#define proclist_contains(list, procno, link_member)
Definition: proclist.h:184
void ConditionVariableInit ( ConditionVariable cv)

Definition at line 39 of file condition_variable.c.

References ConditionVariable::mutex, proclist_init(), SpinLockInit, and ConditionVariable::wakeup.

Referenced by btinitparallelscan(), ExecBitmapHeapInitializeDSM(), ReplicationOriginShmemInit(), and ReplicationSlotsShmemInit().

40 {
41  SpinLockInit(&cv->mutex);
42  proclist_init(&cv->wakeup);
43 }
proclist_head wakeup
#define SpinLockInit(lock)
Definition: spin.h:60
static void proclist_init(proclist_head *list)
Definition: proclist.h:29
void ConditionVariablePrepareToSleep ( ConditionVariable cv)

Definition at line 53 of file condition_variable.c.

References AddWaitEventToSet(), Assert, CreateWaitEventSet(), ConditionVariable::mutex, MyLatch, MyProc, PGINVALID_SOCKET, PGPROC::pgprocno, proclist_contains, proclist_push_tail, ResetLatch(), SpinLockAcquire, SpinLockRelease, TopMemoryContext, ConditionVariable::wakeup, and WL_LATCH_SET.

Referenced by ConditionVariableSleep(), ReplicationSlotAcquire(), and replorigin_drop().

54 {
55  int pgprocno = MyProc->pgprocno;
56 
57  /*
58  * It's not legal to prepare a sleep until the previous sleep has been
59  * completed or canceled.
60  */
61  Assert(cv_sleep_target == NULL);
62 
63  /* Record the condition variable on which we will sleep. */
64  cv_sleep_target = cv;
65 
66  /* Create a reusable WaitEventSet. */
67  if (cv_wait_event_set == NULL)
68  {
71  MyLatch, NULL);
72  }
73 
74  /*
75  * Reset my latch before adding myself to the queue and before entering
76  * the caller's predicate loop.
77  */
79 
80  /* Add myself to the wait queue. */
81  SpinLockAcquire(&cv->mutex);
82  if (!proclist_contains(&cv->wakeup, pgprocno, cvWaitLink))
83  proclist_push_tail(&cv->wakeup, pgprocno, cvWaitLink);
84  SpinLockRelease(&cv->mutex);
85 }
int AddWaitEventToSet(WaitEventSet *set, uint32 events, pgsocket fd, Latch *latch, void *user_data)
Definition: latch.c:666
proclist_head wakeup
PGPROC * MyProc
Definition: proc.c:67
static WaitEventSet * cv_wait_event_set
void ResetLatch(volatile Latch *latch)
Definition: latch.c:497
WaitEventSet * CreateWaitEventSet(MemoryContext context, int nevents)
Definition: latch.c:520
#define SpinLockAcquire(lock)
Definition: spin.h:62
MemoryContext TopMemoryContext
Definition: mcxt.c:43
#define SpinLockRelease(lock)
Definition: spin.h:64
#define PGINVALID_SOCKET
Definition: port.h:24
static ConditionVariable * cv_sleep_target
#define Assert(condition)
Definition: c.h:681
#define proclist_push_tail(list, procno, link_member)
Definition: proclist.h:180
int pgprocno
Definition: proc.h:110
struct Latch * MyLatch
Definition: globals.c:52
#define WL_LATCH_SET
Definition: latch.h:124
#define proclist_contains(list, procno, link_member)
Definition: proclist.h:184
bool ConditionVariableSignal ( ConditionVariable cv)

Definition at line 187 of file condition_variable.c.

References ConditionVariable::mutex, PGPROC::procLatch, proclist_is_empty(), proclist_pop_head_node, SetLatch(), SpinLockAcquire, SpinLockRelease, and ConditionVariable::wakeup.

Referenced by _bt_parallel_release(), and ConditionVariableBroadcast().

188 {
189  PGPROC *proc = NULL;
190 
191  /* Remove the first process from the wakeup queue (if any). */
192  SpinLockAcquire(&cv->mutex);
193  if (!proclist_is_empty(&cv->wakeup))
194  proc = proclist_pop_head_node(&cv->wakeup, cvWaitLink);
195  SpinLockRelease(&cv->mutex);
196 
197  /* If we found someone sleeping, set their latch to wake them up. */
198  if (proc != NULL)
199  {
200  SetLatch(&proc->procLatch);
201  return true;
202  }
203 
204  /* No sleeping processes. */
205  return false;
206 }
proclist_head wakeup
Latch procLatch
Definition: proc.h:104
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define SpinLockRelease(lock)
Definition: spin.h:64
#define proclist_pop_head_node(list, link_member)
Definition: proclist.h:182
void SetLatch(volatile Latch *latch)
Definition: latch.c:414
static bool proclist_is_empty(proclist_head *list)
Definition: proclist.h:38
Definition: proc.h:95
void ConditionVariableSleep ( ConditionVariable cv,
uint32  wait_event_info 
)

Definition at line 102 of file condition_variable.c.

References Assert, CHECK_FOR_INTERRUPTS, ConditionVariablePrepareToSleep(), ConditionVariable::mutex, MyLatch, MyProc, PGPROC::pgprocno, proclist_contains, proclist_push_tail, ResetLatch(), SpinLockAcquire, SpinLockRelease, WaitEventSetWait(), and ConditionVariable::wakeup.

Referenced by _bt_parallel_seize(), BitmapShouldInitializeSharedState(), ReplicationSlotAcquire(), and replorigin_drop().

103 {
104  WaitEvent event;
105  bool done = false;
106 
107  /*
108  * If the caller didn't prepare to sleep explicitly, then do so now and
109  * return immediately. The caller's predicate loop should immediately
110  * call again if its exit condition is not yet met. This initial spurious
111  * return can be avoided by calling ConditionVariablePrepareToSleep(cv)
112  * first. Whether it's worth doing that depends on whether you expect the
113  * condition to be met initially, in which case skipping the prepare
114  * allows you to skip manipulation of the wait list, or not met initially,
115  * in which case preparing first allows you to skip a spurious test of the
116  * caller's exit condition.
117  */
118  if (cv_sleep_target == NULL)
119  {
121  return;
122  }
123 
124  /* Any earlier condition variable sleep must have been canceled. */
125  Assert(cv_sleep_target == cv);
126 
127  while (!done)
128  {
130 
131  /*
132  * Wait for latch to be set. We don't care about the result because
133  * our contract permits spurious returns.
134  */
135  WaitEventSetWait(cv_wait_event_set, -1, &event, 1, wait_event_info);
136 
137  /* Reset latch before testing whether we can return. */
139 
140  /*
141  * If this process has been taken out of the wait list, then we know
142  * that is has been signaled by ConditionVariableSignal. We put it
143  * back into the wait list, so we don't miss any further signals while
144  * the caller's loop checks its condition. If it hasn't been taken
145  * out of the wait list, then the latch must have been set by
146  * something other than ConditionVariableSignal; though we don't
147  * guarantee not to return spuriously, we'll avoid these obvious
148  * cases.
149  */
150  SpinLockAcquire(&cv->mutex);
151  if (!proclist_contains(&cv->wakeup, MyProc->pgprocno, cvWaitLink))
152  {
153  done = true;
154  proclist_push_tail(&cv->wakeup, MyProc->pgprocno, cvWaitLink);
155  }
156  SpinLockRelease(&cv->mutex);
157  }
158 }
proclist_head wakeup
PGPROC * MyProc
Definition: proc.c:67
static WaitEventSet * cv_wait_event_set
void ResetLatch(volatile Latch *latch)
Definition: latch.c:497
void ConditionVariablePrepareToSleep(ConditionVariable *cv)
#define SpinLockAcquire(lock)
Definition: spin.h:62
#define SpinLockRelease(lock)
Definition: spin.h:64
static ConditionVariable * cv_sleep_target
#define Assert(condition)
Definition: c.h:681
#define proclist_push_tail(list, procno, link_member)
Definition: proclist.h:180
int pgprocno
Definition: proc.h:110
struct Latch * MyLatch
Definition: globals.c:52
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
int WaitEventSetWait(WaitEventSet *set, long timeout, WaitEvent *occurred_events, int nevents, uint32 wait_event_info)
Definition: latch.c:921
#define proclist_contains(list, procno, link_member)
Definition: proclist.h:184

Variable Documentation

ConditionVariable* cv_sleep_target = NULL
static

Definition at line 30 of file condition_variable.c.

Referenced by ConditionVariableCancelSleep().

WaitEventSet* cv_wait_event_set = NULL
static

Definition at line 33 of file condition_variable.c.