Skip to content

Commit 1321509

Browse files
committed
Introduce timed waits for condition variables.
Provide ConditionVariableTimedSleep(), like ConditionVariableSleep() but with a timeout argument. Author: Shawn Debnath Reviewed-by: Kyotaro Horiguchi, Thomas Munro Discussion: https://postgr.es/m/eeb06007ccfe46e399df6af18bfcd15a@EX13D05UWC002.ant.amazon.com
1 parent b31fbe8 commit 1321509

File tree

2 files changed

+56
-7
lines changed

2 files changed

+56
-7
lines changed

src/backend/storage/lmgr/condition_variable.c

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "postgres.h"
2020

2121
#include "miscadmin.h"
22+
#include "portability/instr_time.h"
2223
#include "storage/condition_variable.h"
2324
#include "storage/ipc.h"
2425
#include "storage/proc.h"
@@ -122,8 +123,24 @@ ConditionVariablePrepareToSleep(ConditionVariable *cv)
122123
void
123124
ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info)
124125
{
125-
WaitEvent event;
126-
bool done = false;
126+
(void) ConditionVariableTimedSleep(cv, -1 /* no timeout */ ,
127+
wait_event_info);
128+
}
129+
130+
/*
131+
* Wait for a condition variable to be signaled or a timeout to be reached.
132+
*
133+
* Returns true when timeout expires, otherwise returns false.
134+
*
135+
* See ConditionVariableSleep() for general usage.
136+
*/
137+
bool
138+
ConditionVariableTimedSleep(ConditionVariable *cv, long timeout,
139+
uint32 wait_event_info)
140+
{
141+
long cur_timeout = -1;
142+
instr_time start_time;
143+
instr_time cur_time;
127144

128145
/*
129146
* If the caller didn't prepare to sleep explicitly, then do so now and
@@ -143,23 +160,37 @@ ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info)
143160
if (cv_sleep_target != cv)
144161
{
145162
ConditionVariablePrepareToSleep(cv);
146-
return;
163+
return false;
147164
}
148165

149-
do
166+
/*
167+
* Record the current time so that we can calculate the remaining timeout
168+
* if we are woken up spuriously.
169+
*/
170+
if (timeout >= 0)
150171
{
151-
CHECK_FOR_INTERRUPTS();
172+
INSTR_TIME_SET_CURRENT(start_time);
173+
Assert(timeout >= 0 && timeout <= INT_MAX);
174+
cur_timeout = timeout;
175+
}
176+
177+
while (true)
178+
{
179+
WaitEvent event;
180+
bool done = false;
152181

153182
/*
154183
* Wait for latch to be set. (If we're awakened for some other
155184
* reason, the code below will cope anyway.)
156185
*/
157-
(void) WaitEventSetWait(cv_wait_event_set, -1, &event, 1,
186+
(void) WaitEventSetWait(cv_wait_event_set, cur_timeout, &event, 1,
158187
wait_event_info);
159188

160189
/* Reset latch before examining the state of the wait list. */
161190
ResetLatch(MyLatch);
162191

192+
CHECK_FOR_INTERRUPTS();
193+
163194
/*
164195
* If this process has been taken out of the wait list, then we know
165196
* that it has been signaled by ConditionVariableSignal (or
@@ -182,7 +213,23 @@ ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info)
182213
proclist_push_tail(&cv->wakeup, MyProc->pgprocno, cvWaitLink);
183214
}
184215
SpinLockRelease(&cv->mutex);
185-
} while (!done);
216+
217+
/* We were signaled, so return */
218+
if (done)
219+
return false;
220+
221+
/* If we're not done, update cur_timeout for next iteration */
222+
if (timeout >= 0)
223+
{
224+
INSTR_TIME_SET_CURRENT(cur_time);
225+
INSTR_TIME_SUBTRACT(cur_time, start_time);
226+
cur_timeout = timeout - (long) INSTR_TIME_GET_MILLISEC(cur_time);
227+
228+
/* Have we crossed the timeout threshold? */
229+
if (cur_timeout <= 0)
230+
return true;
231+
}
232+
}
186233
}
187234

188235
/*

src/include/storage/condition_variable.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ extern void ConditionVariableInit(ConditionVariable *cv);
4343
* the condition variable.
4444
*/
4545
extern void ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info);
46+
extern bool ConditionVariableTimedSleep(ConditionVariable *cv, long timeout,
47+
uint32 wait_event_info);
4648
extern void ConditionVariableCancelSleep(void);
4749

4850
/*

0 commit comments

Comments
 (0)