PostgreSQL Source Code  git master
barrier.c File Reference
#include "postgres.h"
#include "storage/barrier.h"
Include dependency graph for barrier.c:

Go to the source code of this file.

Functions

static bool BarrierDetachImpl (Barrier *barrier, bool arrive)
 
void BarrierInit (Barrier *barrier, int participants)
 
bool BarrierArriveAndWait (Barrier *barrier, uint32 wait_event_info)
 
bool BarrierArriveAndDetach (Barrier *barrier)
 
bool BarrierArriveAndDetachExceptLast (Barrier *barrier)
 
int BarrierAttach (Barrier *barrier)
 
bool BarrierDetach (Barrier *barrier)
 
int BarrierPhase (Barrier *barrier)
 
int BarrierParticipants (Barrier *barrier)
 

Function Documentation

◆ BarrierArriveAndDetach()

bool BarrierArriveAndDetach ( Barrier barrier)

Definition at line 203 of file barrier.c.

204 {
205  return BarrierDetachImpl(barrier, true);
206 }
static bool BarrierDetachImpl(Barrier *barrier, bool arrive)
Definition: barrier.c:300
static THREAD_BARRIER_T barrier
Definition: pgbench.c:480

References barrier, and BarrierDetachImpl().

Referenced by ExecHashTableDetach(), and ExecHashTableDetachBatch().

◆ BarrierArriveAndDetachExceptLast()

bool BarrierArriveAndDetachExceptLast ( Barrier barrier)

Definition at line 213 of file barrier.c.

214 {
215  SpinLockAcquire(&barrier->mutex);
216  if (barrier->participants > 1)
217  {
218  --barrier->participants;
219  SpinLockRelease(&barrier->mutex);
220 
221  return false;
222  }
223  Assert(barrier->participants == 1);
224  ++barrier->phase;
225  SpinLockRelease(&barrier->mutex);
226 
227  return true;
228 }
#define Assert(condition)
Definition: c.h:849
#define SpinLockRelease(lock)
Definition: spin.h:61
#define SpinLockAcquire(lock)
Definition: spin.h:59

References Assert, barrier, SpinLockAcquire, and SpinLockRelease.

Referenced by ExecHashTableDetachBatch(), and ExecParallelPrepHashTableForUnmatched().

◆ BarrierArriveAndWait()

bool BarrierArriveAndWait ( Barrier barrier,
uint32  wait_event_info 
)

Definition at line 125 of file barrier.c.

126 {
127  bool release = false;
128  bool elected;
129  int start_phase;
130  int next_phase;
131 
132  SpinLockAcquire(&barrier->mutex);
133  start_phase = barrier->phase;
134  next_phase = start_phase + 1;
135  ++barrier->arrived;
136  if (barrier->arrived == barrier->participants)
137  {
138  release = true;
139  barrier->arrived = 0;
140  barrier->phase = next_phase;
141  barrier->elected = next_phase;
142  }
143  SpinLockRelease(&barrier->mutex);
144 
145  /*
146  * If we were the last expected participant to arrive, we can release our
147  * peers and return true to indicate that this backend has been elected to
148  * perform any serial work.
149  */
150  if (release)
151  {
152  ConditionVariableBroadcast(&barrier->condition_variable);
153 
154  return true;
155  }
156 
157  /*
158  * Otherwise we have to wait for the last participant to arrive and
159  * advance the phase.
160  */
161  elected = false;
162  ConditionVariablePrepareToSleep(&barrier->condition_variable);
163  for (;;)
164  {
165  /*
166  * We know that phase must either be start_phase, indicating that we
167  * need to keep waiting, or next_phase, indicating that the last
168  * participant that we were waiting for has either arrived or detached
169  * so that the next phase has begun. The phase cannot advance any
170  * further than that without this backend's participation, because
171  * this backend is attached.
172  */
173  SpinLockAcquire(&barrier->mutex);
174  Assert(barrier->phase == start_phase || barrier->phase == next_phase);
175  release = barrier->phase == next_phase;
176  if (release && barrier->elected != next_phase)
177  {
178  /*
179  * Usually the backend that arrives last and releases the other
180  * backends is elected to return true (see above), so that it can
181  * begin processing serial work while it has a CPU timeslice.
182  * However, if the barrier advanced because someone detached, then
183  * one of the backends that is awoken will need to be elected.
184  */
185  barrier->elected = barrier->phase;
186  elected = true;
187  }
188  SpinLockRelease(&barrier->mutex);
189  if (release)
190  break;
191  ConditionVariableSleep(&barrier->condition_variable, wait_event_info);
192  }
194 
195  return elected;
196 }
bool ConditionVariableCancelSleep(void)
void ConditionVariableBroadcast(ConditionVariable *cv)
void ConditionVariablePrepareToSleep(ConditionVariable *cv)
void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info)

References Assert, barrier, ConditionVariableBroadcast(), ConditionVariableCancelSleep(), ConditionVariablePrepareToSleep(), ConditionVariableSleep(), SpinLockAcquire, and SpinLockRelease.

Referenced by ExecHashJoinImpl(), ExecHashTableCreate(), ExecParallelHashIncreaseNumBatches(), ExecParallelHashIncreaseNumBuckets(), ExecParallelHashJoinNewBatch(), ExecParallelHashJoinSetUpBatches(), and MultiExecParallelHash().

◆ BarrierAttach()

int BarrierAttach ( Barrier barrier)

Definition at line 236 of file barrier.c.

237 {
238  int phase;
239 
240  Assert(!barrier->static_party);
241 
242  SpinLockAcquire(&barrier->mutex);
243  ++barrier->participants;
244  phase = barrier->phase;
245  SpinLockRelease(&barrier->mutex);
246 
247  return phase;
248 }

References Assert, barrier, SpinLockAcquire, and SpinLockRelease.

Referenced by ExecHashTableCreate(), ExecParallelHashJoinNewBatch(), ExecParallelHashJoinSetUpBatches(), and MultiExecParallelHash().

◆ BarrierDetach()

bool BarrierDetach ( Barrier barrier)

Definition at line 256 of file barrier.c.

257 {
258  return BarrierDetachImpl(barrier, false);
259 }

References barrier, and BarrierDetachImpl().

Referenced by ExecParallelHashJoinNewBatch(), ExecParallelHashJoinSetUpBatches(), and MultiExecParallelHash().

◆ BarrierDetachImpl()

static bool BarrierDetachImpl ( Barrier barrier,
bool  arrive 
)
inlinestatic

Definition at line 300 of file barrier.c.

301 {
302  bool release;
303  bool last;
304 
305  Assert(!barrier->static_party);
306 
307  SpinLockAcquire(&barrier->mutex);
308  Assert(barrier->participants > 0);
309  --barrier->participants;
310 
311  /*
312  * If any other participants are waiting and we were the last participant
313  * waited for, release them. If no other participants are waiting, but
314  * this is a BarrierArriveAndDetach() call, then advance the phase too.
315  */
316  if ((arrive || barrier->participants > 0) &&
317  barrier->arrived == barrier->participants)
318  {
319  release = true;
320  barrier->arrived = 0;
321  ++barrier->phase;
322  }
323  else
324  release = false;
325 
326  last = barrier->participants == 0;
327  SpinLockRelease(&barrier->mutex);
328 
329  if (release)
330  ConditionVariableBroadcast(&barrier->condition_variable);
331 
332  return last;
333 }

References Assert, barrier, ConditionVariableBroadcast(), SpinLockAcquire, and SpinLockRelease.

Referenced by BarrierArriveAndDetach(), and BarrierDetach().

◆ BarrierInit()

void BarrierInit ( Barrier barrier,
int  participants 
)

Definition at line 100 of file barrier.c.

101 {
102  SpinLockInit(&barrier->mutex);
103  barrier->participants = participants;
104  barrier->arrived = 0;
105  barrier->phase = 0;
106  barrier->elected = 0;
107  barrier->static_party = participants > 0;
108  ConditionVariableInit(&barrier->condition_variable);
109 }
void ConditionVariableInit(ConditionVariable *cv)
#define SpinLockInit(lock)
Definition: spin.h:57

References barrier, ConditionVariableInit(), and SpinLockInit.

Referenced by ExecHashJoinInitializeDSM(), ExecHashJoinReInitializeDSM(), and ExecParallelHashJoinSetUpBatches().

◆ BarrierParticipants()

int BarrierParticipants ( Barrier barrier)

Definition at line 281 of file barrier.c.

282 {
283  int participants;
284 
285  SpinLockAcquire(&barrier->mutex);
286  participants = barrier->participants;
287  SpinLockRelease(&barrier->mutex);
288 
289  return participants;
290 }

References barrier, SpinLockAcquire, and SpinLockRelease.

◆ BarrierPhase()

int BarrierPhase ( Barrier barrier)

Definition at line 265 of file barrier.c.

266 {
267  /*
268  * It is OK to read barrier->phase without locking, because it can't
269  * change without us (we are attached to it), and we executed a memory
270  * barrier when we either attached or participated in changing it last
271  * time.
272  */
273  return barrier->phase;
274 }

References barrier.

Referenced by ExecHashJoinImpl(), ExecHashTableCreate(), ExecHashTableDetach(), ExecHashTableDetachBatch(), ExecParallelHashIncreaseNumBatches(), ExecParallelHashIncreaseNumBuckets(), ExecParallelHashJoinNewBatch(), ExecParallelHashJoinSetUpBatches(), ExecParallelHashTableInsert(), ExecParallelHashTupleAlloc(), ExecParallelPrepHashTableForUnmatched(), and MultiExecParallelHash().