WalSndWaitForWal(XLogRecPtr loc)
{
	int			wakeEvents;
	static XLogRecPtr RecentFlushPtr = InvalidXLogRecPtr;


	/*
	 * Fast path to avoid acquiring the spinlock in the we already know we
	 * have enough WAL available. This is particularly interesting if we're
	 * far behind.
	 */
	if (RecentFlushPtr != InvalidXLogRecPtr &&
		loc <= RecentFlushPtr)
		return RecentFlushPtr;

	/* Get a more recent flush pointer. */
	if (!RecoveryInProgress())
		RecentFlushPtr = GetFlushRecPtr();
	else
		RecentFlushPtr = GetXLogReplayRecPtr(NULL);

	for (;;)
	{
		long		sleeptime;
		TimestampTz now;

		/*
		 * Emergency bailout if postmaster has died.  This is to avoid the
		 * necessity for manual cleanup of all postmaster children.
		 */
		if (!PostmasterIsAlive())
			exit(1);

		/* Clear any already-pending wakeups */
		ResetLatch(MyLatch);

		CHECK_FOR_INTERRUPTS();

		/* Process any requests or signals received recently */
		if (got_SIGHUP)
		{
			got_SIGHUP = false;
			ProcessConfigFile(PGC_SIGHUP);
			SyncRepInitConfig();
		}

		/* Check for input from the client */
		ProcessRepliesIfAny();

		/* Update our idea of the currently flushed position. */
		if (!RecoveryInProgress())
			RecentFlushPtr = GetFlushRecPtr();
		else
			RecentFlushPtr = GetXLogReplayRecPtr(NULL);

		/*
		 * If postmaster asked us to stop, don't wait here anymore. This will
		 * cause the xlogreader to return without reading a full record, which
		 * is the fastest way to reach the mainloop which then can quit.
		 *
		 * It's important to do this check after the recomputation of
		 * RecentFlushPtr, so we can send all remaining data before shutting
		 * down.
		 */
		if (walsender_ready_to_stop)
			break;

		/*
		 * We only send regular messages to the client for full decoded
		 * transactions, but a synchronous replication and walsender shutdown
		 * possibly are waiting for a later location. So we send pings
		 * containing the flush location every now and then.
		 */
		if (MyWalSnd->flush < sentPtr &&
			MyWalSnd->write < sentPtr &&
			!waiting_for_ping_response)
		{
			WalSndKeepalive(false);
			waiting_for_ping_response = true;
		}

		/* check whether we're done */
		if (loc <= RecentFlushPtr)
			break;

		/* Waiting for new WAL. Since we need to wait, we're now caught up. */
		WalSndCaughtUp = true;

		/*
		 * Try to flush pending output to the client. Also wait for the socket
		 * becoming writable, if there's still pending output after an attempt
		 * to flush. Otherwise we might just sit on output data while waiting
		 * for new WAL being generated.
		 */
		if (pq_flush_if_writable() != 0)
			WalSndShutdown();

		now = GetCurrentTimestamp();

		/* die if timeout was reached */
		WalSndCheckTimeOut(now);

		/* Send keepalive if the time has come */
		WalSndKeepaliveIfNecessary(now);

		sleeptime = WalSndComputeSleeptime(now);

		wakeEvents = WL_LATCH_SET | WL_POSTMASTER_DEATH |
			WL_SOCKET_READABLE | WL_TIMEOUT;

		if (pq_is_send_pending())
			wakeEvents |= WL_SOCKET_WRITEABLE;

		/* Sleep until something happens or we time out */
		WaitLatchOrSocket(MyLatch, wakeEvents,
						  MyProcPort->sock, sleeptime);
	}

	/* reactivate latch so WalSndLoop knows to continue */
	SetLatch(MyLatch);
	return RecentFlushPtr;
}