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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy