Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit13db3b9

Browse files
committed
Allow ConditionVariable[PrepareTo]Sleep to auto-switch between CVs.
The original coding here insisted that callers manually cancel any preparedsleep for one condition variable before starting a sleep on another one.While that's not a huge burden today, it seems like a gotcha that will biteus in future if the use of condition variables increases; anything we cando to make the use of this API simpler and more robust is attractive.Hence, allow these functions to automatically switch their attention toa different CV when required. This is safe for the same reason it was OKfor commitaced5a9 to let a broadcast operation cancel any prepared CVsleep: whenever we return to the other test-and-sleep loop, we willautomatically re-prepare that CV, paying at most an extra test of thatloop's exit condition.Back-patch to v10 where condition variables were introduced. Ordinarilywe would probably not back-patch a change like this, but since it does notinvalidate any coding pattern that was legal before, it seems safe enough.Furthermore, there's an open bug in replorigin_drop() for which thesimplest fix requires this. Even if we chose to fix that in some morecomplicated way, the hazard would remain that we might back-patch someother bug fix that requires this behavior.Patch by me, reviewed by Thomas Munro.Discussion:https://postgr.es/m/2437.1515368316@sss.pgh.pa.us
1 parent921059b commit13db3b9

File tree

2 files changed

+15
-15
lines changed

2 files changed

+15
-15
lines changed

‎src/backend/storage/lmgr/condition_variable.c

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,6 @@ ConditionVariableInit(ConditionVariable *cv)
5555
* condition between calling ConditionVariablePrepareToSleep and calling
5656
* ConditionVariableSleep. If that is inconvenient, omit calling
5757
* ConditionVariablePrepareToSleep.
58-
*
59-
* Only one condition variable can be used at a time, ie,
60-
* ConditionVariableCancelSleep must be called before any attempt is made
61-
* to sleep on a different condition variable.
6258
*/
6359
void
6460
ConditionVariablePrepareToSleep(ConditionVariable*cv)
@@ -81,10 +77,15 @@ ConditionVariablePrepareToSleep(ConditionVariable *cv)
8177
}
8278

8379
/*
84-
* It's not legal to prepare a sleep until the previous sleep has been
85-
* completed or canceled.
80+
* If some other sleep is already prepared, cancel it; this is necessary
81+
* because we have just one static variable tracking the prepared sleep,
82+
* and also only one cvWaitLink in our PGPROC. It's okay to do this
83+
* because whenever control does return to the other test-and-sleep loop,
84+
* its ConditionVariableSleep call will just re-establish that sleep as
85+
* the prepared one.
8686
*/
87-
Assert(cv_sleep_target==NULL);
87+
if (cv_sleep_target!=NULL)
88+
ConditionVariableCancelSleep();
8889

8990
/* Record the condition variable on which we will sleep. */
9091
cv_sleep_target=cv;
@@ -133,16 +134,16 @@ ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info)
133134
* is recommended because it avoids manipulations of the wait list, or not
134135
* met initially, in which case preparing first is better because it
135136
* avoids one extra test of the exit condition.
137+
*
138+
* If we are currently prepared to sleep on some other CV, we just cancel
139+
* that and prepare this one; see ConditionVariablePrepareToSleep.
136140
*/
137-
if (cv_sleep_target==NULL)
141+
if (cv_sleep_target!=cv)
138142
{
139143
ConditionVariablePrepareToSleep(cv);
140144
return;
141145
}
142146

143-
/* Any earlier condition variable sleep must have been canceled. */
144-
Assert(cv_sleep_target==cv);
145-
146147
do
147148
{
148149
CHECK_FOR_INTERRUPTS();
@@ -265,7 +266,8 @@ ConditionVariableBroadcast(ConditionVariable *cv)
265266
* prepared CV sleep. The next call to ConditionVariableSleep will take
266267
* care of re-establishing the lost state.
267268
*/
268-
ConditionVariableCancelSleep();
269+
if (cv_sleep_target!=NULL)
270+
ConditionVariableCancelSleep();
269271

270272
/*
271273
* Inspect the state of the queue. If it's empty, we have nothing to do.

‎src/include/storage/condition_variable.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,7 @@ extern void ConditionVariableInit(ConditionVariable *cv);
4040
* ConditionVariableSleep. Spurious wakeups are possible, but should be
4141
* infrequent. After exiting the loop, ConditionVariableCancelSleep must
4242
* be called to ensure that the process is no longer in the wait list for
43-
* the condition variable. Only one condition variable can be used at a
44-
* time, ie, ConditionVariableCancelSleep must be called before any attempt
45-
* is made to sleep on a different condition variable.
43+
* the condition variable.
4644
*/
4745
externvoidConditionVariableSleep(ConditionVariable*cv,uint32wait_event_info);
4846
externvoidConditionVariableCancelSleep(void);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp