Forward received condition variable signals on cancel.
After a process decides not to wait for a condition variable, it can still consume a signal before it reaches ConditionVariableCancelSleep(). In that case, pass the signal on to another waiter if possible, so that a signal doesn't go missing when there is another process ready to receive it. Author: Thomas Munro Reviewed-by: Shawn Debnath Discussion: https://postgr.es/m/CA%2BhUKGLQ_RW%2BXs8znDn36e-%2Bmq2--zrPemBqTQ8eKT-VO1OF4Q%40mail.gmail.com
This commit is contained in:
parent
1321509fa4
commit
b91dd9de5e
@ -245,6 +245,7 @@ void
|
|||||||
ConditionVariableCancelSleep(void)
|
ConditionVariableCancelSleep(void)
|
||||||
{
|
{
|
||||||
ConditionVariable *cv = cv_sleep_target;
|
ConditionVariable *cv = cv_sleep_target;
|
||||||
|
bool signaled = false;
|
||||||
|
|
||||||
if (cv == NULL)
|
if (cv == NULL)
|
||||||
return;
|
return;
|
||||||
@ -252,8 +253,18 @@ ConditionVariableCancelSleep(void)
|
|||||||
SpinLockAcquire(&cv->mutex);
|
SpinLockAcquire(&cv->mutex);
|
||||||
if (proclist_contains(&cv->wakeup, MyProc->pgprocno, cvWaitLink))
|
if (proclist_contains(&cv->wakeup, MyProc->pgprocno, cvWaitLink))
|
||||||
proclist_delete(&cv->wakeup, MyProc->pgprocno, cvWaitLink);
|
proclist_delete(&cv->wakeup, MyProc->pgprocno, cvWaitLink);
|
||||||
|
else
|
||||||
|
signaled = true;
|
||||||
SpinLockRelease(&cv->mutex);
|
SpinLockRelease(&cv->mutex);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If we've received a signal, pass it on to another waiting process, if
|
||||||
|
* there is one. Otherwise a call to ConditionVariableSignal() might get
|
||||||
|
* lost, despite there being another process ready to handle it.
|
||||||
|
*/
|
||||||
|
if (signaled)
|
||||||
|
ConditionVariableSignal(cv);
|
||||||
|
|
||||||
cv_sleep_target = NULL;
|
cv_sleep_target = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user