@@ -724,6 +724,7 @@ typedef struct XLogCtlData
724724 TimestampTz currentChunkStartTime ;
725725 /* Recovery pause state */
726726 RecoveryPauseState recoveryPauseState ;
727+ ConditionVariable recoveryNotPausedCV ;
727728
728729 /*
729730 * lastFpwDisableRecPtr points to the start of the last replayed
@@ -5228,6 +5229,7 @@ XLOGShmemInit(void)
52285229 SpinLockInit (& XLogCtl -> info_lck );
52295230 SpinLockInit (& XLogCtl -> ulsn_lck );
52305231 InitSharedLatch (& XLogCtl -> recoveryWakeupLatch );
5232+ ConditionVariableInit (& XLogCtl -> recoveryNotPausedCV );
52315233}
52325234
52335235/*
@@ -6040,10 +6042,6 @@ recoveryStopsAfter(XLogReaderState *record)
60406042 * endOfRecovery is true if the recovery target is reached and
60416043 * the paused state starts at the end of recovery because of
60426044 * 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.
60476045 */
60486046static void
60496047recoveryPausesHere (bool endOfRecovery )
@@ -6071,17 +6069,22 @@ recoveryPausesHere(bool endOfRecovery)
60716069 HandleStartupProcInterrupts ();
60726070 if (CheckForStandbyTrigger ())
60736071 return ;
6074- pgstat_report_wait_start (WAIT_EVENT_RECOVERY_PAUSE );
60756072
60766073 /*
60776074 * If recovery pause is requested then set it paused. While we are in
60786075 * the loop, user might resume and pause again so set this every time.
60796076 */
60806077 ConfirmRecoveryPaused ();
60816078
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 );
60846086 }
6087+ ConditionVariableCancelSleep ();
60856088}
60866089
60876090/*
@@ -6118,6 +6121,9 @@ SetRecoveryPause(bool recoveryPause)
61186121 XLogCtl -> recoveryPauseState = RECOVERY_PAUSE_REQUESTED ;
61196122
61206123 SpinLockRelease (& XLogCtl -> info_lck );
6124+
6125+ if (!recoveryPause )
6126+ ConditionVariableBroadcast (& XLogCtl -> recoveryNotPausedCV );
61216127}
61226128
61236129/*
@@ -6357,10 +6363,15 @@ RecoveryRequiresIntParameter(const char *param_name, int currValue, int minValue
63576363 */
63586364 ConfirmRecoveryPaused ();
63596365
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 );
63636373 }
6374+ ConditionVariableCancelSleep ();
63646375 }
63656376
63666377 ereport (FATAL ,
0 commit comments