19
19
#include "postgres.h"
20
20
21
21
#include "miscadmin.h"
22
+ #include "portability/instr_time.h"
22
23
#include "storage/condition_variable.h"
23
24
#include "storage/ipc.h"
24
25
#include "storage/proc.h"
@@ -122,8 +123,24 @@ ConditionVariablePrepareToSleep(ConditionVariable *cv)
122
123
void
123
124
ConditionVariableSleep (ConditionVariable * cv , uint32 wait_event_info )
124
125
{
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 ;
127
144
128
145
/*
129
146
* 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)
143
160
if (cv_sleep_target != cv )
144
161
{
145
162
ConditionVariablePrepareToSleep (cv );
146
- return ;
163
+ return false ;
147
164
}
148
165
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 )
150
171
{
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;
152
181
153
182
/*
154
183
* Wait for latch to be set. (If we're awakened for some other
155
184
* reason, the code below will cope anyway.)
156
185
*/
157
- (void ) WaitEventSetWait (cv_wait_event_set , -1 , & event , 1 ,
186
+ (void ) WaitEventSetWait (cv_wait_event_set , cur_timeout , & event , 1 ,
158
187
wait_event_info );
159
188
160
189
/* Reset latch before examining the state of the wait list. */
161
190
ResetLatch (MyLatch );
162
191
192
+ CHECK_FOR_INTERRUPTS ();
193
+
163
194
/*
164
195
* If this process has been taken out of the wait list, then we know
165
196
* that it has been signaled by ConditionVariableSignal (or
@@ -182,7 +213,23 @@ ConditionVariableSleep(ConditionVariable *cv, uint32 wait_event_info)
182
213
proclist_push_tail (& cv -> wakeup , MyProc -> pgprocno , cvWaitLink );
183
214
}
184
215
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
+ }
186
233
}
187
234
188
235
/*
0 commit comments