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)
122123void
123124ConditionVariableSleep (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/*
0 commit comments