@@ -724,6 +724,7 @@ typedef struct XLogCtlData
724
724
TimestampTz currentChunkStartTime ;
725
725
/* Recovery pause state */
726
726
RecoveryPauseState recoveryPauseState ;
727
+ ConditionVariable recoveryNotPausedCV ;
727
728
728
729
/*
729
730
* lastFpwDisableRecPtr points to the start of the last replayed
@@ -5228,6 +5229,7 @@ XLOGShmemInit(void)
5228
5229
SpinLockInit (& XLogCtl -> info_lck );
5229
5230
SpinLockInit (& XLogCtl -> ulsn_lck );
5230
5231
InitSharedLatch (& XLogCtl -> recoveryWakeupLatch );
5232
+ ConditionVariableInit (& XLogCtl -> recoveryNotPausedCV );
5231
5233
}
5232
5234
5233
5235
/*
@@ -6040,10 +6042,6 @@ recoveryStopsAfter(XLogReaderState *record)
6040
6042
* endOfRecovery is true if the recovery target is reached and
6041
6043
* the paused state starts at the end of recovery because of
6042
6044
* recovery_target_action=pause, and false otherwise.
6043
- *
6044
- * XXX Could also be done with shared latch, avoiding the pg_usleep loop.
6045
- * Probably not worth the trouble though. This state shouldn't be one that
6046
- * anyone cares about server power consumption in.
6047
6045
*/
6048
6046
static void
6049
6047
recoveryPausesHere (bool endOfRecovery )
@@ -6071,17 +6069,22 @@ recoveryPausesHere(bool endOfRecovery)
6071
6069
HandleStartupProcInterrupts ();
6072
6070
if (CheckForStandbyTrigger ())
6073
6071
return ;
6074
- pgstat_report_wait_start (WAIT_EVENT_RECOVERY_PAUSE );
6075
6072
6076
6073
/*
6077
6074
* If recovery pause is requested then set it paused. While we are in
6078
6075
* the loop, user might resume and pause again so set this every time.
6079
6076
*/
6080
6077
ConfirmRecoveryPaused ();
6081
6078
6082
- pg_usleep (1000000L ); /* 1000 ms */
6083
- pgstat_report_wait_end ();
6079
+ /*
6080
+ * We wait on a condition variable that will wake us as soon as the
6081
+ * pause ends, but we use a timeout so we can check the above exit
6082
+ * condition periodically too.
6083
+ */
6084
+ ConditionVariableTimedSleep (& XLogCtl -> recoveryNotPausedCV , 1000 ,
6085
+ WAIT_EVENT_RECOVERY_PAUSE );
6084
6086
}
6087
+ ConditionVariableCancelSleep ();
6085
6088
}
6086
6089
6087
6090
/*
@@ -6118,6 +6121,9 @@ SetRecoveryPause(bool recoveryPause)
6118
6121
XLogCtl -> recoveryPauseState = RECOVERY_PAUSE_REQUESTED ;
6119
6122
6120
6123
SpinLockRelease (& XLogCtl -> info_lck );
6124
+
6125
+ if (!recoveryPause )
6126
+ ConditionVariableBroadcast (& XLogCtl -> recoveryNotPausedCV );
6121
6127
}
6122
6128
6123
6129
/*
@@ -6357,10 +6363,15 @@ RecoveryRequiresIntParameter(const char *param_name, int currValue, int minValue
6357
6363
*/
6358
6364
ConfirmRecoveryPaused ();
6359
6365
6360
- pgstat_report_wait_start (WAIT_EVENT_RECOVERY_PAUSE );
6361
- pg_usleep (1000000L ); /* 1000 ms */
6362
- pgstat_report_wait_end ();
6366
+ /*
6367
+ * We wait on a condition variable that will wake us as soon as
6368
+ * the pause ends, but we use a timeout so we can check the
6369
+ * above conditions periodically too.
6370
+ */
6371
+ ConditionVariableTimedSleep (& XLogCtl -> recoveryNotPausedCV , 1000 ,
6372
+ WAIT_EVENT_RECOVERY_PAUSE );
6363
6373
}
6374
+ ConditionVariableCancelSleep ();
6364
6375
}
6365
6376
6366
6377
ereport (FATAL ,
0 commit comments